From 9cb37a122b0a58f0a41f192d717fc682765a5e1d Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 20 Nov 2019 09:44:12 +0100 Subject: [PATCH 01/29] Kibana app migration: Shim dashboard (#48913) --- .../dashboard/__tests__/get_app_state_mock.ts | 2 +- .../public/dashboard/_dashboard_app.scss | 2 +- .../kibana/public/dashboard/application.ts | 228 +++++ .../public/dashboard/dashboard_app.html | 20 +- .../kibana/public/dashboard/dashboard_app.tsx | 105 +- .../dashboard/dashboard_app_controller.tsx | 149 ++- .../public/dashboard/dashboard_state.test.ts | 10 +- .../dashboard/dashboard_state_manager.ts | 25 +- .../public/dashboard/global_state_sync.ts | 67 ++ .../public/dashboard/help_menu/help_menu.js | 34 +- .../dashboard/help_menu/help_menu_util.js | 6 +- .../kibana/public/dashboard/index.js | 207 ---- .../kibana/public/dashboard/index.ts | 69 ++ .../kibana/public/dashboard/legacy_app.js | 224 ++++ .../kibana/public/dashboard/legacy_imports.ts | 68 ++ ...embeddable_saved_object_converters.test.ts | 8 +- .../lib/embeddable_saved_object_converters.ts | 9 +- .../dashboard/lib/migrate_app_state.test.ts | 11 +- .../public/dashboard/lib/migrate_app_state.ts | 8 +- .../public/dashboard/lib/save_dashboard.ts | 6 +- .../dashboard/lib/update_saved_dashboard.ts | 7 +- .../dashboard_listing.test.js.snap | 966 +++++++++--------- .../dashboard/listing/dashboard_listing.js | 46 +- .../kibana/public/dashboard/plugin.ts | 151 +++ .../dashboard/top_nav/save_modal.test.js | 7 + .../public/dashboard/top_nav/save_modal.tsx | 4 +- .../dashboard/top_nav/show_clone_modal.tsx | 6 +- .../top_nav/show_options_popover.tsx | 8 +- .../kibana/public/dashboard/types.ts | 5 +- .../public/discover/angular/discover.js | 109 +- .../kibana/public/discover/breadcrumbs.ts | 2 +- .../kibana/public/discover/kibana_services.ts | 2 + .../kibana/public/management/index.js | 8 - .../management/route_setup/load_default.js | 110 -- .../kibana/public/visualize/editor/editor.js | 33 +- .../kibana/public/visualize/index.js | 4 +- .../public/visualize/kibana_services.ts | 1 + .../ui/public/capabilities/route_setup.ts | 38 - src/legacy/ui/public/chrome/api/angular.js | 4 +- .../ui/public/kbn_top_nav/kbn_top_nav.js | 7 +- .../public/legacy_compat/angular_config.tsx | 93 +- .../ensure_default_index_pattern.tsx | 105 ++ src/legacy/ui/public/legacy_compat/index.ts | 1 + .../public/routes/__tests__/_route_manager.js | 12 - .../ui/public/routes/route_manager.d.ts | 2 +- src/legacy/ui/public/routes/route_manager.js | 4 - .../ui/public/state_management/state.js | 15 +- .../ui/public/timefilter/setup_router.test.js | 7 +- .../ui/public/timefilter/setup_router.ts | 86 +- .../ui/public/vis/vis_filters/vis_filters.js | 1 - .../viewport/_dashboard_viewport.scss | 2 + test/functional/apps/dashboard/embed_mode.js | 9 +- .../dashboard_mode/public/dashboard_viewer.js | 4 + x-pack/legacy/plugins/graph/public/index.ts | 2 + x-pack/legacy/plugins/graph/public/plugin.ts | 8 +- .../legacy/plugins/graph/public/render_app.ts | 15 +- 56 files changed, 1895 insertions(+), 1247 deletions(-) create mode 100644 src/legacy/core_plugins/kibana/public/dashboard/application.ts create mode 100644 src/legacy/core_plugins/kibana/public/dashboard/global_state_sync.ts delete mode 100644 src/legacy/core_plugins/kibana/public/dashboard/index.js create mode 100644 src/legacy/core_plugins/kibana/public/dashboard/index.ts create mode 100644 src/legacy/core_plugins/kibana/public/dashboard/legacy_app.js create mode 100644 src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts create mode 100644 src/legacy/core_plugins/kibana/public/dashboard/plugin.ts delete mode 100644 src/legacy/core_plugins/kibana/public/management/route_setup/load_default.js delete mode 100644 src/legacy/ui/public/capabilities/route_setup.ts create mode 100644 src/legacy/ui/public/legacy_compat/ensure_default_index_pattern.tsx diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_app_state_mock.ts b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_app_state_mock.ts index 1f2094d68063d6..d9dea35a8a1c03 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_app_state_mock.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_app_state_mock.ts @@ -17,7 +17,7 @@ * under the License. */ -import { AppStateClass } from 'ui/state_management/app_state'; +import { AppStateClass } from '../legacy_imports'; /** * A poor excuse for a mock just to get some basic tests to run in jest without requiring the injector. diff --git a/src/legacy/core_plugins/kibana/public/dashboard/_dashboard_app.scss b/src/legacy/core_plugins/kibana/public/dashboard/_dashboard_app.scss index eebfad5979d68f..14c35759d70a99 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/_dashboard_app.scss +++ b/src/legacy/core_plugins/kibana/public/dashboard/_dashboard_app.scss @@ -1,7 +1,7 @@ .dshAppContainer { - flex: 1; display: flex; flex-direction: column; + height: 100%; } .dshStartScreen { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/application.ts b/src/legacy/core_plugins/kibana/public/dashboard/application.ts new file mode 100644 index 00000000000000..d507d547d9ba95 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/application.ts @@ -0,0 +1,228 @@ +/* + * 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 { EuiConfirmModal, EuiIcon } from '@elastic/eui'; +import angular, { IModule } from 'angular'; +import { IPrivate } from 'ui/private'; +import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; +import { + AppMountContext, + ChromeStart, + LegacyCoreStart, + SavedObjectsClientContract, + UiSettingsClientContract, +} from 'kibana/public'; +import { Storage } from '../../../../../plugins/kibana_utils/public'; +import { + GlobalStateProvider, + StateManagementConfigProvider, + AppStateProvider, + PrivateProvider, + EventsProvider, + PersistedState, + createTopNavDirective, + createTopNavHelper, + PromiseServiceCreator, + KbnUrlProvider, + RedirectWhenMissingProvider, + confirmModalFactory, + configureAppAngularModule, +} from './legacy_imports'; + +// @ts-ignore +import { initDashboardApp } from './legacy_app'; +import { DataStart } from '../../../data/public'; +import { EmbeddablePublicPlugin } from '../../../../../plugins/embeddable/public'; +import { NavigationStart } from '../../../navigation/public'; +import { DataPublicPluginStart as NpDataStart } from '../../../../../plugins/data/public'; +import { SharePluginStart } from '../../../../../plugins/share/public'; + +export interface RenderDeps { + core: LegacyCoreStart; + indexPatterns: DataStart['indexPatterns']['indexPatterns']; + dataStart: DataStart; + npDataStart: NpDataStart; + navigation: NavigationStart; + savedObjectsClient: SavedObjectsClientContract; + savedObjectRegistry: any; + dashboardConfig: any; + savedDashboards: any; + dashboardCapabilities: any; + uiSettings: UiSettingsClientContract; + chrome: ChromeStart; + addBasePath: (path: string) => string; + savedQueryService: DataStart['search']['services']['savedQueryService']; + embeddables: ReturnType; + localStorage: Storage; + share: SharePluginStart; +} + +let angularModuleInstance: IModule | null = null; + +export const renderApp = (element: HTMLElement, appBasePath: string, deps: RenderDeps) => { + if (!angularModuleInstance) { + angularModuleInstance = createLocalAngularModule(deps.core, deps.navigation); + // global routing stuff + configureAppAngularModule(angularModuleInstance, deps.core as LegacyCoreStart, true); + // custom routing stuff + initDashboardApp(angularModuleInstance, deps); + } + const $injector = mountDashboardApp(appBasePath, element); + return () => { + $injector.get('$rootScope').$destroy(); + }; +}; + +const mainTemplate = (basePath: string) => `
+ +
+
+`; + +const moduleName = 'app/dashboard'; + +const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react']; + +function mountDashboardApp(appBasePath: string, element: HTMLElement) { + const mountpoint = document.createElement('div'); + mountpoint.setAttribute('style', 'height: 100%'); + // eslint-disable-next-line + mountpoint.innerHTML = mainTemplate(appBasePath); + // bootstrap angular into detached element and attach it later to + // make angular-within-angular possible + const $injector = angular.bootstrap(mountpoint, [moduleName]); + // initialize global state handler + element.appendChild(mountpoint); + return $injector; +} + +function createLocalAngularModule(core: AppMountContext['core'], navigation: NavigationStart) { + createLocalI18nModule(); + createLocalPrivateModule(); + createLocalPromiseModule(); + createLocalConfigModule(core); + createLocalKbnUrlModule(); + createLocalStateModule(); + createLocalPersistedStateModule(); + createLocalTopNavModule(navigation); + createLocalConfirmModalModule(); + createLocalIconModule(); + + const dashboardAngularModule = angular.module(moduleName, [ + ...thirdPartyAngularDependencies, + 'app/dashboard/Config', + 'app/dashboard/I18n', + 'app/dashboard/Private', + 'app/dashboard/PersistedState', + 'app/dashboard/TopNav', + 'app/dashboard/State', + 'app/dashboard/ConfirmModal', + 'app/dashboard/icon', + ]); + return dashboardAngularModule; +} + +function createLocalIconModule() { + angular + .module('app/dashboard/icon', ['react']) + .directive('icon', reactDirective => reactDirective(EuiIcon)); +} + +function createLocalConfirmModalModule() { + angular + .module('app/dashboard/ConfirmModal', ['react']) + .factory('confirmModal', confirmModalFactory) + .directive('confirmModal', reactDirective => reactDirective(EuiConfirmModal)); +} + +function createLocalStateModule() { + angular + .module('app/dashboard/State', [ + 'app/dashboard/Private', + 'app/dashboard/Config', + 'app/dashboard/KbnUrl', + 'app/dashboard/Promise', + 'app/dashboard/PersistedState', + ]) + .factory('AppState', function(Private: any) { + return Private(AppStateProvider); + }) + .service('getAppState', function(Private: any) { + return Private(AppStateProvider).getAppState; + }) + .service('globalState', function(Private: any) { + return Private(GlobalStateProvider); + }); +} + +function createLocalPersistedStateModule() { + angular + .module('app/dashboard/PersistedState', ['app/dashboard/Private', 'app/dashboard/Promise']) + .factory('PersistedState', (Private: IPrivate) => { + const Events = Private(EventsProvider); + return class AngularPersistedState extends PersistedState { + constructor(value: any, path: any) { + super(value, path, Events); + } + }; + }); +} + +function createLocalKbnUrlModule() { + angular + .module('app/dashboard/KbnUrl', ['app/dashboard/Private', 'ngRoute']) + .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider)) + .service('redirectWhenMissing', (Private: IPrivate) => Private(RedirectWhenMissingProvider)); +} + +function createLocalConfigModule(core: AppMountContext['core']) { + angular + .module('app/dashboard/Config', ['app/dashboard/Private']) + .provider('stateManagementConfig', StateManagementConfigProvider) + .provider('config', () => { + return { + $get: () => ({ + get: core.uiSettings.get.bind(core.uiSettings), + }), + }; + }); +} + +function createLocalPromiseModule() { + angular.module('app/dashboard/Promise', []).service('Promise', PromiseServiceCreator); +} + +function createLocalPrivateModule() { + angular.module('app/dashboard/Private', []).provider('Private', PrivateProvider); +} + +function createLocalTopNavModule(navigation: NavigationStart) { + angular + .module('app/dashboard/TopNav', ['react']) + .directive('kbnTopNav', createTopNavDirective) + .directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); +} + +function createLocalI18nModule() { + angular + .module('app/dashboard/I18n', []) + .provider('i18n', I18nProvider) + .filter('i18n', i18nFilter) + .directive('i18nId', i18nDirective); +} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html index f644f3811e3e09..a94fd500257d92 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html @@ -4,11 +4,11 @@ >
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx index d5da4ba51e55b6..0ce8f2ef59fc0c 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx @@ -17,26 +17,16 @@ * under the License. */ -import _ from 'lodash'; - -// @ts-ignore -import { uiModules } from 'ui/modules'; -import { IInjector } from 'ui/chrome'; - -// @ts-ignore -import * as filterActions from 'plugins/kibana/discover/doc_table/actions/filter'; +import { StaticIndexPattern, SavedQuery } from 'plugins/data'; +import moment from 'moment'; +import { Subscription } from 'rxjs'; import { AppStateClass as TAppStateClass, AppState as TAppState, -} from 'ui/state_management/app_state'; - -import { KbnUrl } from 'ui/url/kbn_url'; -import { IndexPattern } from 'ui/index_patterns'; -import { IPrivate } from 'ui/private'; -import { StaticIndexPattern, SavedQuery } from 'plugins/data'; -import moment from 'moment'; -import { Subscription } from 'rxjs'; + IInjector, + KbnUrl, +} from './legacy_imports'; import { ViewMode } from '../../../embeddable_api/public/np_ready/public'; import { SavedObjectDashboard } from './saved_dashboard/saved_dashboard'; @@ -44,6 +34,7 @@ import { DashboardAppState, SavedDashboardPanel, ConfirmModalFn } from './types' import { TimeRange, Query, esFilters } from '../../../../../../src/plugins/data/public'; import { DashboardAppController } from './dashboard_app_controller'; +import { RenderDeps } from './application'; export interface DashboardAppScope extends ng.IScope { dash: SavedObjectDashboard; @@ -90,54 +81,40 @@ export interface DashboardAppScope extends ng.IScope { kbnTopNav: any; enterEditMode: () => void; timefilterSubscriptions$: Subscription; + isVisible: boolean; } -const app = uiModules.get('app/dashboard', ['elasticsearch', 'ngRoute', 'react', 'kibana/config']); - -app.directive('dashboardApp', function($injector: IInjector) { - const AppState = $injector.get>('AppState'); - const kbnUrl = $injector.get('kbnUrl'); - const confirmModal = $injector.get('confirmModal'); - const config = $injector.get('config'); - - const Private = $injector.get('Private'); +export function initDashboardAppDirective(app: any, deps: RenderDeps) { + app.directive('dashboardApp', function($injector: IInjector) { + const AppState = $injector.get>('AppState'); + const kbnUrl = $injector.get('kbnUrl'); + const confirmModal = $injector.get('confirmModal'); + const config = deps.uiSettings; - const indexPatterns = $injector.get<{ - getDefault: () => Promise; - }>('indexPatterns'); - - return { - restrict: 'E', - controllerAs: 'dashboardApp', - controller: ( - $scope: DashboardAppScope, - $route: any, - $routeParams: { - id?: string; - }, - getAppState: { - previouslyStored: () => TAppState | undefined; - }, - dashboardConfig: { - getHideWriteControls: () => boolean; - }, - localStorage: { - get: (prop: string) => unknown; - } - ) => - new DashboardAppController({ - $route, - $scope, - $routeParams, - getAppState, - dashboardConfig, - localStorage, - Private, - kbnUrl, - AppStateClass: AppState, - indexPatterns, - config, - confirmModal, - }), - }; -}); + return { + restrict: 'E', + controllerAs: 'dashboardApp', + controller: ( + $scope: DashboardAppScope, + $route: any, + $routeParams: { + id?: string; + }, + getAppState: any, + globalState: any + ) => + new DashboardAppController({ + $route, + $scope, + $routeParams, + getAppState, + globalState, + kbnUrl, + AppStateClass: AppState, + config, + confirmModal, + ...deps, + }), + }; + }); +} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx index 457d8972876ae6..16c0e4437c344c 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx @@ -23,41 +23,23 @@ import React from 'react'; import angular from 'angular'; import { uniq } from 'lodash'; -import chrome from 'ui/chrome'; -import { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; -import { toastNotifications } from 'ui/notify'; - -// @ts-ignore -import { ConfirmationButtonTypes } from 'ui/modals/confirm_modal'; -import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; - -import { docTitle } from 'ui/doc_title/doc_title'; - -import { showSaveModal, SaveResult } from 'ui/saved_objects/show_saved_object_save_modal'; - -import { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; - -import { timefilter } from 'ui/timefilter'; - -import { getUnhashableStatesProvider } from 'ui/state_management/state_hashing/get_unhashable_states_provider'; +import { Subscription } from 'rxjs'; import { + subscribeWithScope, + ConfirmationButtonTypes, + showSaveModal, + SaveResult, + migrateLegacyQuery, + State, AppStateClass as TAppStateClass, - AppState as TAppState, -} from 'ui/state_management/app_state'; - -import { KbnUrl } from 'ui/url/kbn_url'; -import { IndexPattern } from 'ui/index_patterns'; -import { IPrivate } from 'ui/private'; -import { SavedQuery } from 'src/legacy/core_plugins/data/public'; -import { SaveOptions } from 'ui/saved_objects/saved_object'; -import { capabilities } from 'ui/capabilities'; -import { Subscription } from 'rxjs'; -import { npStart } from 'ui/new_platform'; -import { unhashUrl } from 'ui/state_management/state_hashing'; -import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder'; + KbnUrl, + SaveOptions, + SavedObjectFinder, + unhashUrl, +} from './legacy_imports'; +import { FilterStateManager, IndexPattern, SavedQuery } from '../../../data/public'; import { Query } from '../../../../../plugins/data/public'; -import { start as data } from '../../../data/public/legacy'; import { DashboardContainer, @@ -72,7 +54,6 @@ import { ViewMode, openAddPanelFlyout, } from '../../../embeddable_api/public/np_ready/public'; -import { start } from '../../../embeddable_api/public/np_ready/public/legacy'; import { DashboardAppState, NavAction, ConfirmModalFn, SavedDashboardPanel } from './types'; import { showOptionsPopover } from './top_nav/show_options_popover'; @@ -87,8 +68,23 @@ import { getDashboardTitle } from './dashboard_strings'; import { DashboardAppScope } from './dashboard_app'; import { VISUALIZE_EMBEDDABLE_TYPE } from '../visualize/embeddable'; import { convertSavedDashboardPanelToPanelState } from './lib/embeddable_saved_object_converters'; - -const { savedQueryService } = data.search.services; +import { RenderDeps } from './application'; + +export interface DashboardAppControllerDependencies extends RenderDeps { + $scope: DashboardAppScope; + $route: any; + $routeParams: any; + getAppState: any; + globalState: State; + indexPatterns: { + getDefault: () => Promise; + }; + dashboardConfig: any; + kbnUrl: KbnUrl; + AppStateClass: TAppStateClass; + config: any; + confirmModal: ConfirmModalFn; +} export class DashboardAppController { // Part of the exposed plugin API - do not remove without careful consideration. @@ -101,58 +97,55 @@ export class DashboardAppController { $route, $routeParams, getAppState, + globalState, dashboardConfig, localStorage, - Private, kbnUrl, AppStateClass, indexPatterns, config, confirmModal, - }: { - $scope: DashboardAppScope; - $route: any; - $routeParams: any; - getAppState: { - previouslyStored: () => TAppState | undefined; - }; - indexPatterns: { - getDefault: () => Promise; - }; - dashboardConfig: any; - localStorage: { - get: (prop: string) => unknown; - }; - Private: IPrivate; - kbnUrl: KbnUrl; - AppStateClass: TAppStateClass; - config: any; - confirmModal: ConfirmModalFn; - }) { - const queryFilter = Private(FilterBarQueryFilterProvider); - const getUnhashableStates = Private(getUnhashableStatesProvider); + savedQueryService, + embeddables, + share, + dashboardCapabilities, + npDataStart: { + query: { + filterManager, + timefilter: { timefilter }, + }, + }, + core: { notifications, overlays, chrome, injectedMetadata }, + }: DashboardAppControllerDependencies) { + new FilterStateManager(globalState, getAppState, filterManager); + const queryFilter = filterManager; + + function getUnhashableStates(): State[] { + return [getAppState(), globalState].filter(Boolean); + } let lastReloadRequestTime = 0; const dash = ($scope.dash = $route.current.locals.dash); if (dash.id) { - docTitle.change(dash.title); + chrome.docTitle.change(dash.title); } const dashboardStateManager = new DashboardStateManager({ savedDashboard: dash, AppStateClass, hideWriteControls: dashboardConfig.getHideWriteControls(), + kibanaVersion: injectedMetadata.getKibanaVersion(), }); $scope.appState = dashboardStateManager.getAppState(); - // The 'previouslyStored' check is so we only update the time filter on dashboard open, not during + // The hash check is so we only update the time filter on dashboard open, not during // normal cross app navigation. - if (dashboardStateManager.getIsTimeSavedWithDashboard() && !getAppState.previouslyStored()) { + if (dashboardStateManager.getIsTimeSavedWithDashboard() && !globalState.$inheritedGlobalState) { dashboardStateManager.syncTimefilterWithDashboard(timefilter); } - $scope.showSaveQuery = capabilities.get().dashboard.saveQuery as boolean; + $scope.showSaveQuery = dashboardCapabilities.saveQuery as boolean; const updateIndexPatterns = (container?: DashboardContainer) => { if (!container || isErrorEmbeddable(container)) { @@ -187,10 +180,7 @@ export class DashboardAppController { [key: string]: DashboardPanelState; } = {}; dashboardStateManager.getPanels().forEach((panel: SavedDashboardPanel) => { - embeddablesMap[panel.panelIndex] = convertSavedDashboardPanelToPanelState( - panel, - dashboardStateManager.getUseMargins() - ); + embeddablesMap[panel.panelIndex] = convertSavedDashboardPanelToPanelState(panel); }); let expandedPanelId; if (dashboardContainer && !isErrorEmbeddable(dashboardContainer)) { @@ -239,7 +229,7 @@ export class DashboardAppController { let outputSubscription: Subscription | undefined; const dashboardDom = document.getElementById('dashboardViewport'); - const dashboardFactory = start.getEmbeddableFactory( + const dashboardFactory = embeddables.getEmbeddableFactory( DASHBOARD_CONTAINER_TYPE ) as DashboardContainerFactory; dashboardFactory @@ -334,7 +324,7 @@ export class DashboardAppController { // Push breadcrumbs to new header navigation const updateBreadcrumbs = () => { - chrome.breadcrumbs.set([ + chrome.setBreadcrumbs([ { text: i18n.translate('kbn.dashboard.dashboardAppBreadcrumbsTitle', { defaultMessage: 'Dashboard', @@ -495,7 +485,7 @@ export class DashboardAppController { }); $scope.$watch( - () => capabilities.get().dashboard.saveQuery, + () => dashboardCapabilities.saveQuery, newCapability => { $scope.showSaveQuery = newCapability as boolean; } @@ -595,7 +585,7 @@ export class DashboardAppController { return saveDashboard(angular.toJson, timefilter, dashboardStateManager, saveOptions) .then(function(id) { if (id) { - toastNotifications.addSuccess({ + notifications.toasts.addSuccess({ title: i18n.translate('kbn.dashboard.dashboardWasSavedSuccessMessage', { defaultMessage: `Dashboard '{dashTitle}' was saved`, values: { dashTitle: dash.title }, @@ -606,14 +596,14 @@ export class DashboardAppController { if (dash.id !== $routeParams.id) { kbnUrl.change(createDashboardEditUrl(dash.id)); } else { - docTitle.change(dash.lastSavedTitle); + chrome.docTitle.change(dash.lastSavedTitle); updateViewMode(ViewMode.VIEW); } } return { id }; }) .catch(error => { - toastNotifications.addDanger({ + notifications.toasts.addDanger({ title: i18n.translate('kbn.dashboard.dashboardWasNotSavedDangerMessage', { defaultMessage: `Dashboard '{dashTitle}' was not saved. Error: {errorMessage}`, values: { @@ -734,10 +724,10 @@ export class DashboardAppController { if (dashboardContainer && !isErrorEmbeddable(dashboardContainer)) { openAddPanelFlyout({ embeddable: dashboardContainer, - getAllFactories: start.getEmbeddableFactories, - getFactory: start.getEmbeddableFactory, - notifications: npStart.core.notifications, - overlays: npStart.core.overlays, + getAllFactories: embeddables.getEmbeddableFactories, + getFactory: embeddables.getEmbeddableFactory, + notifications, + overlays, SavedObjectFinder, }); } @@ -757,7 +747,7 @@ export class DashboardAppController { }); }; navActions[TopNavIds.SHARE] = anchorElement => { - npStart.plugins.share.toggleShareContextMenu({ + share.toggleShareContextMenu({ anchorElement, allowEmbed: true, allowShortUrl: !dashboardConfig.getHideWriteControls(), @@ -784,8 +774,15 @@ export class DashboardAppController { }, }); + const visibleSubscription = chrome.getIsVisible$().subscribe(isVisible => { + $scope.$evalAsync(() => { + $scope.isVisible = isVisible; + }); + }); + $scope.$on('$destroy', () => { updateSubscription.unsubscribe(); + visibleSubscription.unsubscribe(); $scope.timefilterSubscriptions$.unsubscribe(); dashboardStateManager.destroy(); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state.test.ts index 5e81373001bf57..d5d776944ad7af 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state.test.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state.test.ts @@ -21,11 +21,10 @@ import './np_core.test.mocks'; import { DashboardStateManager } from './dashboard_state_manager'; import { getAppStateMock, getSavedDashboardMock } from './__tests__'; -import { AppStateClass } from 'ui/state_management/app_state'; +import { AppStateClass } from './legacy_imports'; import { DashboardAppState } from './types'; -import { TimeRange, TimefilterContract } from 'src/plugins/data/public'; +import { TimeRange, TimefilterContract, InputTimeRange } from 'src/plugins/data/public'; import { ViewMode } from 'src/plugins/embeddable/public'; -import { InputTimeRange } from 'ui/timefilter'; jest.mock('ui/registry/field_formats', () => ({ fieldFormats: { @@ -33,6 +32,10 @@ jest.mock('ui/registry/field_formats', () => ({ }, })); +jest.mock('ui/state_management/state', () => ({ + State: {}, +})); + describe('DashboardState', function() { let dashboardState: DashboardStateManager; const savedDashboard = getSavedDashboardMock(); @@ -52,6 +55,7 @@ describe('DashboardState', function() { savedDashboard, AppStateClass: getAppStateMock() as AppStateClass, hideWriteControls: false, + kibanaVersion: '7.0.0', }); } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts index d5af4c93d0e0cc..ac8628ec2a9d94 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts @@ -20,15 +20,21 @@ import { i18n } from '@kbn/i18n'; import _ from 'lodash'; -import { stateMonitorFactory, StateMonitor } from 'ui/state_management/state_monitor_factory'; -import { Timefilter } from 'ui/timefilter'; -import { AppStateClass as TAppStateClass } from 'ui/state_management/app_state'; -import { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; import { Moment } from 'moment'; import { DashboardContainer } from 'src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public'; import { ViewMode } from '../../../../../../src/plugins/embeddable/public'; -import { Query, esFilters } from '../../../../../../src/plugins/data/public'; +import { + stateMonitorFactory, + StateMonitor, + AppStateClass as TAppStateClass, + migrateLegacyQuery, +} from './legacy_imports'; +import { + Query, + esFilters, + TimefilterContract as Timefilter, +} from '../../../../../../src/plugins/data/public'; import { getAppStateDefaults, migrateAppState } from './lib'; import { convertPanelStateToSavedDashboardPanel } from './lib/embeddable_saved_object_converters'; @@ -54,6 +60,7 @@ export class DashboardStateManager { }; private stateDefaults: DashboardAppStateDefaults; private hideWriteControls: boolean; + private kibanaVersion: string; public isDirty: boolean; private changeListeners: Array<(status: { dirty: boolean }) => void>; private stateMonitor: StateMonitor; @@ -68,11 +75,14 @@ export class DashboardStateManager { savedDashboard, AppStateClass, hideWriteControls, + kibanaVersion, }: { savedDashboard: SavedObjectDashboard; AppStateClass: TAppStateClass; hideWriteControls: boolean; + kibanaVersion: string; }) { + this.kibanaVersion = kibanaVersion; this.savedDashboard = savedDashboard; this.hideWriteControls = hideWriteControls; @@ -84,7 +94,7 @@ export class DashboardStateManager { // appState based on the URL (the url trumps the defaults). This means if we update the state format at all and // want to handle BWC, we must not only migrate the data stored with saved Dashboard, but also any old state in the // url. - migrateAppState(this.appState); + migrateAppState(this.appState, kibanaVersion); this.isDirty = false; @@ -146,7 +156,8 @@ export class DashboardStateManager { } convertedPanelStateMap[panelState.explicitInput.id] = convertPanelStateToSavedDashboardPanel( - panelState + panelState, + this.kibanaVersion ); if ( diff --git a/src/legacy/core_plugins/kibana/public/dashboard/global_state_sync.ts b/src/legacy/core_plugins/kibana/public/dashboard/global_state_sync.ts new file mode 100644 index 00000000000000..8a733f940734b9 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/global_state_sync.ts @@ -0,0 +1,67 @@ +/* + * 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 { State } from './legacy_imports'; +import { DataPublicPluginStart as NpDataStart } from '../../../../../plugins/data/public'; + +/** + * Helper function to sync the global state with the various state providers + * when a local angular application mounts. There are three different ways + * global state can be passed into the application: + * * parameter in the URL hash - e.g. shared link + * * in-memory state in the data plugin exports (timefilter and filterManager) - e.g. default values + * + * This function looks up the three sources (earlier in the list means it takes precedence), + * puts it into the globalState object and syncs it with the url. + * + * Currently the legacy chrome takes care of restoring the global state when navigating from + * one app to another - to migrate away from that it will become necessary to also write the current + * state to local storage + */ +export function syncOnMount( + globalState: State, + { + query: { + filterManager, + timefilter: { timefilter }, + }, + }: NpDataStart +) { + // pull in global state information from the URL + globalState.fetch(); + // remember whether there were info in the URL + const hasGlobalURLState = Boolean(Object.keys(globalState.toObject()).length); + + // sync kibana platform state with the angular global state + if (!globalState.time) { + globalState.time = timefilter.getTime(); + } + if (!globalState.refreshInterval) { + globalState.refreshInterval = timefilter.getRefreshInterval(); + } + if (!globalState.filters && filterManager.getGlobalFilters().length > 0) { + globalState.filters = filterManager.getGlobalFilters(); + } + // only inject cross app global state if there is none in the url itself (that takes precedence) + if (hasGlobalURLState) { + // set flag the global state is set from the URL + globalState.$inheritedGlobalState = true; + } + globalState.save(); +} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js index 56b2bd253381c7..1b1a7f84c81310 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js @@ -17,26 +17,30 @@ * under the License. */ -import React, { Fragment, PureComponent } from 'react'; +import React, { PureComponent } from 'react'; import { EuiButton, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; +import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; export class HelpMenu extends PureComponent { render() { return ( - - - - - - - + + <> + + + + + + + ); } } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js index aeabff2d97007b..2dc8ce523a7da6 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js @@ -21,9 +21,9 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { HelpMenu } from './help_menu'; -export function addHelpMenuToAppChrome(chrome) { - chrome.helpExtension.set(domElement => { - render(, domElement); +export function addHelpMenuToAppChrome(chrome, docLinks) { + chrome.setHelpExtension(domElement => { + render(, domElement); return () => { unmountComponentAtNode(domElement); }; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/index.js b/src/legacy/core_plugins/kibana/public/dashboard/index.js deleted file mode 100644 index 712e05c92e5e8b..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dashboard/index.js +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import './dashboard_app'; -import { i18n } from '@kbn/i18n'; -import './saved_dashboard/saved_dashboards'; -import './dashboard_config'; -import uiRoutes from 'ui/routes'; -import chrome from 'ui/chrome'; -import { wrapInI18nContext } from 'ui/i18n'; -import { toastNotifications } from 'ui/notify'; - -import dashboardTemplate from './dashboard_app.html'; -import dashboardListingTemplate from './listing/dashboard_listing_ng_wrapper.html'; - -import { DashboardConstants, createDashboardEditUrl } from './dashboard_constants'; -import { InvalidJSONProperty, SavedObjectNotFound } from '../../../../../plugins/kibana_utils/public'; -import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; -import { SavedObjectsClientProvider } from 'ui/saved_objects'; -import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; -import { DashboardListing, EMPTY_FILTER } from './listing/dashboard_listing'; -import { uiModules } from 'ui/modules'; -import 'ui/capabilities/route_setup'; -import { addHelpMenuToAppChrome } from './help_menu/help_menu_util'; - -import { npStart } from 'ui/new_platform'; - -// load directives -import '../../../data/public'; - -const app = uiModules.get('app/dashboard', [ - 'ngRoute', - 'react', -]); - -app.directive('dashboardListing', function (reactDirective) { - return reactDirective(wrapInI18nContext(DashboardListing)); -}); - -function createNewDashboardCtrl($scope) { - $scope.visitVisualizeAppLinkText = i18n.translate('kbn.dashboard.visitVisualizeAppLinkText', { - defaultMessage: 'visit the Visualize app', - }); - addHelpMenuToAppChrome(chrome); -} - -uiRoutes - .defaults(/dashboard/, { - requireDefaultIndex: true, - requireUICapability: 'dashboard.show', - badge: uiCapabilities => { - if (uiCapabilities.dashboard.showWriteControls) { - return undefined; - } - - return { - text: i18n.translate('kbn.dashboard.badge.readOnly.text', { - defaultMessage: 'Read only', - }), - tooltip: i18n.translate('kbn.dashboard.badge.readOnly.tooltip', { - defaultMessage: 'Unable to save dashboards', - }), - iconType: 'glasses' - }; - } - }) - .when(DashboardConstants.LANDING_PAGE_PATH, { - template: dashboardListingTemplate, - controller($injector, $location, $scope, Private, config) { - const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName; - const kbnUrl = $injector.get('kbnUrl'); - const dashboardConfig = $injector.get('dashboardConfig'); - - $scope.listingLimit = config.get('savedObjects:listingLimit'); - $scope.create = () => { - kbnUrl.redirect(DashboardConstants.CREATE_NEW_DASHBOARD_URL); - }; - $scope.find = (search) => { - return services.dashboards.find(search, $scope.listingLimit); - }; - $scope.editItem = ({ id }) => { - kbnUrl.redirect(`${createDashboardEditUrl(id)}?_a=(viewMode:edit)`); - }; - $scope.getViewUrl = ({ id }) => { - return chrome.addBasePath(`#${createDashboardEditUrl(id)}`); - }; - $scope.delete = (dashboards) => { - return services.dashboards.delete(dashboards.map(d => d.id)); - }; - $scope.hideWriteControls = dashboardConfig.getHideWriteControls(); - $scope.initialFilter = ($location.search()).filter || EMPTY_FILTER; - chrome.breadcrumbs.set([{ - text: i18n.translate('kbn.dashboard.dashboardBreadcrumbsTitle', { - defaultMessage: 'Dashboards', - }), - }]); - addHelpMenuToAppChrome(chrome); - }, - resolve: { - dash: function ($route, Private, redirectWhenMissing, kbnUrl) { - const savedObjectsClient = Private(SavedObjectsClientProvider); - const title = $route.current.params.title; - if (title) { - return savedObjectsClient.find({ - search: `"${title}"`, - search_fields: 'title', - type: 'dashboard', - }).then(results => { - // The search isn't an exact match, lets see if we can find a single exact match to use - const matchingDashboards = results.savedObjects.filter( - dashboard => dashboard.attributes.title.toLowerCase() === title.toLowerCase()); - if (matchingDashboards.length === 1) { - kbnUrl.redirect(createDashboardEditUrl(matchingDashboards[0].id)); - } else { - kbnUrl.redirect(`${DashboardConstants.LANDING_PAGE_PATH}?filter="${title}"`); - } - throw uiRoutes.WAIT_FOR_URL_CHANGE_TOKEN; - }).catch(redirectWhenMissing({ - 'dashboard': DashboardConstants.LANDING_PAGE_PATH - })); - } - } - } - }) - .when(DashboardConstants.CREATE_NEW_DASHBOARD_URL, { - template: dashboardTemplate, - controller: createNewDashboardCtrl, - requireUICapability: 'dashboard.createNew', - resolve: { - dash: function (savedDashboards, redirectWhenMissing) { - return savedDashboards.get() - .catch(redirectWhenMissing({ - 'dashboard': DashboardConstants.LANDING_PAGE_PATH - })); - } - } - }) - .when(createDashboardEditUrl(':id'), { - template: dashboardTemplate, - controller: createNewDashboardCtrl, - resolve: { - dash: function (savedDashboards, $route, redirectWhenMissing, kbnUrl, AppState) { - const id = $route.current.params.id; - - return savedDashboards.get(id) - .then((savedDashboard) => { - npStart.core.chrome.recentlyAccessed.add(savedDashboard.getFullPath(), savedDashboard.title, id); - return savedDashboard; - }) - .catch((error) => { - // A corrupt dashboard was detected (e.g. with invalid JSON properties) - if (error instanceof InvalidJSONProperty) { - toastNotifications.addDanger(error.message); - kbnUrl.redirect(DashboardConstants.LANDING_PAGE_PATH); - return; - } - - // Preserve BWC of v5.3.0 links for new, unsaved dashboards. - // See https://github.com/elastic/kibana/issues/10951 for more context. - if (error instanceof SavedObjectNotFound && id === 'create') { - // Note "new AppState" is necessary so the state in the url is preserved through the redirect. - kbnUrl.redirect(DashboardConstants.CREATE_NEW_DASHBOARD_URL, {}, new AppState()); - toastNotifications.addWarning(i18n.translate('kbn.dashboard.urlWasRemovedInSixZeroWarningMessage', - { defaultMessage: 'The url "dashboard/create" was removed in 6.0. Please update your bookmarks.' } - )); - } else { - throw error; - } - }) - .catch(redirectWhenMissing({ - 'dashboard': DashboardConstants.LANDING_PAGE_PATH - })); - } - } - }); - -FeatureCatalogueRegistryProvider.register(() => { - return { - id: 'dashboard', - title: i18n.translate('kbn.dashboard.featureCatalogue.dashboardTitle', { - defaultMessage: 'Dashboard', - }), - description: i18n.translate('kbn.dashboard.featureCatalogue.dashboardDescription', { - defaultMessage: 'Display and share a collection of visualizations and saved searches.', - }), - icon: 'dashboardApp', - path: `/app/kibana#${DashboardConstants.LANDING_PAGE_PATH}`, - showOnHomePage: true, - category: FeatureCatalogueCategory.DATA - }; -}); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/index.ts b/src/legacy/core_plugins/kibana/public/dashboard/index.ts new file mode 100644 index 00000000000000..111806701c829e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/index.ts @@ -0,0 +1,69 @@ +/* + * 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 { + npSetup, + npStart, + SavedObjectRegistryProvider, + legacyChrome, + IPrivate, +} from './legacy_imports'; +import { DashboardPlugin, LegacyAngularInjectedDependencies } from './plugin'; +import { start as data } from '../../../data/public/legacy'; +import { localApplicationService } from '../local_application_service'; +import { start as embeddables } from '../../../embeddable_api/public/np_ready/public/legacy'; +import { start as navigation } from '../../../navigation/public/legacy'; +import './saved_dashboard/saved_dashboards'; +import './dashboard_config'; + +/** + * Get dependencies relying on the global angular context. + * They also have to get resolved together with the legacy imports above + */ +async function getAngularDependencies(): Promise { + const injector = await legacyChrome.dangerouslyGetActiveInjector(); + + const Private = injector.get('Private'); + + const savedObjectRegistry = Private(SavedObjectRegistryProvider); + + return { + dashboardConfig: injector.get('dashboardConfig'), + savedObjectRegistry, + savedDashboards: injector.get('savedDashboards'), + }; +} + +(async () => { + const instance = new DashboardPlugin(); + instance.setup(npSetup.core, { + feature_catalogue: npSetup.plugins.feature_catalogue, + __LEGACY: { + localApplicationService, + getAngularDependencies, + }, + }); + instance.start(npStart.core, { + ...npStart.plugins, + data, + npData: npStart.plugins.data, + embeddables, + navigation, + }); +})(); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_app.js b/src/legacy/core_plugins/kibana/public/dashboard/legacy_app.js new file mode 100644 index 00000000000000..c7f2adb4b875b9 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_app.js @@ -0,0 +1,224 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +import dashboardTemplate from './dashboard_app.html'; +import dashboardListingTemplate from './listing/dashboard_listing_ng_wrapper.html'; + +import { ensureDefaultIndexPattern } from './legacy_imports'; +import { initDashboardAppDirective } from './dashboard_app'; +import { DashboardConstants, createDashboardEditUrl } from './dashboard_constants'; +import { + InvalidJSONProperty, + SavedObjectNotFound, +} from '../../../../../plugins/kibana_utils/public'; +import { DashboardListing, EMPTY_FILTER } from './listing/dashboard_listing'; +import { addHelpMenuToAppChrome } from './help_menu/help_menu_util'; +import { registerTimefilterWithGlobalStateFactory } from '../../../../ui/public/timefilter/setup_router'; +import { syncOnMount } from './global_state_sync'; + +export function initDashboardApp(app, deps) { + initDashboardAppDirective(app, deps); + + app.directive('dashboardListing', function (reactDirective) { + return reactDirective(DashboardListing); + }); + + function createNewDashboardCtrl($scope) { + $scope.visitVisualizeAppLinkText = i18n.translate('kbn.dashboard.visitVisualizeAppLinkText', { + defaultMessage: 'visit the Visualize app', + }); + addHelpMenuToAppChrome(deps.chrome, deps.core.docLinks); + } + + app.run(globalState => { + syncOnMount(globalState, deps.npDataStart); + }); + + app.run((globalState, $rootScope) => { + registerTimefilterWithGlobalStateFactory( + deps.npDataStart.query.timefilter.timefilter, + globalState, + $rootScope + ); + }); + + app.config(function ($routeProvider) { + const defaults = { + reloadOnSearch: false, + requireUICapability: 'dashboard.show', + badge: () => { + if (deps.dashboardCapabilities.showWriteControls) { + return undefined; + } + + return { + text: i18n.translate('kbn.dashboard.badge.readOnly.text', { + defaultMessage: 'Read only', + }), + tooltip: i18n.translate('kbn.dashboard.badge.readOnly.tooltip', { + defaultMessage: 'Unable to save dashboards', + }), + iconType: 'glasses', + }; + }, + }; + + $routeProvider + .when(DashboardConstants.LANDING_PAGE_PATH, { + ...defaults, + template: dashboardListingTemplate, + controller($injector, $location, $scope) { + const services = deps.savedObjectRegistry.byLoaderPropertiesName; + const kbnUrl = $injector.get('kbnUrl'); + const dashboardConfig = deps.dashboardConfig; + + $scope.listingLimit = deps.uiSettings.get('savedObjects:listingLimit'); + $scope.create = () => { + kbnUrl.redirect(DashboardConstants.CREATE_NEW_DASHBOARD_URL); + }; + $scope.find = search => { + return services.dashboards.find(search, $scope.listingLimit); + }; + $scope.editItem = ({ id }) => { + kbnUrl.redirect(`${createDashboardEditUrl(id)}?_a=(viewMode:edit)`); + }; + $scope.getViewUrl = ({ id }) => { + return deps.addBasePath(`#${createDashboardEditUrl(id)}`); + }; + $scope.delete = dashboards => { + return services.dashboards.delete(dashboards.map(d => d.id)); + }; + $scope.hideWriteControls = dashboardConfig.getHideWriteControls(); + $scope.initialFilter = $location.search().filter || EMPTY_FILTER; + deps.chrome.setBreadcrumbs([ + { + text: i18n.translate('kbn.dashboard.dashboardBreadcrumbsTitle', { + defaultMessage: 'Dashboards', + }), + }, + ]); + addHelpMenuToAppChrome(deps.chrome, deps.core.docLinks); + }, + resolve: { + dash: function ($rootScope, $route, redirectWhenMissing, kbnUrl) { + return ensureDefaultIndexPattern(deps.core, deps.dataStart, $rootScope, kbnUrl).then(() => { + const savedObjectsClient = deps.savedObjectsClient; + const title = $route.current.params.title; + if (title) { + return savedObjectsClient + .find({ + search: `"${title}"`, + search_fields: 'title', + type: 'dashboard', + }) + .then(results => { + // The search isn't an exact match, lets see if we can find a single exact match to use + const matchingDashboards = results.savedObjects.filter( + dashboard => dashboard.attributes.title.toLowerCase() === title.toLowerCase() + ); + if (matchingDashboards.length === 1) { + kbnUrl.redirect(createDashboardEditUrl(matchingDashboards[0].id)); + } else { + kbnUrl.redirect(`${DashboardConstants.LANDING_PAGE_PATH}?filter="${title}"`); + } + $rootScope.$digest(); + return new Promise(() => {}); + }); + } + }); + }, + }, + }) + .when(DashboardConstants.CREATE_NEW_DASHBOARD_URL, { + ...defaults, + template: dashboardTemplate, + controller: createNewDashboardCtrl, + requireUICapability: 'dashboard.createNew', + resolve: { + dash: function (redirectWhenMissing, $rootScope, kbnUrl) { + return ensureDefaultIndexPattern(deps.core, deps.dataStart, $rootScope, kbnUrl) + .then(() => { + return deps.savedDashboards.get(); + }) + .catch( + redirectWhenMissing({ + dashboard: DashboardConstants.LANDING_PAGE_PATH, + }) + ); + }, + }, + }) + .when(createDashboardEditUrl(':id'), { + ...defaults, + template: dashboardTemplate, + controller: createNewDashboardCtrl, + resolve: { + dash: function ($rootScope, $route, redirectWhenMissing, kbnUrl, AppState) { + const id = $route.current.params.id; + + return ensureDefaultIndexPattern(deps.core, deps.dataStart, $rootScope, kbnUrl) + .then(() => { + return deps.savedDashboards.get(id); + }) + .then(savedDashboard => { + deps.chrome.recentlyAccessed.add( + savedDashboard.getFullPath(), + savedDashboard.title, + id + ); + return savedDashboard; + }) + .catch(error => { + // A corrupt dashboard was detected (e.g. with invalid JSON properties) + if (error instanceof InvalidJSONProperty) { + deps.toastNotifications.addDanger(error.message); + kbnUrl.redirect(DashboardConstants.LANDING_PAGE_PATH); + return; + } + + // Preserve BWC of v5.3.0 links for new, unsaved dashboards. + // See https://github.com/elastic/kibana/issues/10951 for more context. + if (error instanceof SavedObjectNotFound && id === 'create') { + // Note "new AppState" is necessary so the state in the url is preserved through the redirect. + kbnUrl.redirect(DashboardConstants.CREATE_NEW_DASHBOARD_URL, {}, new AppState()); + deps.toastNotifications.addWarning( + i18n.translate('kbn.dashboard.urlWasRemovedInSixZeroWarningMessage', { + defaultMessage: + 'The url "dashboard/create" was removed in 6.0. Please update your bookmarks.', + }) + ); + return new Promise(() => {}); + } else { + throw error; + } + }) + .catch( + redirectWhenMissing({ + dashboard: DashboardConstants.LANDING_PAGE_PATH, + }) + ); + }, + }, + }) + .when(`dashboard/:tail*?`, { redirectTo: `/${deps.core.injectedMetadata.getInjectedVar('kbnDefaultAppId')}` }) + .when(`dashboards/:tail*?`, { redirectTo: `/${deps.core.injectedMetadata.getInjectedVar('kbnDefaultAppId')}` }); + }); +} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts new file mode 100644 index 00000000000000..7c3c389330887e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts @@ -0,0 +1,68 @@ +/* + * 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. + */ + +/** + * The imports in this file are static functions and types which still live in legacy folders and are used + * within dashboard. To consolidate them all in one place, they are re-exported from this file. Eventually + * this list should become empty. Imports from the top level of shimmed or moved plugins can be imported + * directly where they are needed. + */ + +import chrome from 'ui/chrome'; + +export const legacyChrome = chrome; +export { State } from 'ui/state_management/state'; +export { AppState } from 'ui/state_management/app_state'; +export { AppStateClass } from 'ui/state_management/app_state'; +export { SaveOptions } from 'ui/saved_objects/saved_object'; +export { npSetup, npStart } from 'ui/new_platform'; +export { SavedObjectRegistryProvider } from 'ui/saved_objects'; +export { IPrivate } from 'ui/private'; +export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; +export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; +// @ts-ignore +export { ConfirmationButtonTypes } from 'ui/modals/confirm_modal'; +export { showSaveModal, SaveResult } from 'ui/saved_objects/show_saved_object_save_modal'; +export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; +export { KbnUrl } from 'ui/url/kbn_url'; +// @ts-ignore +export { GlobalStateProvider } from 'ui/state_management/global_state'; +// @ts-ignore +export { StateManagementConfigProvider } from 'ui/state_management/config_provider'; +// @ts-ignore +export { AppStateProvider } from 'ui/state_management/app_state'; +// @ts-ignore +export { PrivateProvider } from 'ui/private/private'; +// @ts-ignore +export { EventsProvider } from 'ui/events'; +export { PersistedState } from 'ui/persisted_state'; +// @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'; +// @ts-ignore +export { confirmModalFactory } from 'ui/modals/confirm_modal'; +export { configureAppAngularModule } from 'ui/legacy_compat'; +export { stateMonitorFactory, StateMonitor } from 'ui/state_management/state_monitor_factory'; +export { ensureDefaultIndexPattern } from 'ui/legacy_compat'; +export { unhashUrl } from 'ui/state_management/state_hashing'; +export { IInjector } from 'ui/chrome'; +export { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder'; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/lib/embeddable_saved_object_converters.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/lib/embeddable_saved_object_converters.test.ts index 99bb6b115b985d..3f04cad4f322b6 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/lib/embeddable_saved_object_converters.test.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/lib/embeddable_saved_object_converters.test.ts @@ -48,7 +48,7 @@ test('convertSavedDashboardPanelToPanelState', () => { version: '7.0.0', }; - expect(convertSavedDashboardPanelToPanelState(savedDashboardPanel, true)).toEqual({ + expect(convertSavedDashboardPanelToPanelState(savedDashboardPanel)).toEqual({ gridData: { x: 0, y: 0, @@ -82,7 +82,7 @@ test('convertSavedDashboardPanelToPanelState does not include undefined id', () version: '7.0.0', }; - const converted = convertSavedDashboardPanelToPanelState(savedDashboardPanel, false); + const converted = convertSavedDashboardPanelToPanelState(savedDashboardPanel); expect(converted.hasOwnProperty('savedObjectId')).toBe(false); }); @@ -103,7 +103,7 @@ test('convertPanelStateToSavedDashboardPanel', () => { type: 'search', }; - expect(convertPanelStateToSavedDashboardPanel(dashboardPanel)).toEqual({ + expect(convertPanelStateToSavedDashboardPanel(dashboardPanel, '6.3.0')).toEqual({ type: 'search', embeddableConfig: { something: 'hi!', @@ -137,6 +137,6 @@ test('convertPanelStateToSavedDashboardPanel will not add an undefined id when n type: 'search', }; - const converted = convertPanelStateToSavedDashboardPanel(dashboardPanel); + const converted = convertPanelStateToSavedDashboardPanel(dashboardPanel, '8.0.0'); expect(converted.hasOwnProperty('id')).toBe(false); }); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/lib/embeddable_saved_object_converters.ts b/src/legacy/core_plugins/kibana/public/dashboard/lib/embeddable_saved_object_converters.ts index 4a3bc3b2281069..2d42609e1e25fe 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/lib/embeddable_saved_object_converters.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/lib/embeddable_saved_object_converters.ts @@ -18,12 +18,10 @@ */ import { omit } from 'lodash'; import { DashboardPanelState } from 'src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public'; -import chrome from 'ui/chrome'; import { SavedDashboardPanel } from '../types'; export function convertSavedDashboardPanelToPanelState( - savedDashboardPanel: SavedDashboardPanel, - useMargins: boolean + savedDashboardPanel: SavedDashboardPanel ): DashboardPanelState { return { type: savedDashboardPanel.type, @@ -38,13 +36,14 @@ export function convertSavedDashboardPanelToPanelState( } export function convertPanelStateToSavedDashboardPanel( - panelState: DashboardPanelState + panelState: DashboardPanelState, + version: string ): SavedDashboardPanel { const customTitle: string | undefined = panelState.explicitInput.title ? (panelState.explicitInput.title as string) : undefined; return { - version: chrome.getKibanaVersion(), + version, type: panelState.type, gridData: panelState.gridData, panelIndex: panelState.explicitInput.id, diff --git a/src/legacy/core_plugins/kibana/public/dashboard/lib/migrate_app_state.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/lib/migrate_app_state.test.ts index 10c27226300a58..4aa2461bb65930 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/lib/migrate_app_state.test.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/lib/migrate_app_state.test.ts @@ -43,7 +43,7 @@ test('migrate app state from 6.0', async () => { getQueryParamName: () => 'a', save: mockSave, }; - migrateAppState(appState); + migrateAppState(appState, '8.0'); expect(appState.uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; @@ -58,6 +58,7 @@ test('migrate app state from 6.0', async () => { }); test('migrate sort from 6.1', async () => { + const TARGET_VERSION = '8.0'; const mockSave = jest.fn(); const appState = { uiState: { @@ -80,7 +81,7 @@ test('migrate sort from 6.1', async () => { save: mockSave, useMargins: false, }; - migrateAppState(appState); + migrateAppState(appState, TARGET_VERSION); expect(appState.uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; @@ -112,7 +113,7 @@ test('migrates 6.0 even when uiState does not exist', async () => { getQueryParamName: () => 'a', save: mockSave, }; - migrateAppState(appState); + migrateAppState(appState, '8.0'); expect((appState as any).uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; @@ -147,7 +148,7 @@ test('6.2 migration adjusts w & h without margins', async () => { save: mockSave, useMargins: false, }; - migrateAppState(appState); + migrateAppState(appState, '8.0'); expect((appState as any).uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; @@ -184,7 +185,7 @@ test('6.2 migration adjusts w & h with margins', async () => { save: mockSave, useMargins: true, }; - migrateAppState(appState); + migrateAppState(appState, '8.0'); expect((appState as any).uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/lib/migrate_app_state.ts b/src/legacy/core_plugins/kibana/public/dashboard/lib/migrate_app_state.ts index 9bd93029f06d88..c4ad754548459d 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/lib/migrate_app_state.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/lib/migrate_app_state.ts @@ -18,7 +18,6 @@ */ import semver from 'semver'; -import chrome from 'ui/chrome'; import { i18n } from '@kbn/i18n'; import { createUiStatsReporter, METRIC_TYPE } from '../../../../ui_metric/public'; import { @@ -37,7 +36,10 @@ import { migratePanelsTo730 } from '../migrations/migrate_to_730_panels'; * * Once we hit a major version, we can remove support for older style URLs and get rid of this logic. */ -export function migrateAppState(appState: { [key: string]: unknown } | DashboardAppState) { +export function migrateAppState( + appState: { [key: string]: unknown } | DashboardAppState, + kibanaVersion: string +) { if (!appState.panels) { throw new Error( i18n.translate('kbn.dashboard.panel.invalidData', { @@ -73,7 +75,7 @@ export function migrateAppState(appState: { [key: string]: unknown } | Dashboard | SavedDashboardPanel630 | SavedDashboardPanel640To720 >, - chrome.getKibanaVersion(), + kibanaVersion, appState.useMargins, appState.uiState ); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/lib/save_dashboard.ts b/src/legacy/core_plugins/kibana/public/dashboard/lib/save_dashboard.ts index 168f320b5ea7ec..e0d82373d3ad9d 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/lib/save_dashboard.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/lib/save_dashboard.ts @@ -17,8 +17,8 @@ * under the License. */ -import { SaveOptions } from 'ui/saved_objects/saved_object'; -import { Timefilter } from 'ui/timefilter'; +import { TimefilterContract } from 'src/plugins/data/public'; +import { SaveOptions } from '../legacy_imports'; import { updateSavedDashboard } from './update_saved_dashboard'; import { DashboardStateManager } from '../dashboard_state_manager'; @@ -32,7 +32,7 @@ import { DashboardStateManager } from '../dashboard_state_manager'; */ export function saveDashboard( toJson: (obj: any) => string, - timeFilter: Timefilter, + timeFilter: TimefilterContract, dashboardStateManager: DashboardStateManager, saveOptions: SaveOptions ): Promise { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/lib/update_saved_dashboard.ts b/src/legacy/core_plugins/kibana/public/dashboard/lib/update_saved_dashboard.ts index 707b5a0f5f5f57..ce9096b3a56f0c 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/lib/update_saved_dashboard.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/lib/update_saved_dashboard.ts @@ -18,16 +18,15 @@ */ import _ from 'lodash'; -import { AppState } from 'ui/state_management/app_state'; -import { Timefilter } from 'ui/timefilter'; -import { RefreshInterval } from 'src/plugins/data/public'; +import { RefreshInterval, TimefilterContract } from 'src/plugins/data/public'; +import { AppState } from '../legacy_imports'; import { FilterUtils } from './filter_utils'; import { SavedObjectDashboard } from '../saved_dashboard/saved_dashboard'; export function updateSavedDashboard( savedDashboard: SavedObjectDashboard, appState: AppState, - timeFilter: Timefilter, + timeFilter: TimefilterContract, toJson: (object: T) => string ) { savedDashboard.title = appState.title; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/listing/__snapshots__/dashboard_listing.test.js.snap b/src/legacy/core_plugins/kibana/public/dashboard/listing/__snapshots__/dashboard_listing.test.js.snap index 1ed05035f5f4ce..b2f004568841a3 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/listing/__snapshots__/dashboard_listing.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/dashboard/listing/__snapshots__/dashboard_listing.test.js.snap @@ -1,533 +1,545 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`after fetch hideWriteControls 1`] = ` - - - - - } - /> -
- } - tableColumns={ - Array [ - Object { - "field": "title", - "name": "Title", - "render": [Function], - "sortable": true, - }, + + + + + + } + /> +
+ } + tableColumns={ + Array [ + Object { + "field": "title", + "name": "Title", + "render": [Function], + "sortable": true, + }, + Object { + "dataType": "string", + "field": "description", + "name": "Description", + "sortable": true, + }, + ] + } + tableListTitle="Dashboards" + toastNotifications={Object {}} + uiSettings={ Object { - "dataType": "string", - "field": "description", - "name": "Description", - "sortable": true, - }, - ] - } - tableListTitle="Dashboards" - toastNotifications={Object {}} - uiSettings={ - Object { - "get": [MockFunction], + "get": [MockFunction], + } } - } -/> + /> + `; exports[`after fetch initialFilter 1`] = ` - - - - - } - body={ - -

+ + + -

-

- - - , + + } + body={ + +

+ +

+

+ + + , + } } - } + /> +

+
+ } + iconType="dashboardApp" + title={ +

+ -

- - } - iconType="dashboardApp" - title={ -

- -

- } - /> - - } - tableColumns={ - Array [ - Object { - "field": "title", - "name": "Title", - "render": [Function], - "sortable": true, - }, +

+ } + /> + + } + tableColumns={ + Array [ + Object { + "field": "title", + "name": "Title", + "render": [Function], + "sortable": true, + }, + Object { + "dataType": "string", + "field": "description", + "name": "Description", + "sortable": true, + }, + ] + } + tableListTitle="Dashboards" + toastNotifications={Object {}} + uiSettings={ Object { - "dataType": "string", - "field": "description", - "name": "Description", - "sortable": true, - }, - ] - } - tableListTitle="Dashboards" - toastNotifications={Object {}} - uiSettings={ - Object { - "get": [MockFunction], + "get": [MockFunction], + } } - } -/> + /> + `; exports[`after fetch renders call to action when no dashboards exist 1`] = ` - - - - - } - body={ - -

+ + + -

-

- - - , + + } + body={ + +

+ +

+

+ + + , + } } - } + /> +

+
+ } + iconType="dashboardApp" + title={ +

+ -

- - } - iconType="dashboardApp" - title={ -

- -

- } - /> - - } - tableColumns={ - Array [ - Object { - "field": "title", - "name": "Title", - "render": [Function], - "sortable": true, - }, +

+ } + /> + + } + tableColumns={ + Array [ + Object { + "field": "title", + "name": "Title", + "render": [Function], + "sortable": true, + }, + Object { + "dataType": "string", + "field": "description", + "name": "Description", + "sortable": true, + }, + ] + } + tableListTitle="Dashboards" + toastNotifications={Object {}} + uiSettings={ Object { - "dataType": "string", - "field": "description", - "name": "Description", - "sortable": true, - }, - ] - } - tableListTitle="Dashboards" - toastNotifications={Object {}} - uiSettings={ - Object { - "get": [MockFunction], + "get": [MockFunction], + } } - } -/> + /> + `; exports[`after fetch renders table rows 1`] = ` - - - - - } - body={ - -

+ + + -

-

- - - , + + } + body={ + +

+ +

+

+ + + , + } } - } + /> +

+
+ } + iconType="dashboardApp" + title={ +

+ -

- - } - iconType="dashboardApp" - title={ -

- -

- } - /> - - } - tableColumns={ - Array [ - Object { - "field": "title", - "name": "Title", - "render": [Function], - "sortable": true, - }, +

+ } + /> + + } + tableColumns={ + Array [ + Object { + "field": "title", + "name": "Title", + "render": [Function], + "sortable": true, + }, + Object { + "dataType": "string", + "field": "description", + "name": "Description", + "sortable": true, + }, + ] + } + tableListTitle="Dashboards" + toastNotifications={Object {}} + uiSettings={ Object { - "dataType": "string", - "field": "description", - "name": "Description", - "sortable": true, - }, - ] - } - tableListTitle="Dashboards" - toastNotifications={Object {}} - uiSettings={ - Object { - "get": [MockFunction], + "get": [MockFunction], + } } - } -/> + /> + `; exports[`after fetch renders warning when listingLimit is exceeded 1`] = ` - - - - - } - body={ - -

+ + + -

-

- - - , + + } + body={ + +

+ +

+

+ + + , + } } - } + /> +

+
+ } + iconType="dashboardApp" + title={ +

+ -

- - } - iconType="dashboardApp" - title={ -

- -

- } - /> - - } - tableColumns={ - Array [ - Object { - "field": "title", - "name": "Title", - "render": [Function], - "sortable": true, - }, +

+ } + /> + + } + tableColumns={ + Array [ + Object { + "field": "title", + "name": "Title", + "render": [Function], + "sortable": true, + }, + Object { + "dataType": "string", + "field": "description", + "name": "Description", + "sortable": true, + }, + ] + } + tableListTitle="Dashboards" + toastNotifications={Object {}} + uiSettings={ Object { - "dataType": "string", - "field": "description", - "name": "Description", - "sortable": true, - }, - ] - } - tableListTitle="Dashboards" - toastNotifications={Object {}} - uiSettings={ - Object { - "get": [MockFunction], + "get": [MockFunction], + } } - } -/> + /> + `; exports[`renders empty page in before initial fetch to avoid flickering 1`] = ` - - - - - } - body={ - -

+ + + -

-

- - - , + + } + body={ + +

+ +

+

+ + + , + } } - } + /> +

+
+ } + iconType="dashboardApp" + title={ +

+ -

- - } - iconType="dashboardApp" - title={ -

- -

- } - /> - - } - tableColumns={ - Array [ - Object { - "field": "title", - "name": "Title", - "render": [Function], - "sortable": true, - }, +

+ } + /> + + } + tableColumns={ + Array [ + Object { + "field": "title", + "name": "Title", + "render": [Function], + "sortable": true, + }, + Object { + "dataType": "string", + "field": "description", + "name": "Description", + "sortable": true, + }, + ] + } + tableListTitle="Dashboards" + toastNotifications={Object {}} + uiSettings={ Object { - "dataType": "string", - "field": "description", - "name": "Description", - "sortable": true, - }, - ] - } - tableListTitle="Dashboards" - toastNotifications={Object {}} - uiSettings={ - Object { - "get": [MockFunction], + "get": [MockFunction], + } } - } -/> + /> + `; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js index c222fcd3c928ce..98581223afa461 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js @@ -19,7 +19,7 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; -import { FormattedMessage } from '@kbn/i18n/react'; +import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { EuiLink, EuiButton, EuiEmptyPrompt } from '@elastic/eui'; @@ -41,27 +41,29 @@ export class DashboardListing extends React.Component { render() { return ( - + + + ); } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts b/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts new file mode 100644 index 00000000000000..32f09c3eeab852 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts @@ -0,0 +1,151 @@ +/* + * 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 { + App, + CoreSetup, + CoreStart, + LegacyCoreStart, + Plugin, + SavedObjectsClientContract, +} from 'kibana/public'; +import { i18n } from '@kbn/i18n'; +import { RenderDeps } from './application'; +import { LocalApplicationService } from '../local_application_service'; +import { DataStart } from '../../../data/public'; +import { DataPublicPluginStart as NpDataStart } from '../../../../../plugins/data/public'; +import { EmbeddablePublicPlugin } from '../../../../../plugins/embeddable/public'; +import { Storage } from '../../../../../plugins/kibana_utils/public'; +import { NavigationStart } from '../../../navigation/public'; +import { DashboardConstants } from './dashboard_constants'; +import { + FeatureCatalogueCategory, + FeatureCatalogueSetup, +} from '../../../../../plugins/feature_catalogue/public'; +import { SharePluginStart } from '../../../../../plugins/share/public'; + +export interface LegacyAngularInjectedDependencies { + dashboardConfig: any; + savedObjectRegistry: any; + savedDashboards: any; +} + +export interface DashboardPluginStartDependencies { + data: DataStart; + npData: NpDataStart; + embeddables: ReturnType; + navigation: NavigationStart; + share: SharePluginStart; +} + +export interface DashboardPluginSetupDependencies { + __LEGACY: { + getAngularDependencies: () => Promise; + localApplicationService: LocalApplicationService; + }; + feature_catalogue: FeatureCatalogueSetup; +} + +export class DashboardPlugin implements Plugin { + private startDependencies: { + dataStart: DataStart; + npDataStart: NpDataStart; + savedObjectsClient: SavedObjectsClientContract; + embeddables: ReturnType; + navigation: NavigationStart; + share: SharePluginStart; + } | null = null; + + public setup( + core: CoreSetup, + { + __LEGACY: { localApplicationService, getAngularDependencies, ...legacyServices }, + feature_catalogue, + }: DashboardPluginSetupDependencies + ) { + const app: App = { + id: '', + title: 'Dashboards', + mount: async ({ core: contextCore }, params) => { + if (this.startDependencies === null) { + throw new Error('not started yet'); + } + const { + dataStart, + savedObjectsClient, + embeddables, + navigation, + share, + npDataStart, + } = this.startDependencies; + const angularDependencies = await getAngularDependencies(); + const deps: RenderDeps = { + core: contextCore as LegacyCoreStart, + ...legacyServices, + ...angularDependencies, + navigation, + dataStart, + share, + npDataStart, + indexPatterns: dataStart.indexPatterns.indexPatterns, + savedObjectsClient, + chrome: contextCore.chrome, + addBasePath: contextCore.http.basePath.prepend, + uiSettings: contextCore.uiSettings, + savedQueryService: dataStart.search.services.savedQueryService, + embeddables, + dashboardCapabilities: contextCore.application.capabilities.dashboard, + localStorage: new Storage(localStorage), + }; + const { renderApp } = await import('./application'); + return renderApp(params.element, params.appBasePath, deps); + }, + }; + localApplicationService.register({ ...app, id: 'dashboard' }); + localApplicationService.register({ ...app, id: 'dashboards' }); + + feature_catalogue.register({ + id: 'dashboard', + title: i18n.translate('kbn.dashboard.featureCatalogue.dashboardTitle', { + defaultMessage: 'Dashboard', + }), + description: i18n.translate('kbn.dashboard.featureCatalogue.dashboardDescription', { + defaultMessage: 'Display and share a collection of visualizations and saved searches.', + }), + icon: 'dashboardApp', + path: `/app/kibana#${DashboardConstants.LANDING_PAGE_PATH}`, + showOnHomePage: true, + category: FeatureCatalogueCategory.DATA, + }); + } + + start( + { savedObjects: { client: savedObjectsClient } }: CoreStart, + { data: dataStart, embeddables, navigation, npData, share }: DashboardPluginStartDependencies + ) { + this.startDependencies = { + dataStart, + npDataStart: npData, + savedObjectsClient, + embeddables, + navigation, + share, + }; + } +} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.test.js b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.test.js index 153a049276ceee..aa7e219d759632 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.test.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.test.js @@ -17,9 +17,16 @@ * under the License. */ + import React from 'react'; import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; +jest.mock('../legacy_imports', () => ({ + SavedObjectSaveModal: () => null +})); + +jest.mock('ui/new_platform'); + import { DashboardSaveModal } from './save_modal'; test('renders DashboardSaveModal', () => { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.tsx b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.tsx index 47455f04ba8091..0640b2be431be9 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.tsx @@ -19,10 +19,10 @@ import React, { Fragment } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; - -import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; import { EuiFormRow, EuiTextArea, EuiSwitch } from '@elastic/eui'; +import { SavedObjectSaveModal } from '../legacy_imports'; + interface SaveOptions { newTitle: string; newDescription: string; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/show_clone_modal.tsx b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/show_clone_modal.tsx index c3cd5621b2c888..af1020e01e0c52 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/show_clone_modal.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/show_clone_modal.tsx @@ -17,10 +17,10 @@ * under the License. */ -import { I18nContext } from 'ui/i18n'; import React from 'react'; import ReactDOM from 'react-dom'; import { i18n } from '@kbn/i18n'; +import { I18nProvider } from '@kbn/i18n/react'; import { DashboardCloneModal } from './clone_modal'; export function showCloneModal( @@ -54,7 +54,7 @@ export function showCloneModal( }; document.body.appendChild(container); const element = ( - + - + ); ReactDOM.render(element, container); } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/show_options_popover.tsx b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/show_options_popover.tsx index 8640d7dbc6bdca..7c23e4808fbea3 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/show_options_popover.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/show_options_popover.tsx @@ -19,9 +19,9 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { I18nContext } from 'ui/i18n'; - +import { I18nProvider } from '@kbn/i18n/react'; import { EuiWrappingPopover } from '@elastic/eui'; + import { OptionsMenu } from './options'; let isOpen = false; @@ -55,7 +55,7 @@ export function showOptionsPopover({ document.body.appendChild(container); const element = ( - + - + ); ReactDOM.render(element, container); } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/types.ts b/src/legacy/core_plugins/kibana/public/dashboard/types.ts index 3c2c87a502da46..371274401739e0 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/types.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/types.ts @@ -17,9 +17,8 @@ * under the License. */ -import { AppState } from 'ui/state_management/app_state'; -import { AppState as TAppState } from 'ui/state_management/app_state'; import { ViewMode } from 'src/plugins/embeddable/public'; +import { AppState } from './legacy_imports'; import { RawSavedDashboardPanelTo60, RawSavedDashboardPanel610, @@ -153,5 +152,5 @@ export type AddFilterFn = ( operator: string; index: string; }, - appState: TAppState + appState: AppState ) => void; diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/angular/discover.js index 20a05e17d16d65..ba74ea069c4ab7 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/discover.js @@ -57,9 +57,11 @@ import { vislibSeriesResponseHandlerProvider, Vis, SavedObjectSaveModal, + ensureDefaultIndexPattern, } from '../kibana_services'; const { + core, chrome, docTitle, FilterBarQueryFilterProvider, @@ -72,7 +74,6 @@ const { } = getServices(); import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../breadcrumbs'; -import { extractTimeFilter, changeTimeFilter } from '../../../../data/public'; import { start as data } from '../../../../data/public/legacy'; import { generateFilters } from '../../../../../../plugins/data/public'; @@ -91,7 +92,6 @@ const app = uiModules.get('apps/discover', [ uiRoutes .defaults(/^\/discover(\/|$)/, { - requireDefaultIndex: true, requireUICapability: 'discover.show', k7Breadcrumbs: ($route, $injector) => $injector.invoke( @@ -119,50 +119,53 @@ uiRoutes template: indexTemplate, reloadOnSearch: false, resolve: { - ip: function (Promise, indexPatterns, config, Private) { + savedObjects: function (Promise, indexPatterns, config, Private, $rootScope, kbnUrl, redirectWhenMissing, savedSearches, $route) { const State = Private(StateProvider); - return indexPatterns.getCache().then((savedObjects)=> { - /** - * In making the indexPattern modifiable it was placed in appState. Unfortunately, - * the load order of AppState conflicts with the load order of many other things - * so in order to get the name of the index we should use, and to switch to the - * default if necessary, we parse the appState with a temporary State object and - * then destroy it immediatly after we're done - * - * @type {State} - */ - const state = new State('_a', {}); - - const specified = !!state.index; - const exists = _.findIndex(savedObjects, o => o.id === state.index) > -1; - const id = exists ? state.index : config.get('defaultIndex'); - state.destroy(); + const savedSearchId = $route.current.params.id; + return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl).then(() => { return Promise.props({ - list: savedObjects, - loaded: indexPatterns.get(id), - stateVal: state.index, - stateValFound: specified && exists + ip: indexPatterns.getCache().then((savedObjects) => { + /** + * In making the indexPattern modifiable it was placed in appState. Unfortunately, + * the load order of AppState conflicts with the load order of many other things + * so in order to get the name of the index we should use, and to switch to the + * default if necessary, we parse the appState with a temporary State object and + * then destroy it immediatly after we're done + * + * @type {State} + */ + const state = new State('_a', {}); + + const specified = !!state.index; + const exists = _.findIndex(savedObjects, o => o.id === state.index) > -1; + const id = exists ? state.index : config.get('defaultIndex'); + state.destroy(); + + return Promise.props({ + list: savedObjects, + loaded: indexPatterns.get(id), + stateVal: state.index, + stateValFound: specified && exists + }); + }), + savedSearch: savedSearches.get(savedSearchId) + .then((savedSearch) => { + if (savedSearchId) { + chrome.recentlyAccessed.add( + savedSearch.getFullPath(), + savedSearch.title, + savedSearchId); + } + return savedSearch; + }) + .catch(redirectWhenMissing({ + 'search': '/discover', + 'index-pattern': '/management/kibana/objects/savedSearches/' + $route.current.params.id + })) }); }); }, - savedSearch: function (redirectWhenMissing, savedSearches, $route) { - const savedSearchId = $route.current.params.id; - return savedSearches.get(savedSearchId) - .then((savedSearch) => { - if (savedSearchId) { - chrome.recentlyAccessed.add( - savedSearch.getFullPath(), - savedSearch.title, - savedSearchId); - } - return savedSearch; - }) - .catch(redirectWhenMissing({ - 'search': '/discover', - 'index-pattern': '/management/kibana/objects/savedSearches/' + $route.current.params.id - })); - } } }); @@ -224,7 +227,7 @@ function discoverController( }; // the saved savedSearch - const savedSearch = $route.current.locals.savedSearch; + const savedSearch = $route.current.locals.savedObjects.savedSearch; let abortController; $scope.$on('$destroy', () => { @@ -417,20 +420,6 @@ function discoverController( queryFilter.setFilters(filters); }; - $scope.applyFilters = filters => { - const { timeRangeFilter, restOfFilters } = extractTimeFilter($scope.indexPattern.timeFieldName, filters); - queryFilter.addFilters(restOfFilters); - if (timeRangeFilter) changeTimeFilter(timefilter, timeRangeFilter); - - $scope.state.$newFilters = []; - }; - - $scope.$watch('state.$newFilters', (filters = []) => { - if (filters.length === 1) { - $scope.applyFilters(filters); - } - }); - const getFieldCounts = async () => { // the field counts aren't set until we have the data back, // so we wait for the fetch to be done before proceeding @@ -539,7 +528,7 @@ function discoverController( sampleSize: config.get('discover:sampleSize'), timefield: isDefaultTypeIndexPattern($scope.indexPattern) && $scope.indexPattern.timeFieldName, savedSearch: savedSearch, - indexPatternList: $route.current.locals.ip.list, + indexPatternList: $route.current.locals.savedObjects.ip.list, }; const shouldSearchOnPageLoad = () => { @@ -1055,7 +1044,7 @@ function discoverController( loaded: loadedIndexPattern, stateVal, stateValFound, - } = $route.current.locals.ip; + } = $route.current.locals.savedObjects.ip; const ownIndexPattern = $scope.searchSource.getOwnField('index'); @@ -1103,12 +1092,12 @@ function discoverController( // Block the UI from loading if the user has loaded a rollup index pattern but it isn't // supported. $scope.isUnsupportedIndexPattern = ( - !isDefaultTypeIndexPattern($route.current.locals.ip.loaded) - && !hasSearchStategyForIndexPattern($route.current.locals.ip.loaded) + !isDefaultTypeIndexPattern($route.current.locals.savedObjects.ip.loaded) + && !hasSearchStategyForIndexPattern($route.current.locals.savedObjects.ip.loaded) ); if ($scope.isUnsupportedIndexPattern) { - $scope.unsupportedIndexPatternType = $route.current.locals.ip.loaded.type; + $scope.unsupportedIndexPatternType = $route.current.locals.savedObjects.ip.loaded.type; return; } diff --git a/src/legacy/core_plugins/kibana/public/discover/breadcrumbs.ts b/src/legacy/core_plugins/kibana/public/discover/breadcrumbs.ts index 51e0dcba1cad0b..6c3856932c96c1 100644 --- a/src/legacy/core_plugins/kibana/public/discover/breadcrumbs.ts +++ b/src/legacy/core_plugins/kibana/public/discover/breadcrumbs.ts @@ -34,7 +34,7 @@ export function getSavedSearchBreadcrumbs($route: any) { return [ ...getRootBreadcrumbs(), { - text: $route.current.locals.savedSearch.id, + text: $route.current.locals.savedObjects.savedSearch.id, }, ]; } 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 61d7933464e7f4..02b08d7fa4b612 100644 --- a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts @@ -46,6 +46,7 @@ import * as docViewsRegistry from 'ui/registry/doc_views'; const services = { // new plattform + core: npStart.core, addBasePath: npStart.core.http.basePath.prepend, capabilities: npStart.core.application.capabilities, chrome: npStart.core.chrome, @@ -108,6 +109,7 @@ export { getUnhashableStatesProvider } from 'ui/state_management/state_hashing'; export { tabifyAggResponse } from 'ui/agg_response/tabify'; // @ts-ignore export { vislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib'; +export { ensureDefaultIndexPattern } from 'ui/legacy_compat'; export { unhashUrl } from 'ui/state_management/state_hashing'; // EXPORT types diff --git a/src/legacy/core_plugins/kibana/public/management/index.js b/src/legacy/core_plugins/kibana/public/management/index.js index c0949318e92530..83fc8e4db9b558 100644 --- a/src/legacy/core_plugins/kibana/public/management/index.js +++ b/src/legacy/core_plugins/kibana/public/management/index.js @@ -28,7 +28,6 @@ import { I18nContext } from 'ui/i18n'; import { uiModules } from 'ui/modules'; import appTemplate from './app.html'; import landingTemplate from './landing.html'; -import { capabilities } from 'ui/capabilities'; import { management, SidebarNav, MANAGEMENT_BREADCRUMB } from 'ui/management'; import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; import { timefilter } from 'ui/timefilter'; @@ -50,13 +49,6 @@ uiRoutes redirectTo: '/management' }); -require('./route_setup/load_default')({ - whenMissingRedirectTo: () => { - const canManageIndexPatterns = capabilities.get().management.kibana.index_patterns; - return canManageIndexPatterns ? '/management/kibana/index_pattern' : '/home'; - } -}); - export function updateLandingPage(version) { const node = document.getElementById(LANDING_ID); if (!node) { diff --git a/src/legacy/core_plugins/kibana/public/management/route_setup/load_default.js b/src/legacy/core_plugins/kibana/public/management/route_setup/load_default.js deleted file mode 100644 index f797acbe8888e7..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/route_setup/load_default.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import React from 'react'; -import { banners } from 'ui/notify'; -import { NoDefaultIndexPattern } from 'ui/index_patterns'; -import uiRoutes from 'ui/routes'; -import { - EuiCallOut, -} from '@elastic/eui'; -import { clearTimeout } from 'timers'; -import { i18n } from '@kbn/i18n'; - -let bannerId; -let timeoutId; - -function displayBanner() { - clearTimeout(timeoutId); - - // Avoid being hostile to new users who don't have an index pattern setup yet - // give them a friendly info message instead of a terse error message - bannerId = banners.set({ - id: bannerId, // initially undefined, but reused after first set - component: ( - - ) - }); - - // hide the message after the user has had a chance to acknowledge it -- so it doesn't permanently stick around - timeoutId = setTimeout(() => { - banners.remove(bannerId); - timeoutId = undefined; - }, 15000); -} - -// eslint-disable-next-line import/no-default-export -export default function (opts) { - opts = opts || {}; - const whenMissingRedirectTo = opts.whenMissingRedirectTo || null; - - uiRoutes - .addSetupWork(function loadDefaultIndexPattern(Promise, $route, config, indexPatterns) { - const route = _.get($route, 'current.$$route'); - - if (!route.requireDefaultIndex) { - return; - } - - return indexPatterns.getIds() - .then(function (patterns) { - let defaultId = config.get('defaultIndex'); - let defined = !!defaultId; - const exists = _.contains(patterns, defaultId); - - if (defined && !exists) { - config.remove('defaultIndex'); - defaultId = defined = false; - } - - if (!defined) { - // If there is any index pattern created, set the first as default - if (patterns.length >= 1) { - defaultId = patterns[0]; - config.set('defaultIndex', defaultId); - } else { - throw new NoDefaultIndexPattern(); - } - } - }); - }) - .afterWork( - // success - null, - - // failure - function (err, kbnUrl) { - const hasDefault = !(err instanceof NoDefaultIndexPattern); - if (hasDefault || !whenMissingRedirectTo) throw err; // rethrow - - kbnUrl.change(whenMissingRedirectTo()); - - displayBanner(); - } - ); -} diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js index 619903e93c1270..821883655766ba 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js @@ -24,6 +24,7 @@ import '../saved_visualizations/saved_visualizations'; import './visualization_editor'; import './visualization'; +import { ensureDefaultIndexPattern } from 'ui/legacy_compat'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { migrateAppState } from './lib'; @@ -49,6 +50,7 @@ import { } from '../kibana_services'; const { + core, capabilities, chrome, chromeLegacy, @@ -71,7 +73,7 @@ uiRoutes template: editorTemplate, k7Breadcrumbs: getCreateBreadcrumbs, resolve: { - savedVis: function (savedVisualizations, redirectWhenMissing, $route) { + savedVis: function (savedVisualizations, redirectWhenMissing, $route, $rootScope, kbnUrl) { const visTypes = visualizations.types.all(); const visType = _.find(visTypes, { name: $route.current.params.type }); const shouldHaveIndex = visType.requiresSearch && visType.options.showIndexSelection; @@ -84,7 +86,7 @@ uiRoutes ); } - return savedVisualizations.get($route.current.params) + return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl).then(() => savedVisualizations.get($route.current.params)) .then(savedVis => { if (savedVis.vis.type.setup) { return savedVis.vis.type.setup(savedVis) @@ -102,28 +104,33 @@ uiRoutes template: editorTemplate, k7Breadcrumbs: getEditBreadcrumbs, resolve: { - savedVis: function (savedVisualizations, redirectWhenMissing, $route) { - return savedVisualizations.get($route.current.params.id) + savedVis: function (savedVisualizations, redirectWhenMissing, $route, $rootScope, kbnUrl) { + return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl) + .then(() => savedVisualizations.get($route.current.params.id)) .then((savedVis) => { chrome.recentlyAccessed.add( savedVis.getFullPath(), savedVis.title, - savedVis.id); + savedVis.id + ); return savedVis; }) .then(savedVis => { if (savedVis.vis.type.setup) { - return savedVis.vis.type.setup(savedVis) - .catch(() => savedVis); + return savedVis.vis.type.setup(savedVis).catch(() => savedVis); } return savedVis; }) - .catch(redirectWhenMissing({ - 'visualization': '/visualize', - 'search': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, - 'index-pattern': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, - 'index-pattern-field': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id - })); + .catch( + redirectWhenMissing({ + visualization: '/visualize', + search: '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, + 'index-pattern': + '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, + 'index-pattern-field': + '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, + }) + ); } } }); diff --git a/src/legacy/core_plugins/kibana/public/visualize/index.js b/src/legacy/core_plugins/kibana/public/visualize/index.js index 592a355a71b0d7..57707f63213768 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/index.js +++ b/src/legacy/core_plugins/kibana/public/visualize/index.js @@ -17,6 +17,7 @@ * under the License. */ +import { ensureDefaultIndexPattern } from 'ui/legacy_compat'; import './editor/editor'; import { i18n } from '@kbn/i18n'; import './saved_visualizations/_saved_vis'; @@ -32,7 +33,6 @@ const { FeatureCatalogueRegistryProvider, uiRoutes } = getServices(); uiRoutes .defaults(/visualize/, { - requireDefaultIndex: true, requireUICapability: 'visualize.show', badge: uiCapabilities => { if (uiCapabilities.visualize.save) { @@ -57,6 +57,7 @@ uiRoutes controllerAs: 'listingController', resolve: { createNewVis: () => false, + hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(getServices().core, getServices().data, $rootScope, kbnUrl) }, }) .when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, { @@ -66,6 +67,7 @@ uiRoutes controllerAs: 'listingController', resolve: { createNewVis: () => true, + hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(getServices().core, getServices().data, $rootScope, kbnUrl) }, }); diff --git a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts index 3be49971cf4c94..e2201cdca9a576 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts @@ -60,6 +60,7 @@ const services = { savedObjectsClient: npStart.core.savedObjects.client, toastNotifications: npStart.core.notifications.toasts, uiSettings: npStart.core.uiSettings, + core: npStart.core, share: npStart.plugins.share, data, diff --git a/src/legacy/ui/public/capabilities/route_setup.ts b/src/legacy/ui/public/capabilities/route_setup.ts deleted file mode 100644 index c7817b8cc5748c..00000000000000 --- a/src/legacy/ui/public/capabilities/route_setup.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { get } from 'lodash'; -import chrome from 'ui/chrome'; -import uiRoutes from 'ui/routes'; -import { UICapabilities } from '.'; - -uiRoutes.addSetupWork( - (uiCapabilities: UICapabilities, kbnBaseUrl: string, $route: any, kbnUrl: any) => { - const route = get($route, 'current.$$route') as any; - if (!route.requireUICapability) { - return; - } - - if (!get(uiCapabilities, route.requireUICapability)) { - const url = chrome.addBasePath(`${kbnBaseUrl}#/home`); - kbnUrl.redirect(url); - throw uiRoutes.WAIT_FOR_URL_CHANGE_TOKEN; - } - } -); diff --git a/src/legacy/ui/public/chrome/api/angular.js b/src/legacy/ui/public/chrome/api/angular.js index e6457fec936330..73d50a83e11a5a 100644 --- a/src/legacy/ui/public/chrome/api/angular.js +++ b/src/legacy/ui/public/chrome/api/angular.js @@ -21,13 +21,15 @@ import { uiModules } from '../../modules'; import { directivesProvider } from '../directives'; import { registerSubUrlHooks } from './sub_url_hooks'; +import { start as data } from '../../../../core_plugins/data/public/legacy'; import { configureAppAngularModule } from 'ui/legacy_compat'; +import { npStart } from '../../new_platform/new_platform'; export function initAngularApi(chrome, internals) { chrome.setupAngular = function () { const kibana = uiModules.get('kibana'); - configureAppAngularModule(kibana); + configureAppAngularModule(kibana, npStart.core, data, false); kibana.value('chrome', chrome); diff --git a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js index 9c4cee6b05db04..a1d48caf3f4898 100644 --- a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js +++ b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js @@ -75,8 +75,7 @@ export function createTopNavDirective() { module.directive('kbnTopNav', createTopNavDirective); -export function createTopNavHelper(reactDirective) { - const { TopNavMenu } = navigation.ui; +export const createTopNavHelper = ({ TopNavMenu }) => (reactDirective) => { return reactDirective( wrapInI18nContext(TopNavMenu), [ @@ -116,6 +115,6 @@ export function createTopNavHelper(reactDirective) { 'showAutoRefreshOnly', ], ); -} +}; -module.directive('kbnTopNavHelper', createTopNavHelper); +module.directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); diff --git a/src/legacy/ui/public/legacy_compat/angular_config.tsx b/src/legacy/ui/public/legacy_compat/angular_config.tsx index 788718e8484308..6e9f5c85aa1b2a 100644 --- a/src/legacy/ui/public/legacy_compat/angular_config.tsx +++ b/src/legacy/ui/public/legacy_compat/angular_config.tsx @@ -28,7 +28,7 @@ import { IRootScopeService, } from 'angular'; import $ from 'jquery'; -import { cloneDeep, forOwn, set } from 'lodash'; +import _, { cloneDeep, forOwn, get, set } from 'lodash'; import React, { Fragment } from 'react'; import * as Rx from 'rxjs'; @@ -37,27 +37,43 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { CoreStart, LegacyCoreStart } from 'kibana/public'; import { fatalError } from 'ui/notify'; -import { capabilities } from 'ui/capabilities'; +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'; -import { npStart } from '../new_platform'; -import { toastNotifications } from '../notify'; // @ts-ignore import { isSystemApiRequest } from '../system_api'; const URL_LIMIT_WARN_WITHIN = 1000; -function isDummyWrapperRoute($route: any) { +/** + * Detects whether a given angular route is a dummy route that doesn't + * require any action. There are two ways this can happen: + * If `outerAngularWrapperRoute` is set on the route config object, + * it means the local application service set up this route on the outer angular + * and the internal routes will handle the hooks. + * + * If angular did not detect a route and it is the local angular, we are currently + * navigating away from a URL controlled by a local angular router and the + * application will get unmounted. In this case the outer router will handle + * the hooks. + * @param $route Injected $route dependency + * @param isLocalAngular Flag whether this is the local angular router + */ +function isDummyRoute($route: any, isLocalAngular: boolean) { return ( - $route.current && $route.current.$$route && $route.current.$$route.outerAngularWrapperRoute + ($route.current && $route.current.$$route && $route.current.$$route.outerAngularWrapperRoute) || + (!$route.current && isLocalAngular) ); } -export const configureAppAngularModule = (angularModule: IModule) => { - const newPlatform = npStart.core; +export const configureAppAngularModule = ( + angularModule: IModule, + newPlatform: LegacyCoreStart, + isLocalAngular: boolean +) => { const legacyMetadata = newPlatform.injectedMetadata.getLegacyMetadata(); forOwn(newPlatform.injectedMetadata.getInjectedVars(), (val, name) => { @@ -73,15 +89,16 @@ export const configureAppAngularModule = (angularModule: IModule) => { .value('buildSha', legacyMetadata.buildSha) .value('serverName', legacyMetadata.serverName) .value('esUrl', getEsUrl(newPlatform)) - .value('uiCapabilities', capabilities.get()) + .value('uiCapabilities', newPlatform.application.capabilities) .config(setupCompileProvider(newPlatform)) .config(setupLocationProvider(newPlatform)) .config($setupXsrfRequestInterceptor(newPlatform)) .run(capture$httpLoadingCount(newPlatform)) - .run($setupBreadcrumbsAutoClear(newPlatform)) - .run($setupBadgeAutoClear(newPlatform)) - .run($setupHelpExtensionAutoClear(newPlatform)) - .run($setupUrlOverflowHandling(newPlatform)); + .run($setupBreadcrumbsAutoClear(newPlatform, isLocalAngular)) + .run($setupBadgeAutoClear(newPlatform, isLocalAngular)) + .run($setupHelpExtensionAutoClear(newPlatform, isLocalAngular)) + .run($setupUrlOverflowHandling(newPlatform, isLocalAngular)) + .run($setupUICapabilityRedirect(newPlatform)); }; const getEsUrl = (newPlatform: CoreStart) => { @@ -168,12 +185,42 @@ const capture$httpLoadingCount = (newPlatform: CoreStart) => ( ); }; +/** + * integrates with angular to automatically redirect to home if required + * capability is not met + */ +const $setupUICapabilityRedirect = (newPlatform: CoreStart) => ( + $rootScope: IRootScopeService, + $injector: any +) => { + const isKibanaAppRoute = window.location.pathname.endsWith('/app/kibana'); + // this feature only works within kibana app for now after everything is + // switched to the application service, this can be changed to handle all + // apps. + if (!isKibanaAppRoute) { + return; + } + $rootScope.$on( + '$routeChangeStart', + (event, { $$route: route }: { $$route?: RouteConfiguration } = {}) => { + if (!route || !route.requireUICapability) { + return; + } + + if (!get(newPlatform.application.capabilities, route.requireUICapability)) { + $injector.get('kbnUrl').change('/home'); + event.preventDefault(); + } + } + ); +}; + /** * internal angular run function that will be called when angular bootstraps and * lets us integrate with the angular router so that we can automatically clear * the breadcrumbs if we switch to a Kibana app that does not use breadcrumbs correctly */ -const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart) => ( +const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart, isLocalAngular: boolean) => ( $rootScope: IRootScopeService, $injector: any ) => { @@ -195,7 +242,7 @@ const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart) => ( }); $rootScope.$on('$routeChangeSuccess', () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } const current = $route.current || {}; @@ -223,7 +270,7 @@ const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart) => ( * lets us integrate with the angular router so that we can automatically clear * the badge if we switch to a Kibana app that does not use the badge correctly */ -const $setupBadgeAutoClear = (newPlatform: CoreStart) => ( +const $setupBadgeAutoClear = (newPlatform: CoreStart, isLocalAngular: boolean) => ( $rootScope: IRootScopeService, $injector: any ) => { @@ -237,7 +284,7 @@ const $setupBadgeAutoClear = (newPlatform: CoreStart) => ( }); $rootScope.$on('$routeChangeSuccess', () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } const current = $route.current || {}; @@ -266,7 +313,7 @@ const $setupBadgeAutoClear = (newPlatform: CoreStart) => ( * the helpExtension if we switch to a Kibana app that does not set its own * helpExtension */ -const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => ( +const $setupHelpExtensionAutoClear = (newPlatform: CoreStart, isLocalAngular: boolean) => ( $rootScope: IRootScopeService, $injector: any ) => { @@ -284,14 +331,14 @@ const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => ( const $route = $injector.has('$route') ? $injector.get('$route') : {}; $rootScope.$on('$routeChangeStart', () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } helpExtensionSetSinceRouteChange = false; }); $rootScope.$on('$routeChangeSuccess', () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } const current = $route.current || {}; @@ -304,7 +351,7 @@ const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => ( }); }; -const $setupUrlOverflowHandling = (newPlatform: CoreStart) => ( +const $setupUrlOverflowHandling = (newPlatform: CoreStart, isLocalAngular: boolean) => ( $location: ILocationService, $rootScope: IRootScopeService, $injector: auto.IInjectorService @@ -312,7 +359,7 @@ const $setupUrlOverflowHandling = (newPlatform: CoreStart) => ( const $route = $injector.has('$route') ? $injector.get('$route') : {}; const urlOverflow = new UrlOverflowService(); const check = () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } // disable long url checks when storing state in session storage @@ -326,7 +373,7 @@ const $setupUrlOverflowHandling = (newPlatform: CoreStart) => ( try { if (urlOverflow.check($location.absUrl()) <= URL_LIMIT_WARN_WITHIN) { - toastNotifications.addWarning({ + newPlatform.notifications.toasts.addWarning({ title: i18n.translate('common.ui.chrome.bigUrlWarningNotificationTitle', { defaultMessage: 'The URL is big and Kibana might stop working', }), diff --git a/src/legacy/ui/public/legacy_compat/ensure_default_index_pattern.tsx b/src/legacy/ui/public/legacy_compat/ensure_default_index_pattern.tsx new file mode 100644 index 00000000000000..98e95865d7325a --- /dev/null +++ b/src/legacy/ui/public/legacy_compat/ensure_default_index_pattern.tsx @@ -0,0 +1,105 @@ +/* + * 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 { contains } from 'lodash'; +import { IRootScopeService } from 'angular'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import { i18n } from '@kbn/i18n'; +import { I18nProvider } from '@kbn/i18n/react'; +import { EuiCallOut } from '@elastic/eui'; +import { CoreStart } from 'kibana/public'; +import { DataStart } from '../../../core_plugins/data/public'; + +let bannerId: string; +let timeoutId: NodeJS.Timeout | undefined; + +/** + * Checks whether a default index pattern is set and exists and defines + * one otherwise. + * + * If there are no index patterns, redirect to management page and show + * banner. In this case the promise returned from this function will never + * resolve to wait for the URL change to happen. + */ +export async function ensureDefaultIndexPattern( + newPlatform: CoreStart, + data: DataStart, + $rootScope: IRootScopeService, + kbnUrl: any +) { + const patterns = await data.indexPatterns.indexPatterns.getIds(); + let defaultId = newPlatform.uiSettings.get('defaultIndex'); + let defined = !!defaultId; + const exists = contains(patterns, defaultId); + + if (defined && !exists) { + newPlatform.uiSettings.remove('defaultIndex'); + defaultId = defined = false; + } + + if (defined) { + return; + } + + // If there is any index pattern created, set the first as default + if (patterns.length >= 1) { + defaultId = patterns[0]; + newPlatform.uiSettings.set('defaultIndex', defaultId); + } else { + const canManageIndexPatterns = + newPlatform.application.capabilities.management.kibana.index_patterns; + const redirectTarget = canManageIndexPatterns ? '/management/kibana/index_pattern' : '/home'; + + if (timeoutId) { + clearTimeout(timeoutId); + } + + // Avoid being hostile to new users who don't have an index pattern setup yet + // give them a friendly info message instead of a terse error message + bannerId = newPlatform.overlays.banners.replace(bannerId, (element: HTMLElement) => { + ReactDOM.render( + + + , + element + ); + return () => ReactDOM.unmountComponentAtNode(element); + }); + + // hide the message after the user has had a chance to acknowledge it -- so it doesn't permanently stick around + timeoutId = setTimeout(() => { + newPlatform.overlays.banners.remove(bannerId); + timeoutId = undefined; + }, 15000); + + kbnUrl.change(redirectTarget); + $rootScope.$digest(); + + // return never-resolving promise to stop resolving and wait for the url change + return new Promise(() => {}); + } +} diff --git a/src/legacy/ui/public/legacy_compat/index.ts b/src/legacy/ui/public/legacy_compat/index.ts index b29056954051ba..ea8932114118e6 100644 --- a/src/legacy/ui/public/legacy_compat/index.ts +++ b/src/legacy/ui/public/legacy_compat/index.ts @@ -18,3 +18,4 @@ */ export { configureAppAngularModule } from './angular_config'; +export { ensureDefaultIndexPattern } from './ensure_default_index_pattern'; diff --git a/src/legacy/ui/public/routes/__tests__/_route_manager.js b/src/legacy/ui/public/routes/__tests__/_route_manager.js index d6d4c869b4b7ea..450bb51f0b0c62 100644 --- a/src/legacy/ui/public/routes/__tests__/_route_manager.js +++ b/src/legacy/ui/public/routes/__tests__/_route_manager.js @@ -119,18 +119,6 @@ describe('routes/route_manager', function () { expect($rp.when.secondCall.args[1]).to.have.property('reloadOnSearch', false); expect($rp.when.lastCall.args[1]).to.have.property('reloadOnSearch', true); }); - - it('sets route.requireDefaultIndex to false by default', function () { - routes.when('/nothing-set'); - routes.when('/no-index-required', { requireDefaultIndex: false }); - routes.when('/index-required', { requireDefaultIndex: true }); - routes.config($rp); - - expect($rp.when.callCount).to.be(3); - expect($rp.when.firstCall.args[1]).to.have.property('requireDefaultIndex', false); - expect($rp.when.secondCall.args[1]).to.have.property('requireDefaultIndex', false); - expect($rp.when.lastCall.args[1]).to.have.property('requireDefaultIndex', true); - }); }); describe('#defaults()', () => { diff --git a/src/legacy/ui/public/routes/route_manager.d.ts b/src/legacy/ui/public/routes/route_manager.d.ts index 56203354f3c203..a5261a7c8ee3a8 100644 --- a/src/legacy/ui/public/routes/route_manager.d.ts +++ b/src/legacy/ui/public/routes/route_manager.d.ts @@ -23,7 +23,7 @@ import { ChromeBreadcrumb } from '../../../../core/public'; -interface RouteConfiguration { +export interface RouteConfiguration { controller?: string | ((...args: any[]) => void); redirectTo?: string; resolveRedirectTo?: (...args: any[]) => void; diff --git a/src/legacy/ui/public/routes/route_manager.js b/src/legacy/ui/public/routes/route_manager.js index ba48984bb45b9d..6444ef66fbe474 100644 --- a/src/legacy/ui/public/routes/route_manager.js +++ b/src/legacy/ui/public/routes/route_manager.js @@ -46,10 +46,6 @@ export default function RouteManager() { route.reloadOnSearch = false; } - if (route.requireDefaultIndex == null) { - route.requireDefaultIndex = false; - } - wrapRouteWithPrep(route, setup); $routeProvider.when(path, route); }); diff --git a/src/legacy/ui/public/state_management/state.js b/src/legacy/ui/public/state_management/state.js index b7623ab0fc5a51..8d55a6929a617a 100644 --- a/src/legacy/ui/public/state_management/state.js +++ b/src/legacy/ui/public/state_management/state.js @@ -42,9 +42,14 @@ import { isStateHash, } from './state_storage'; -export function StateProvider(Private, $rootScope, $location, stateManagementConfig, config, kbnUrl) { +export function StateProvider(Private, $rootScope, $location, stateManagementConfig, config, kbnUrl, $injector) { const Events = Private(EventsProvider); + const isDummyRoute = () => + $injector.has('$route') && + $injector.get('$route').current && + $injector.get('$route').current.outerAngularWrapperRoute; + createLegacyClass(State).inherits(Events); function State( urlParam, @@ -137,7 +142,7 @@ export function StateProvider(Private, $rootScope, $location, stateManagementCon let stash = this._readFromURL(); - // nothing to read from the url? save if ordered to persist + // nothing to read from the url? save if ordered to persist, but only if it's not on a wrapper route if (stash === null) { if (this._persistAcrossApps) { return this.save(); @@ -150,7 +155,7 @@ export function StateProvider(Private, $rootScope, $location, stateManagementCon // apply diff to state from stash, will change state in place via side effect const diffResults = applyDiff(this, stash); - if (diffResults.keys.length) { + if (!isDummyRoute() && diffResults.keys.length) { this.emit('fetch_with_changes', diffResults.keys); } }; @@ -164,6 +169,10 @@ export function StateProvider(Private, $rootScope, $location, stateManagementCon return; } + if (isDummyRoute()) { + return; + } + let stash = this._readFromURL(); const state = this.toObject(); replace = replace || false; diff --git a/src/legacy/ui/public/timefilter/setup_router.test.js b/src/legacy/ui/public/timefilter/setup_router.test.js index 4bc797e5eff00e..f229937c3b435b 100644 --- a/src/legacy/ui/public/timefilter/setup_router.test.js +++ b/src/legacy/ui/public/timefilter/setup_router.test.js @@ -42,9 +42,14 @@ describe('registerTimefilterWithGlobalState()', () => { } }; + const rootScope = { + $on: jest.fn() + }; + registerTimefilterWithGlobalState( timefilter, - globalState + globalState, + rootScope, ); expect(setTime.mock.calls.length).toBe(2); diff --git a/src/legacy/ui/public/timefilter/setup_router.ts b/src/legacy/ui/public/timefilter/setup_router.ts index 0a73378f99cd7d..64105b016fb44c 100644 --- a/src/legacy/ui/public/timefilter/setup_router.ts +++ b/src/legacy/ui/public/timefilter/setup_router.ts @@ -23,6 +23,7 @@ import moment from 'moment'; import { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; import chrome from 'ui/chrome'; import { RefreshInterval, TimeRange, TimefilterContract } from 'src/plugins/data/public'; +import { Subscription } from 'rxjs'; // TODO // remove everything underneath once globalState is no longer an angular service @@ -40,49 +41,62 @@ export function getTimefilterConfig() { }; } -// Currently some parts of Kibana (index patterns, timefilter) rely on addSetupWork in the uiRouter -// and require it to be executed to properly function. -// This function is exposed for applications that do not use uiRoutes like APM -// Kibana issue https://github.com/elastic/kibana/issues/19110 tracks the removal of this dependency on uiRouter -export const registerTimefilterWithGlobalState = _.once( - (timefilter: TimefilterContract, globalState: any, $rootScope: IScope) => { - // settings have to be re-fetched here, to make sure that settings changed by overrideLocalDefault are taken into account. - const config = getTimefilterConfig(); - timefilter.setTime(_.defaults(globalState.time || {}, config.timeDefaults)); - timefilter.setRefreshInterval( - _.defaults(globalState.refreshInterval || {}, config.refreshIntervalDefaults) - ); +export const registerTimefilterWithGlobalStateFactory = ( + timefilter: TimefilterContract, + globalState: any, + $rootScope: IScope +) => { + // settings have to be re-fetched here, to make sure that settings changed by overrideLocalDefault are taken into account. + const config = getTimefilterConfig(); + timefilter.setTime(_.defaults(globalState.time || {}, config.timeDefaults)); + timefilter.setRefreshInterval( + _.defaults(globalState.refreshInterval || {}, config.refreshIntervalDefaults) + ); - globalState.on('fetch_with_changes', () => { - // clone and default to {} in one - const newTime: TimeRange = _.defaults({}, globalState.time, config.timeDefaults); - const newRefreshInterval: RefreshInterval = _.defaults( - {}, - globalState.refreshInterval, - config.refreshIntervalDefaults - ); + globalState.on('fetch_with_changes', () => { + // clone and default to {} in one + const newTime: TimeRange = _.defaults({}, globalState.time, config.timeDefaults); + const newRefreshInterval: RefreshInterval = _.defaults( + {}, + globalState.refreshInterval, + config.refreshIntervalDefaults + ); - if (newTime) { - if (newTime.to) newTime.to = convertISO8601(newTime.to); - if (newTime.from) newTime.from = convertISO8601(newTime.from); - } + if (newTime) { + if (newTime.to) newTime.to = convertISO8601(newTime.to); + if (newTime.from) newTime.from = convertISO8601(newTime.from); + } - timefilter.setTime(newTime); - timefilter.setRefreshInterval(newRefreshInterval); - }); + timefilter.setTime(newTime); + timefilter.setRefreshInterval(newRefreshInterval); + }); - const updateGlobalStateWithTime = () => { - globalState.time = timefilter.getTime(); - globalState.refreshInterval = timefilter.getRefreshInterval(); - globalState.save(); - }; + const updateGlobalStateWithTime = () => { + globalState.time = timefilter.getTime(); + globalState.refreshInterval = timefilter.getRefreshInterval(); + globalState.save(); + }; + const subscriptions = new Subscription(); + subscriptions.add( subscribeWithScope($rootScope, timefilter.getRefreshIntervalUpdate$(), { next: updateGlobalStateWithTime, - }); + }) + ); + subscriptions.add( subscribeWithScope($rootScope, timefilter.getTimeUpdate$(), { next: updateGlobalStateWithTime, - }); - } -); + }) + ); + + $rootScope.$on('$destroy', () => { + subscriptions.unsubscribe(); + }); +}; + +// Currently some parts of Kibana (index patterns, timefilter) rely on addSetupWork in the uiRouter +// and require it to be executed to properly function. +// This function is exposed for applications that do not use uiRoutes like APM +// Kibana issue https://github.com/elastic/kibana/issues/19110 tracks the removal of this dependency on uiRouter +export const registerTimefilterWithGlobalState = _.once(registerTimefilterWithGlobalStateFactory); diff --git a/src/legacy/ui/public/vis/vis_filters/vis_filters.js b/src/legacy/ui/public/vis/vis_filters/vis_filters.js index e879d040125f11..18d633e1b5fb2f 100644 --- a/src/legacy/ui/public/vis/vis_filters/vis_filters.js +++ b/src/legacy/ui/public/vis/vis_filters/vis_filters.js @@ -115,7 +115,6 @@ const VisFiltersProvider = (getAppState, $timeout) => { } }; - return { pushFilters, }; diff --git a/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/_dashboard_viewport.scss b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/_dashboard_viewport.scss index 7cbe1351158776..9575908146d1d8 100644 --- a/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/_dashboard_viewport.scss +++ b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/_dashboard_viewport.scss @@ -1,8 +1,10 @@ .dshDashboardViewport { + height: 100%; width: 100%; background-color: $euiColorEmptyShade; } .dshDashboardViewport-withMargins { width: 100%; + height: 100%; } diff --git a/test/functional/apps/dashboard/embed_mode.js b/test/functional/apps/dashboard/embed_mode.js index 7122d9ff8ca250..9eb5b2c9352d86 100644 --- a/test/functional/apps/dashboard/embed_mode.js +++ b/test/functional/apps/dashboard/embed_mode.js @@ -25,6 +25,7 @@ export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['dashboard', 'common']); const browser = getService('browser'); + const globalNav = getService('globalNav'); describe('embed mode', () => { before(async () => { @@ -38,8 +39,8 @@ export default function ({ getService, getPageObjects }) { }); it('hides the chrome', async () => { - const isChromeVisible = await PageObjects.common.isChromeVisible(); - expect(isChromeVisible).to.be(true); + const globalNavShown = await globalNav.exists(); + expect(globalNavShown).to.be(true); const currentUrl = await browser.getCurrentUrl(); const newUrl = currentUrl + '&embed=true'; @@ -48,8 +49,8 @@ export default function ({ getService, getPageObjects }) { await browser.get(newUrl.toString(), useTimeStamp); await retry.try(async () => { - const isChromeHidden = await PageObjects.common.isChromeHidden(); - expect(isChromeHidden).to.be(true); + const globalNavHidden = !(await globalNav.exists()); + expect(globalNavHidden).to.be(true); }); }); diff --git a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js index 5f7ac218e1b982..4fbba4a5ffd31c 100644 --- a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js @@ -38,6 +38,8 @@ import 'ui/agg_response'; import 'ui/agg_types'; import 'leaflet'; import { npStart } from 'ui/new_platform'; +import { localApplicationService } from 'plugins/kibana/local_application_service'; + import { showAppRedirectNotification } from 'ui/notify'; import { DashboardConstants, createDashboardEditUrl } from 'plugins/kibana/dashboard/dashboard_constants'; @@ -45,6 +47,8 @@ import { DashboardConstants, createDashboardEditUrl } from 'plugins/kibana/dashb uiModules.get('kibana') .config(dashboardConfigProvider => dashboardConfigProvider.turnHideWriteControlsOn()); +localApplicationService.attachToAngular(routes); + routes.enable(); routes.otherwise({ redirectTo: defaultUrl() }); diff --git a/x-pack/legacy/plugins/graph/public/index.ts b/x-pack/legacy/plugins/graph/public/index.ts index 48420d403653f1..833134abff0b60 100644 --- a/x-pack/legacy/plugins/graph/public/index.ts +++ b/x-pack/legacy/plugins/graph/public/index.ts @@ -20,6 +20,7 @@ import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_regis import { npSetup, npStart } from 'ui/new_platform'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { start as data } from '../../../../../src/legacy/core_plugins/data/public/legacy'; +import { start as navigation } from '../../../../../src/legacy/core_plugins/navigation/public/legacy'; import { GraphPlugin } from './plugin'; // @ts-ignore @@ -53,6 +54,7 @@ async function getAngularInjectedDependencies(): Promise; + navigation: NavigationStart; } export interface GraphPluginSetupDependencies { @@ -30,6 +32,7 @@ export interface GraphPluginStartDependencies { export class GraphPlugin implements Plugin { private dataStart: DataStart | null = null; + private navigationStart: NavigationStart | null = null; private npDataStart: ReturnType | null = null; private savedObjectsClient: SavedObjectsClientContract | null = null; private angularDependencies: LegacyAngularInjectedDependencies | null = null; @@ -42,6 +45,7 @@ export class GraphPlugin implements Plugin { const { renderApp } = await import('./render_app'); return renderApp({ ...params, + navigation: this.navigationStart!, npData: this.npDataStart!, savedObjectsClient: this.savedObjectsClient!, xpackInfo, @@ -66,9 +70,9 @@ export class GraphPlugin implements Plugin { start( core: CoreStart, - { data, npData, __LEGACY: { angularDependencies } }: GraphPluginStartDependencies + { data, npData, navigation, __LEGACY: { angularDependencies } }: GraphPluginStartDependencies ) { - // TODO is this really the right way? I though the app context would give us those + this.navigationStart = navigation; this.dataStart = data; this.npDataStart = npData; this.angularDependencies = angularDependencies; diff --git a/x-pack/legacy/plugins/graph/public/render_app.ts b/x-pack/legacy/plugins/graph/public/render_app.ts index a8a86f4d1f850e..18cdf0ddd81b24 100644 --- a/x-pack/legacy/plugins/graph/public/render_app.ts +++ b/x-pack/legacy/plugins/graph/public/render_app.ts @@ -25,6 +25,7 @@ import { DataStart } from 'src/legacy/core_plugins/data/public'; import { AppMountContext, ChromeStart, + LegacyCoreStart, SavedObjectsClientContract, ToastsStart, UiSettingsClientContract, @@ -32,6 +33,7 @@ import { // @ts-ignore import { initGraphApp } from './app'; import { Plugin as DataPlugin } from '../../../../../src/plugins/data/public'; +import { NavigationStart } from '../../../../../src/legacy/core_plugins/navigation/public'; /** * These are dependencies of the Graph app besides the base dependencies @@ -44,6 +46,7 @@ export interface GraphDependencies extends LegacyAngularInjectedDependencies { appBasePath: string; capabilities: Record>; coreStart: AppMountContext['core']; + navigation: NavigationStart; chrome: ChromeStart; config: UiSettingsClientContract; toastNotifications: ToastsStart; @@ -75,8 +78,8 @@ export interface LegacyAngularInjectedDependencies { } export const renderApp = ({ appBasePath, element, ...deps }: GraphDependencies) => { - const graphAngularModule = createLocalAngularModule(deps.coreStart); - configureAppAngularModule(graphAngularModule); + const graphAngularModule = createLocalAngularModule(deps.navigation); + configureAppAngularModule(graphAngularModule, deps.coreStart as LegacyCoreStart, true); initGraphApp(graphAngularModule, deps); const $injector = mountGraphApp(appBasePath, element); return () => $injector.get('$rootScope').$destroy(); @@ -104,9 +107,9 @@ function mountGraphApp(appBasePath: string, element: HTMLElement) { return $injector; } -function createLocalAngularModule(core: AppMountContext['core']) { +function createLocalAngularModule(navigation: NavigationStart) { createLocalI18nModule(); - createLocalTopNavModule(); + createLocalTopNavModule(navigation); createLocalConfirmModalModule(); const graphAngularModule = angular.module(moduleName, [ @@ -125,11 +128,11 @@ function createLocalConfirmModalModule() { .directive('confirmModal', reactDirective => reactDirective(EuiConfirmModal)); } -function createLocalTopNavModule() { +function createLocalTopNavModule(navigation: NavigationStart) { angular .module('graphTopNav', ['react']) .directive('kbnTopNav', createTopNavDirective) - .directive('kbnTopNavHelper', createTopNavHelper); + .directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); } function createLocalI18nModule() { From 74fb377620fd1cfbfe31f514e49d3dc2cb1f57ed Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 20 Nov 2019 11:28:21 +0100 Subject: [PATCH 02/29] fix conflict (#51147) --- .../core_plugins/kibana/public/dashboard/index.ts | 2 +- .../core_plugins/kibana/public/dashboard/plugin.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/dashboard/index.ts b/src/legacy/core_plugins/kibana/public/dashboard/index.ts index 111806701c829e..d134739aa24c26 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/index.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/index.ts @@ -53,7 +53,7 @@ async function getAngularDependencies(): Promise { const instance = new DashboardPlugin(); instance.setup(npSetup.core, { - feature_catalogue: npSetup.plugins.feature_catalogue, + ...npSetup.plugins, __LEGACY: { localApplicationService, getAngularDependencies, diff --git a/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts b/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts index 32f09c3eeab852..780fa6571e4e79 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts @@ -36,8 +36,8 @@ import { NavigationStart } from '../../../navigation/public'; import { DashboardConstants } from './dashboard_constants'; import { FeatureCatalogueCategory, - FeatureCatalogueSetup, -} from '../../../../../plugins/feature_catalogue/public'; + HomePublicPluginSetup, +} from '../../../../../plugins/home/public'; import { SharePluginStart } from '../../../../../plugins/share/public'; export interface LegacyAngularInjectedDependencies { @@ -59,7 +59,7 @@ export interface DashboardPluginSetupDependencies { getAngularDependencies: () => Promise; localApplicationService: LocalApplicationService; }; - feature_catalogue: FeatureCatalogueSetup; + home: HomePublicPluginSetup; } export class DashboardPlugin implements Plugin { @@ -76,7 +76,7 @@ export class DashboardPlugin implements Plugin { core: CoreSetup, { __LEGACY: { localApplicationService, getAngularDependencies, ...legacyServices }, - feature_catalogue, + home, }: DashboardPluginSetupDependencies ) { const app: App = { @@ -120,7 +120,7 @@ export class DashboardPlugin implements Plugin { localApplicationService.register({ ...app, id: 'dashboard' }); localApplicationService.register({ ...app, id: 'dashboards' }); - feature_catalogue.register({ + home.featureCatalogue.register({ id: 'dashboard', title: i18n.translate('kbn.dashboard.featureCatalogue.dashboardTitle', { defaultMessage: 'Dashboard', From ff2a3ab7d29e995e2528f294a9455a3081856107 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 20 Nov 2019 12:06:53 +0100 Subject: [PATCH 03/29] Load Lens together with kibana app (#50164) --- src/legacy/plugin_discovery/types.ts | 2 + .../legacy/plugins/lens/common/constants.ts | 8 ++- x-pack/legacy/plugins/lens/index.ts | 7 +- .../lens/public/app_plugin/app.test.tsx | 7 +- .../plugins/lens/public/app_plugin/app.tsx | 29 ++++---- .../plugins/lens/public/app_plugin/plugin.tsx | 68 ++++++++++++------- .../plugins/lens/public/help_menu_util.tsx | 6 +- x-pack/legacy/plugins/lens/public/index.ts | 33 --------- x-pack/legacy/plugins/lens/public/legacy.ts | 23 +++++++ x-pack/legacy/plugins/lens/public/redirect.ts | 19 ++++++ .../lens/public/register_embeddable.ts | 20 ------ .../lens/public/register_vis_type_alias.ts | 4 +- 12 files changed, 126 insertions(+), 100 deletions(-) create mode 100644 x-pack/legacy/plugins/lens/public/legacy.ts create mode 100644 x-pack/legacy/plugins/lens/public/redirect.ts delete mode 100644 x-pack/legacy/plugins/lens/public/register_embeddable.ts diff --git a/src/legacy/plugin_discovery/types.ts b/src/legacy/plugin_discovery/types.ts index 97d3a4352c2f8c..d987260b099bd1 100644 --- a/src/legacy/plugin_discovery/types.ts +++ b/src/legacy/plugin_discovery/types.ts @@ -62,6 +62,8 @@ export interface LegacyPluginOptions { }>; apps: any; hacks: string[]; + visualize: string[]; + devTools: string[]; styleSheetPaths: string; injectDefaultVars: (server: Server) => Record; noParse: string[]; diff --git a/x-pack/legacy/plugins/lens/common/constants.ts b/x-pack/legacy/plugins/lens/common/constants.ts index 787a348a788b8b..c2eed1940fa1ab 100644 --- a/x-pack/legacy/plugins/lens/common/constants.ts +++ b/x-pack/legacy/plugins/lens/common/constants.ts @@ -6,9 +6,13 @@ export const PLUGIN_ID = 'lens'; -export const BASE_APP_URL = '/app/lens'; +export const BASE_APP_URL = '/app/kibana'; export const BASE_API_URL = '/api/lens'; +export function getBasePath() { + return `${BASE_APP_URL}#/lens`; +} + export function getEditPath(id: string) { - return `${BASE_APP_URL}#/edit/${encodeURIComponent(id)}`; + return `${BASE_APP_URL}#/lens/edit/${encodeURIComponent(id)}`; } diff --git a/x-pack/legacy/plugins/lens/index.ts b/x-pack/legacy/plugins/lens/index.ts index 20f92ebbe0654a..d4cea28d140859 100644 --- a/x-pack/legacy/plugins/lens/index.ts +++ b/x-pack/legacy/plugins/lens/index.ts @@ -12,7 +12,7 @@ import mappings from './mappings.json'; import { PLUGIN_ID, getEditPath } from './common'; import { lensServerPlugin } from './server'; -const NOT_INTERNATIONALIZED_PRODUCT_NAME = 'Lens Visualizations'; +export const NOT_INTERNATIONALIZED_PRODUCT_NAME = 'Lens Visualizations'; export const lens: LegacyPluginInitializer = kibana => { return new kibana.Plugin({ @@ -26,10 +26,11 @@ export const lens: LegacyPluginInitializer = kibana => { app: { title: NOT_INTERNATIONALIZED_PRODUCT_NAME, description: 'Explore and visualize data.', - main: `plugins/${PLUGIN_ID}/index`, + main: `plugins/${PLUGIN_ID}/redirect`, listed: false, }, - embeddableFactories: ['plugins/lens/register_embeddable'], + visualize: [`plugins/${PLUGIN_ID}/legacy`], + embeddableFactories: [`plugins/${PLUGIN_ID}/legacy`], styleSheetPaths: resolve(__dirname, 'public/index.scss'), mappings, visTypes: ['plugins/lens/register_vis_type_alias'], diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx index 3fcb6609f28f18..ce05af46ade668 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx @@ -99,6 +99,12 @@ describe('Lens App', () => { data: { query: { filterManager: createMockFilterManager(), + timefilter: { + timefilter: { + getTime: jest.fn(() => ({ from: 'now-7d', to: 'now' })), + setTime: jest.fn(), + }, + }, }, }, dataShim: { @@ -109,7 +115,6 @@ describe('Lens App', () => { }), }, }, - timefilter: { history: {} }, }, storage: { get: jest.fn(), diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx index fc5088c1271ad4..553b98643f8a58 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx @@ -62,33 +62,35 @@ export function App({ docStorage: SavedObjectStore; redirectTo: (id?: string) => void; }) { - const timeDefaults = core.uiSettings.get('timepicker:timeDefaults'); const language = storage.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage'); - const [state, setState] = useState({ - isLoading: !!docId, - isSaveModalVisible: false, - indexPatternsForTopNav: [], - query: { query: '', language }, - dateRange: { - fromDate: timeDefaults.from, - toDate: timeDefaults.to, - }, - filters: [], + const [state, setState] = useState(() => { + const currentRange = data.query.timefilter.timefilter.getTime(); + return { + isLoading: !!docId, + isSaveModalVisible: false, + indexPatternsForTopNav: [], + query: { query: '', language }, + dateRange: { + fromDate: currentRange.from, + toDate: currentRange.to, + }, + filters: [], + }; }); const { lastKnownDoc } = state; useEffect(() => { - const subscription = data.query.filterManager.getUpdates$().subscribe({ + const filterSubscription = data.query.filterManager.getUpdates$().subscribe({ next: () => { setState(s => ({ ...s, filters: data.query.filterManager.getFilters() })); trackUiEvent('app_filters_updated'); }, }); return () => { - subscription.unsubscribe(); + filterSubscription.unsubscribe(); }; }, []); @@ -199,6 +201,7 @@ export function App({ dateRange.from !== state.dateRange.fromDate || dateRange.to !== state.dateRange.toDate ) { + data.query.timefilter.timefilter.setTime(dateRange); trackUiEvent('app_date_change'); } else { trackUiEvent('app_query_change'); diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx index 56c19ea2bb9f26..60a375f696f7b8 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx @@ -4,18 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ +import 'ui/autoload/all'; +// Used to run esaggs queries +import 'uiExports/fieldFormats'; +import 'uiExports/search'; +import 'uiExports/visRequestHandlers'; +import 'uiExports/visResponseHandlers'; +// Used for kibana_context function +import 'uiExports/savedObjectTypes'; + import React from 'react'; import { I18nProvider, FormattedMessage } from '@kbn/i18n/react'; import { HashRouter, Switch, Route, RouteComponentProps } from 'react-router-dom'; +import { render, unmountComponentAtNode } from 'react-dom'; import chrome from 'ui/chrome'; import { CoreSetup, CoreStart } from 'src/core/public'; -import { npSetup, npStart } from 'ui/new_platform'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { DataStart } from '../../../../../../src/legacy/core_plugins/data/public'; -import { start as dataShimStart } from '../../../../../../src/legacy/core_plugins/data/public/legacy'; import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; import { editorFrameSetup, editorFrameStart, editorFrameStop } from '../editor_frame_plugin'; import { indexPatternDatasourceSetup, indexPatternDatasourceStop } from '../indexpattern_plugin'; +import { addHelpMenuToAppChrome } from '../help_menu_util'; import { SavedObjectIndexStore } from '../persistence'; import { xyVisualizationSetup, xyVisualizationStop } from '../xy_visualization_plugin'; import { metricVisualizationSetup, metricVisualizationStop } from '../metric_visualization_plugin'; @@ -31,10 +40,15 @@ import { stopReportManager, trackUiEvent, } from '../lens_ui_telemetry'; +import { LocalApplicationService } from '../../../../../../src/legacy/core_plugins/kibana/public/local_application_service'; +import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../../index'; export interface LensPluginStartDependencies { data: DataPublicPluginStart; dataShim: DataStart; + __LEGACY: { + localApplicationService: LocalApplicationService; + }; } export class AppPlugin { private instance: EditorFrameInstance | null = null; @@ -58,11 +72,16 @@ export class AppPlugin { editorFrameSetupInterface.registerDatasource('indexpattern', indexPattern); } - start(core: CoreStart, { data, dataShim }: LensPluginStartDependencies) { + start( + core: CoreStart, + { data, dataShim, __LEGACY: { localApplicationService } }: LensPluginStartDependencies + ) { if (this.store === null) { throw new Error('Start lifecycle called before setup lifecycle'); } + addHelpMenuToAppChrome(core.chrome); + const store = this.store; const editorFrameStartInterface = editorFrameStart(); @@ -89,9 +108,9 @@ export class AppPlugin { docStorage={store} redirectTo={id => { if (!id) { - routeProps.history.push('/'); + routeProps.history.push('/lens'); } else { - routeProps.history.push(`/edit/${id}`); + routeProps.history.push(`/lens/edit/${id}`); } }} /> @@ -103,17 +122,27 @@ export class AppPlugin { return ; } - return ( - - - - - - - - - - ); + localApplicationService.register({ + id: 'lens', + title: NOT_INTERNATIONALIZED_PRODUCT_NAME, + mount: async (context, params) => { + render( + + + + + + + + + , + params.element + ); + return () => { + unmountComponentAtNode(params.element); + }; + }, + }); } stop() { @@ -131,10 +160,3 @@ export class AppPlugin { editorFrameStop(); } } - -const app = new AppPlugin(); - -export const appSetup = () => app.setup(npSetup.core, {}); -export const appStart = () => - app.start(npStart.core, { dataShim: dataShimStart, data: npStart.plugins.data }); -export const appStop = () => app.stop(); diff --git a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx b/x-pack/legacy/plugins/lens/public/help_menu_util.tsx index 30a05dbc38537c..fec7175ea48eb4 100644 --- a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx +++ b/x-pack/legacy/plugins/lens/public/help_menu_util.tsx @@ -10,12 +10,12 @@ import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { Chrome } from 'ui/chrome'; +import { ChromeStart } from 'kibana/public'; const docsPage = 'lens'; -export function addHelpMenuToAppChrome(chrome: Chrome) { - chrome.helpExtension.set(domElement => { +export function addHelpMenuToAppChrome(chrome: ChromeStart) { + chrome.setHelpExtension(domElement => { render(, domElement); return () => { unmountComponentAtNode(domElement); diff --git a/x-pack/legacy/plugins/lens/public/index.ts b/x-pack/legacy/plugins/lens/public/index.ts index 2a5422d4bb8a16..9f4141dbcae7df 100644 --- a/x-pack/legacy/plugins/lens/public/index.ts +++ b/x-pack/legacy/plugins/lens/public/index.ts @@ -5,36 +5,3 @@ */ export * from './types'; - -import 'ui/autoload/all'; -// Used to run esaggs queries -import 'uiExports/fieldFormats'; -import 'uiExports/search'; -import 'uiExports/visRequestHandlers'; -import 'uiExports/visResponseHandlers'; -import 'uiExports/interpreter'; -// Used for kibana_context function -import 'uiExports/savedObjectTypes'; - -import { render, unmountComponentAtNode } from 'react-dom'; -import { IScope } from 'angular'; -import chrome from 'ui/chrome'; -import { appStart, appSetup, appStop } from './app_plugin'; -import { PLUGIN_ID } from '../common'; -import { addHelpMenuToAppChrome } from './help_menu_util'; - -// TODO: Convert this to the "new platform" way of doing UI -function Root($scope: IScope, $element: JQLite) { - const el = $element[0]; - $scope.$on('$destroy', () => { - unmountComponentAtNode(el); - appStop(); - }); - - appSetup(); - addHelpMenuToAppChrome(chrome); - - return render(appStart(), el); -} - -chrome.setRootController(PLUGIN_ID, Root); diff --git a/x-pack/legacy/plugins/lens/public/legacy.ts b/x-pack/legacy/plugins/lens/public/legacy.ts new file mode 100644 index 00000000000000..0285e041de78cf --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/legacy.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { npSetup, npStart } from 'ui/new_platform'; +import { start as dataShimStart } from '../../../../../src/legacy/core_plugins/data/public/legacy'; + +export * from './types'; + +import { localApplicationService } from '../../../../../src/legacy/core_plugins/kibana/public/local_application_service'; +import { AppPlugin } from './app_plugin'; + +const app = new AppPlugin(); +app.setup(npSetup.core, {}); +app.start(npStart.core, { + dataShim: dataShimStart, + data: npStart.plugins.data, + __LEGACY: { + localApplicationService, + }, +}); diff --git a/x-pack/legacy/plugins/lens/public/redirect.ts b/x-pack/legacy/plugins/lens/public/redirect.ts new file mode 100644 index 00000000000000..25b0188214c5e4 --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/redirect.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// This file redirects lens urls starting with app/lens#... to their counterpart on app/kibana#lens/... to +// make sure it's compatible with the 7.5 release + +import { npSetup } from 'ui/new_platform'; +import chrome from 'ui/chrome'; + +chrome.setRootController('lens', () => { + // prefix the path in the hash with lens/ + const prefixedHashRoute = window.location.hash.replace(/^#\//, '#/lens/'); + + // redirect to the new lens url `app/kibana#/lens/...` + window.location.href = npSetup.core.http.basePath.prepend('/app/kibana' + prefixedHashRoute); +}); diff --git a/x-pack/legacy/plugins/lens/public/register_embeddable.ts b/x-pack/legacy/plugins/lens/public/register_embeddable.ts deleted file mode 100644 index f86cb91a0029e7..00000000000000 --- a/x-pack/legacy/plugins/lens/public/register_embeddable.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { indexPatternDatasourceSetup } from './indexpattern_plugin'; -import { xyVisualizationSetup } from './xy_visualization_plugin'; -import { editorFrameSetup, editorFrameStart } from './editor_frame_plugin'; -import { datatableVisualizationSetup } from './datatable_visualization_plugin'; -import { metricVisualizationSetup } from './metric_visualization_plugin'; - -// bootstrap shimmed plugins to register everything necessary (expression functions and embeddables). -// the new platform will take care of this once in place. -indexPatternDatasourceSetup(); -datatableVisualizationSetup(); -xyVisualizationSetup(); -metricVisualizationSetup(); -editorFrameSetup(); -editorFrameStart(); diff --git a/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts b/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts index 562d0f0ef6135f..185df12054a3c6 100644 --- a/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts +++ b/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts @@ -6,10 +6,10 @@ import { i18n } from '@kbn/i18n'; import { visualizations } from '../../../../../src/legacy/core_plugins/visualizations/public'; -import { BASE_APP_URL, getEditPath } from '../common'; +import { getBasePath, getEditPath } from '../common'; visualizations.types.registerAlias({ - aliasUrl: BASE_APP_URL, + aliasUrl: getBasePath(), name: 'lens', promotion: { description: i18n.translate('xpack.lens.visTypeAlias.promotion.description', { From cdc9caabc9fa4c8449391c127539b63cefae5e76 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Wed, 20 Nov 2019 12:14:27 +0000 Subject: [PATCH 04/29] [ML] Remove unused Angular filters (#51027) --- .../__tests__/abbreviate_whole_number.js | 42 ----- .../formatters/__tests__/format_value.js | 93 ----------- .../__tests__/metric_change_description.js | 33 ---- .../abbreviate_whole_number.test.ts | 37 +++++ ...e_number.js => abbreviate_whole_number.ts} | 5 +- .../ml/public/formatters/format_value.test.ts | 94 +++++++++++ .../{format_value.js => format_value.ts} | 68 +++++--- .../formatters/metric_change_description.js | 139 ---------------- .../metric_change_description.test.ts | 57 +++++++ .../formatters/metric_change_description.ts | 157 ++++++++++++++++++ 10 files changed, 388 insertions(+), 337 deletions(-) delete mode 100644 x-pack/legacy/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js delete mode 100644 x-pack/legacy/plugins/ml/public/formatters/__tests__/format_value.js delete mode 100644 x-pack/legacy/plugins/ml/public/formatters/__tests__/metric_change_description.js create mode 100644 x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.test.ts rename x-pack/legacy/plugins/ml/public/formatters/{abbreviate_whole_number.js => abbreviate_whole_number.ts} (89%) create mode 100644 x-pack/legacy/plugins/ml/public/formatters/format_value.test.ts rename x-pack/legacy/plugins/ml/public/formatters/{format_value.js => format_value.ts} (75%) delete mode 100644 x-pack/legacy/plugins/ml/public/formatters/metric_change_description.js create mode 100644 x-pack/legacy/plugins/ml/public/formatters/metric_change_description.test.ts create mode 100644 x-pack/legacy/plugins/ml/public/formatters/metric_change_description.ts diff --git a/x-pack/legacy/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js b/x-pack/legacy/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js deleted file mode 100644 index 4e85bae4b18629..00000000000000 --- a/x-pack/legacy/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -import expect from '@kbn/expect'; -import { abbreviateWholeNumber } from '../abbreviate_whole_number'; - -describe('ML - abbreviateWholeNumber formatter', () => { - - it('returns the correct format using default max digits', () => { - expect(abbreviateWholeNumber(1)).to.be(1); - expect(abbreviateWholeNumber(12)).to.be(12); - expect(abbreviateWholeNumber(123)).to.be(123); - expect(abbreviateWholeNumber(1234)).to.be('1k'); - expect(abbreviateWholeNumber(12345)).to.be('12k'); - expect(abbreviateWholeNumber(123456)).to.be('123k'); - expect(abbreviateWholeNumber(1234567)).to.be('1m'); - expect(abbreviateWholeNumber(12345678)).to.be('12m'); - expect(abbreviateWholeNumber(123456789)).to.be('123m'); - expect(abbreviateWholeNumber(1234567890)).to.be('1b'); - expect(abbreviateWholeNumber(5555555555555.55)).to.be('6t'); - }); - - it('returns the correct format using custom max digits', () => { - expect(abbreviateWholeNumber(1, 4)).to.be(1); - expect(abbreviateWholeNumber(12, 4)).to.be(12); - expect(abbreviateWholeNumber(123, 4)).to.be(123); - expect(abbreviateWholeNumber(1234, 4)).to.be(1234); - expect(abbreviateWholeNumber(12345, 4)).to.be('12k'); - expect(abbreviateWholeNumber(123456, 6)).to.be(123456); - expect(abbreviateWholeNumber(1234567, 4)).to.be('1m'); - expect(abbreviateWholeNumber(12345678, 3)).to.be('12m'); - expect(abbreviateWholeNumber(123456789, 9)).to.be(123456789); - expect(abbreviateWholeNumber(1234567890, 3)).to.be('1b'); - expect(abbreviateWholeNumber(5555555555555.55, 5)).to.be('6t'); - }); - -}); diff --git a/x-pack/legacy/plugins/ml/public/formatters/__tests__/format_value.js b/x-pack/legacy/plugins/ml/public/formatters/__tests__/format_value.js deleted file mode 100644 index ffdbdd915d3a88..00000000000000 --- a/x-pack/legacy/plugins/ml/public/formatters/__tests__/format_value.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -import expect from '@kbn/expect'; -import moment from 'moment-timezone'; -import { formatValue } from '../format_value'; - -describe('ML - formatValue formatter', () => { - const timeOfWeekRecord = { - job_id: 'gallery_time_of_week', - result_type: 'record', - probability: 0.012818, - record_score: 53.55134, - bucket_span: 900, - detector_index: 0, - timestamp: 1530155700000, - by_field_name: 'clientip', - by_field_value: '65.55.215.39', - function: 'time_of_week', - function_description: 'time' - }; - - const timeOfDayRecord = { - job_id: 'gallery_time_of_day', - result_type: 'record', - probability: 0.012818, - record_score: 97.94245, - bucket_span: 900, - detector_index: 0, - timestamp: 1517472900000, - by_field_name: 'clientip', - by_field_value: '157.56.93.83', - function: 'time_of_day', - function_description: 'time' - }; - - // Set timezone to US/Eastern for time_of_day and time_of_week tests. - beforeEach(() => { - moment.tz.setDefault('US/Eastern'); - }); - - afterEach(() => { - moment.tz.setDefault('Browser'); - }); - - // For time_of_day and time_of_week test values which are offsets in seconds - // from UTC start of week / day are formatted correctly using the test timezone. - it('correctly formats time_of_week value from numeric input', () => { - expect(formatValue(359739, 'time_of_week', undefined, timeOfWeekRecord)).to.be('Wed 23:55'); - }); - - it('correctly formats time_of_day value from numeric input', () => { - expect(formatValue(73781, 'time_of_day', undefined, timeOfDayRecord)).to.be('15:29'); - }); - - it('correctly formats number values from numeric input', () => { - expect(formatValue(1483228800, 'mean')).to.be(1483228800); - expect(formatValue(1234.5678, 'mean')).to.be(1234.6); - expect(formatValue(0.00012345, 'mean')).to.be(0.000123); - expect(formatValue(0, 'mean')).to.be(0); - expect(formatValue(-0.12345, 'mean')).to.be(-0.123); - expect(formatValue(-1234.5678, 'mean')).to.be(-1234.6); - expect(formatValue(-100000.1, 'mean')).to.be(-100000); - }); - - it('correctly formats time_of_week value from array input', () => { - expect(formatValue([359739], 'time_of_week', undefined, timeOfWeekRecord)).to.be('Wed 23:55'); - }); - - it('correctly formats time_of_day value from array input', () => { - expect(formatValue([73781], 'time_of_day', undefined, timeOfDayRecord)).to.be('15:29'); - }); - - it('correctly formats number values from array input', () => { - expect(formatValue([1483228800], 'mean')).to.be(1483228800); - expect(formatValue([1234.5678], 'mean')).to.be(1234.6); - expect(formatValue([0.00012345], 'mean')).to.be(0.000123); - expect(formatValue([0], 'mean')).to.be(0); - expect(formatValue([-0.12345], 'mean')).to.be(-0.123); - expect(formatValue([-1234.5678], 'mean')).to.be(-1234.6); - expect(formatValue([-100000.1], 'mean')).to.be(-100000); - }); - - it('correctly formats multi-valued array', () => { - expect(formatValue([30.3, 26.2], 'lat_long')).to.be('[30.3,26.2]'); - }); - -}); diff --git a/x-pack/legacy/plugins/ml/public/formatters/__tests__/metric_change_description.js b/x-pack/legacy/plugins/ml/public/formatters/__tests__/metric_change_description.js deleted file mode 100644 index 45864ce58bf83b..00000000000000 --- a/x-pack/legacy/plugins/ml/public/formatters/__tests__/metric_change_description.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -import expect from '@kbn/expect'; -import { getMetricChangeDescription } from '../metric_change_description'; - - -describe('ML - metricChangeDescription formatter', () => { - - it('returns correct icon and message if actual > typical', () => { - expect(getMetricChangeDescription(1.01, 1)).to.eql({ iconType: 'sortUp', message: 'Unusually high' }); - expect(getMetricChangeDescription(1.123, 1)).to.eql({ iconType: 'sortUp', message: '1.1x higher' }); - expect(getMetricChangeDescription(2, 1)).to.eql({ iconType: 'sortUp', message: '2x higher' }); - expect(getMetricChangeDescription(9.5, 1)).to.eql({ iconType: 'sortUp', message: '10x higher' }); - expect(getMetricChangeDescription(1000, 1)).to.eql({ iconType: 'sortUp', message: 'More than 100x higher' }); - expect(getMetricChangeDescription(1, 0)).to.eql({ iconType: 'sortUp', message: 'Unexpected non-zero value' }); - }); - - it('returns correct icon and message if actual < typical', () => { - expect(getMetricChangeDescription(1, 1.01)).to.eql({ iconType: 'sortDown', message: 'Unusually low' }); - expect(getMetricChangeDescription(1, 1.123)).to.eql({ iconType: 'sortDown', message: '1.1x lower' }); - expect(getMetricChangeDescription(1, 2)).to.eql({ iconType: 'sortDown', message: '2x lower' }); - expect(getMetricChangeDescription(1, 9.5)).to.eql({ iconType: 'sortDown', message: '10x lower' }); - expect(getMetricChangeDescription(1, 1000)).to.eql({ iconType: 'sortDown', message: 'More than 100x lower' }); - expect(getMetricChangeDescription(0, 1)).to.eql({ iconType: 'sortDown', message: 'Unexpected zero value' }); - }); - -}); diff --git a/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.test.ts b/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.test.ts new file mode 100644 index 00000000000000..feabaa4064978d --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.test.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { abbreviateWholeNumber } from './abbreviate_whole_number'; + +describe('ML - abbreviateWholeNumber formatter', () => { + test('returns the correct format using default max digits', () => { + expect(abbreviateWholeNumber(1)).toBe(1); + expect(abbreviateWholeNumber(12)).toBe(12); + expect(abbreviateWholeNumber(123)).toBe(123); + expect(abbreviateWholeNumber(1234)).toBe('1k'); + expect(abbreviateWholeNumber(12345)).toBe('12k'); + expect(abbreviateWholeNumber(123456)).toBe('123k'); + expect(abbreviateWholeNumber(1234567)).toBe('1m'); + expect(abbreviateWholeNumber(12345678)).toBe('12m'); + expect(abbreviateWholeNumber(123456789)).toBe('123m'); + expect(abbreviateWholeNumber(1234567890)).toBe('1b'); + expect(abbreviateWholeNumber(5555555555555.55)).toBe('6t'); + }); + + test('returns the correct format using custom max digits', () => { + expect(abbreviateWholeNumber(1, 4)).toBe(1); + expect(abbreviateWholeNumber(12, 4)).toBe(12); + expect(abbreviateWholeNumber(123, 4)).toBe(123); + expect(abbreviateWholeNumber(1234, 4)).toBe(1234); + expect(abbreviateWholeNumber(12345, 4)).toBe('12k'); + expect(abbreviateWholeNumber(123456, 6)).toBe(123456); + expect(abbreviateWholeNumber(1234567, 4)).toBe('1m'); + expect(abbreviateWholeNumber(12345678, 3)).toBe('12m'); + expect(abbreviateWholeNumber(123456789, 9)).toBe(123456789); + expect(abbreviateWholeNumber(1234567890, 3)).toBe('1b'); + expect(abbreviateWholeNumber(5555555555555.55, 5)).toBe('6t'); + }); +}); diff --git a/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.js b/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.ts similarity index 89% rename from x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.js rename to x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.ts index 445681be4ff819..6d630c740a359c 100644 --- a/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.js +++ b/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.ts @@ -4,15 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ - /* * Formatter to abbreviate large whole numbers with metric prefixes. * Uses numeral.js to format numbers longer than the specified number of * digits with metric abbreviations e.g. 12345 as 12k, or 98000000 as 98m. -*/ + */ import numeral from '@elastic/numeral'; -export function abbreviateWholeNumber(value, maxDigits = 3) { +export function abbreviateWholeNumber(value: number, maxDigits = 3) { if (Math.abs(value) < Math.pow(10, maxDigits)) { return value; } else { diff --git a/x-pack/legacy/plugins/ml/public/formatters/format_value.test.ts b/x-pack/legacy/plugins/ml/public/formatters/format_value.test.ts new file mode 100644 index 00000000000000..5f146aef97fccf --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/formatters/format_value.test.ts @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import moment from 'moment-timezone'; +import { AnomalyRecordDoc } from '../../common/types/anomalies'; +import { formatValue } from './format_value'; + +describe('ML - formatValue formatter', () => { + const timeOfWeekRecord: AnomalyRecordDoc = { + job_id: 'gallery_time_of_week', + result_type: 'record', + probability: 0.012818, + record_score: 53.55134, + initial_record_score: 53, + bucket_span: 900, + detector_index: 0, + is_interim: false, + timestamp: 1530155700000, + by_field_name: 'clientip', + by_field_value: '65.55.215.39', + function: 'time_of_week', + function_description: 'time', + }; + + const timeOfDayRecord: AnomalyRecordDoc = { + job_id: 'gallery_time_of_day', + result_type: 'record', + probability: 0.012818, + record_score: 97.94245, + initial_record_score: 97, + bucket_span: 900, + detector_index: 0, + is_interim: false, + timestamp: 1517472900000, + by_field_name: 'clientip', + by_field_value: '157.56.93.83', + function: 'time_of_day', + function_description: 'time', + }; + + // Set timezone to US/Eastern for time_of_day and time_of_week tests. + beforeEach(() => { + moment.tz.setDefault('US/Eastern'); + }); + + afterEach(() => { + moment.tz.setDefault('Browser'); + }); + + // For time_of_day and time_of_week test values which are offsets in seconds + // from UTC start of week / day are formatted correctly using the test timezone. + test('correctly formats time_of_week value from numeric input', () => { + expect(formatValue(359739, 'time_of_week', undefined, timeOfWeekRecord)).toBe('Wed 23:55'); + }); + + test('correctly formats time_of_day value from numeric input', () => { + expect(formatValue(73781, 'time_of_day', undefined, timeOfDayRecord)).toBe('15:29'); + }); + + test('correctly formats number values from numeric input', () => { + expect(formatValue(1483228800, 'mean')).toBe(1483228800); + expect(formatValue(1234.5678, 'mean')).toBe(1234.6); + expect(formatValue(0.00012345, 'mean')).toBe(0.000123); + expect(formatValue(0, 'mean')).toBe(0); + expect(formatValue(-0.12345, 'mean')).toBe(-0.123); + expect(formatValue(-1234.5678, 'mean')).toBe(-1234.6); + expect(formatValue(-100000.1, 'mean')).toBe(-100000); + }); + + test('correctly formats time_of_week value from array input', () => { + expect(formatValue([359739], 'time_of_week', undefined, timeOfWeekRecord)).toBe('Wed 23:55'); + }); + + test('correctly formats time_of_day value from array input', () => { + expect(formatValue([73781], 'time_of_day', undefined, timeOfDayRecord)).toBe('15:29'); + }); + + test('correctly formats number values from array input', () => { + expect(formatValue([1483228800], 'mean')).toBe(1483228800); + expect(formatValue([1234.5678], 'mean')).toBe(1234.6); + expect(formatValue([0.00012345], 'mean')).toBe(0.000123); + expect(formatValue([0], 'mean')).toBe(0); + expect(formatValue([-0.12345], 'mean')).toBe(-0.123); + expect(formatValue([-1234.5678], 'mean')).toBe(-1234.6); + expect(formatValue([-100000.1], 'mean')).toBe(-100000); + }); + + test('correctly formats multi-valued array', () => { + expect(formatValue([30.3, 26.2], 'lat_long')).toBe('[30.3,26.2]'); + }); +}); diff --git a/x-pack/legacy/plugins/ml/public/formatters/format_value.js b/x-pack/legacy/plugins/ml/public/formatters/format_value.ts similarity index 75% rename from x-pack/legacy/plugins/ml/public/formatters/format_value.js rename to x-pack/legacy/plugins/ml/public/formatters/format_value.ts index 48988b5561e705..9360957c4a9119 100644 --- a/x-pack/legacy/plugins/ml/public/formatters/format_value.js +++ b/x-pack/legacy/plugins/ml/public/formatters/format_value.ts @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ - - /* * Formatter for 'typical' and 'actual' values from machine learning results. * For detectors which use the time_of_week or time_of_day @@ -14,12 +12,8 @@ */ import moment from 'moment'; - -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - - -const SIGFIGS_IF_ROUNDING = 3; // Number of sigfigs to use for values < 10 +import { AnomalyRecordDoc } from '../../common/types/anomalies'; +const SIGFIGS_IF_ROUNDING = 3; // Number of sigfigs to use for values < 10 // Formats the value of an actual or typical field from a machine learning anomaly record. // mlFunction is the 'function' field from the ML record containing what the user entered e.g. 'high_count', @@ -29,7 +23,12 @@ const SIGFIGS_IF_ROUNDING = 3; // Number of sigfigs to use for values < 10 // For time_of_day or time_of_week functions the anomaly record // containing the timestamp of the anomaly should be supplied in // order to correctly format the day or week offset to the time of the anomaly. -export function formatValue(value, mlFunction, fieldFormat, record) { +export function formatValue( + value: number[] | number, + mlFunction: string, + fieldFormat?: any, + record?: AnomalyRecordDoc +) { // actual and typical values in anomaly record results will be arrays. // Unless the array is multi-valued (as it will be for multi-variate analyses such as lat_long), // simply return the formatted single value. @@ -54,7 +53,12 @@ export function formatValue(value, mlFunction, fieldFormat, record) { // For time_of_day or time_of_week functions the anomaly record // containing the timestamp of the anomaly should be supplied in // order to correctly format the day or week offset to the time of the anomaly. -function formatSingleValue(value, mlFunction, fieldFormat, record) { +function formatSingleValue( + value: number, + mlFunction: string, + fieldFormat?: any, + record?: AnomalyRecordDoc +) { if (value === undefined || value === null) { return ''; } @@ -65,14 +69,24 @@ function formatSingleValue(value, mlFunction, fieldFormat, record) { // that the anomaly occurred using record timestamp if supplied, add on the offset, and finally // revert back to configured timezone for formatting. if (mlFunction === 'time_of_week') { - const d = ((record !== undefined && record.timestamp !== undefined) ? new Date(record.timestamp) : new Date()); - const i = parseInt(value); - const utcMoment = moment.utc(d).startOf('week').add(i, 's'); + const d = + record !== undefined && record.timestamp !== undefined + ? new Date(record.timestamp) + : new Date(); + const utcMoment = moment + .utc(d) + .startOf('week') + .add(value, 's'); return moment(utcMoment.valueOf()).format('ddd HH:mm'); } else if (mlFunction === 'time_of_day') { - const d = ((record !== undefined && record.timestamp !== undefined) ? new Date(record.timestamp) : new Date()); - const i = parseInt(value); - const utcMoment = moment.utc(d).startOf('day').add(i, 's'); + const d = + record !== undefined && record.timestamp !== undefined + ? new Date(record.timestamp) + : new Date(); + const utcMoment = moment + .utc(d) + .startOf('day') + .add(value, 's'); return moment(utcMoment.valueOf()).format('HH:mm'); } else { if (fieldFormat !== undefined) { @@ -81,32 +95,32 @@ function formatSingleValue(value, mlFunction, fieldFormat, record) { // If no Kibana FieldFormat object provided, // format the value depending on its magnitude. const absValue = Math.abs(value); - if (absValue >= 10000 || absValue === Math.floor(absValue)) { + if (absValue >= 10000 || absValue === Math.floor(absValue)) { // Output 0 decimal places if whole numbers or >= 10000 if (fieldFormat !== undefined) { return fieldFormat.convert(value, 'text'); } else { return Number(value.toFixed(0)); } - } else if (absValue >= 10) { // Output to 1 decimal place between 10 and 10000 return Number(value.toFixed(1)); - } - else { + } else { // For values < 10, output to 3 significant figures let multiple; if (value > 0) { - multiple = Math.pow(10, SIGFIGS_IF_ROUNDING - Math.floor(Math.log(value) / Math.LN10) - 1); + multiple = Math.pow( + 10, + SIGFIGS_IF_ROUNDING - Math.floor(Math.log(value) / Math.LN10) - 1 + ); } else { - multiple = Math.pow(10, SIGFIGS_IF_ROUNDING - Math.floor(Math.log(-1 * value) / Math.LN10) - 1); + multiple = Math.pow( + 10, + SIGFIGS_IF_ROUNDING - Math.floor(Math.log(-1 * value) / Math.LN10) - 1 + ); } - return (Math.round(value * multiple)) / multiple; + return Math.round(value * multiple) / multiple; } } } } - -// TODO - remove the filter once all uses of the formatValue Angular filter have been removed. -module.filter('formatValue', () => formatValue); - diff --git a/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.js b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.js deleted file mode 100644 index 06074e9a842c52..00000000000000 --- a/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.js +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -/* - * Produces a concise textual description of how the - * actual value compares to the typical value for an anomaly. - */ - -import { i18n } from '@kbn/i18n'; -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - -// Returns an Object containing a text message and EuiIcon type to -// describe how the actual value compares to the typical. -export function getMetricChangeDescription(actualProp, typicalProp) { - if (actualProp === undefined || typicalProp === undefined) { - return { iconType: 'empty', message: '' }; - } - - let iconType; - let message; - - // For metric functions, actual and typical will be single value arrays. - let actual = actualProp; - let typical = typicalProp; - if (Array.isArray(actualProp)) { - if (actualProp.length === 1) { - actual = actualProp[0]; - } else { - // TODO - do we want to enhance the description depending on detector? - // e.g. 'Unusual location' if using a lat_long detector. - return { - iconType: 'alert', - message: i18n.translate('xpack.ml.formatters.metricChangeDescription.unusualValuesDescription', { - defaultMessage: 'Unusual values', - }), - }; - } - } - - if (Array.isArray(typicalProp)) { - if (typicalProp.length === 1) { - typical = typicalProp[0]; - } - } - - if (actual === typical) { - // Very unlikely, but just in case. - message = i18n.translate('xpack.ml.formatters.metricChangeDescription.actualSameAsTypicalDescription', { - defaultMessage: 'actual same as typical', - }); - } else { - // For actual / typical gives output of the form: - // 4 / 2 2x higher - // 2 / 10 5x lower - // 1000 / 1 More than 100x higher - // 999 / 1000 Unusually low - // 100 / -100 Unusually high - // 0 / 100 Unexpected zero value - // 1 / 0 Unexpected non-zero value - const isHigher = actual > typical; - iconType = isHigher ? 'sortUp' : 'sortDown'; - if (typical !== 0 && actual !== 0) { - const factor = isHigher ? actual / typical : typical / actual; - if (factor > 1.5) { - if (factor <= 100) { - message = isHigher ? i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThanOneAndHalfxHigherDescription', { - defaultMessage: '{factor}x higher', - values: { factor: Math.round(factor) }, - }) : i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThanOneAndHalfxLowerDescription', { - defaultMessage: '{factor}x lower', - values: { factor: Math.round(factor) }, - }); - } else { - message = isHigher ? i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThan100xHigherDescription', { - defaultMessage: 'More than 100x higher', - }) : i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThan100xLowerDescription', { - defaultMessage: 'More than 100x lower', - }); - } - } else if (factor >= 1.05) { - message = isHigher ? i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThanOneAndFiveHundredthsxHigherDescription', { - defaultMessage: '{factor}x higher', - values: { factor: factor.toPrecision(2) }, - }) : i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThanOneAndFiveHundredthsxLowerDescription', { - defaultMessage: '{factor}x lower', - values: { factor: factor.toPrecision(2) }, - }); - } else { - message = isHigher ? i18n.translate('xpack.ml.formatters.metricChangeDescription.unusuallyHighDescription', { - defaultMessage: 'Unusually high', - }) : i18n.translate('xpack.ml.formatters.metricChangeDescription.unusuallyLowDescription', { - defaultMessage: 'Unusually low', - }); - } - - } else { - if (actual === 0) { - message = i18n.translate('xpack.ml.formatters.metricChangeDescription.unexpectedZeroValueDescription', { - defaultMessage: 'Unexpected zero value', - }); - } else { - message = i18n.translate('xpack.ml.formatters.metricChangeDescription.unexpectedNonZeroValueDescription', { - defaultMessage: 'Unexpected non-zero value', - }); - } - } - } - - return { iconType, message }; -} - -// TODO - remove the filter once all uses of the metricChangeDescription Angular filter have been removed. -module.filter('metricChangeDescription', function () { - return function (actual, typical) { - - const { - iconType, - message - } = getMetricChangeDescription(actual, typical); - - switch (iconType) { - case 'sortUp': - return ` ${message}`; - case 'sortDown': - return ` ${message}`; - case 'alert': - return ` ${message}`; - } - - return message; - }; -}); - diff --git a/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.test.ts b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.test.ts new file mode 100644 index 00000000000000..93533fe155e80f --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getMetricChangeDescription } from './metric_change_description'; + +describe('ML - metricChangeDescription formatter', () => { + test('returns correct icon and message if actual > typical', () => { + expect(getMetricChangeDescription(1.01, 1)).toEqual({ + iconType: 'sortUp', + message: 'Unusually high', + }); + expect(getMetricChangeDescription(1.123, 1)).toEqual({ + iconType: 'sortUp', + message: '1.1x higher', + }); + expect(getMetricChangeDescription(2, 1)).toEqual({ iconType: 'sortUp', message: '2x higher' }); + expect(getMetricChangeDescription(9.5, 1)).toEqual({ + iconType: 'sortUp', + message: '10x higher', + }); + expect(getMetricChangeDescription(1000, 1)).toEqual({ + iconType: 'sortUp', + message: 'More than 100x higher', + }); + expect(getMetricChangeDescription(1, 0)).toEqual({ + iconType: 'sortUp', + message: 'Unexpected non-zero value', + }); + }); + + test('returns correct icon and message if actual < typical', () => { + expect(getMetricChangeDescription(1, 1.01)).toEqual({ + iconType: 'sortDown', + message: 'Unusually low', + }); + expect(getMetricChangeDescription(1, 1.123)).toEqual({ + iconType: 'sortDown', + message: '1.1x lower', + }); + expect(getMetricChangeDescription(1, 2)).toEqual({ iconType: 'sortDown', message: '2x lower' }); + expect(getMetricChangeDescription(1, 9.5)).toEqual({ + iconType: 'sortDown', + message: '10x lower', + }); + expect(getMetricChangeDescription(1, 1000)).toEqual({ + iconType: 'sortDown', + message: 'More than 100x lower', + }); + expect(getMetricChangeDescription(0, 1)).toEqual({ + iconType: 'sortDown', + message: 'Unexpected zero value', + }); + }); +}); diff --git a/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.ts b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.ts new file mode 100644 index 00000000000000..68f437b5a1436a --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.ts @@ -0,0 +1,157 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/* + * Produces a concise textual description of how the + * actual value compares to the typical value for an anomaly. + */ + +import { i18n } from '@kbn/i18n'; + +// Returns an Object containing a text message and EuiIcon type to +// describe how the actual value compares to the typical. +export function getMetricChangeDescription( + actualProp: number[] | number, + typicalProp: number[] | number +) { + if (actualProp === undefined || typicalProp === undefined) { + return { iconType: 'empty', message: '' }; + } + + let iconType: string = 'alert'; + let message: string; + + // For metric functions, actual and typical will be single value arrays. + let actual: number = 0; + let typical: number = 0; + if (Array.isArray(actualProp)) { + if (actualProp.length === 1) { + actual = actualProp[0]; + } else { + // lat_long anomalies currently the only multi-value case. + // TODO - do we want to enhance the description depending on detector? + // e.g. 'Unusual location' if using a lat_long detector. + return { + iconType: 'alert', + message: i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.unusualValuesDescription', + { + defaultMessage: 'Unusual values', + } + ), + }; + } + } else { + actual = actualProp; + } + + if (Array.isArray(typicalProp)) { + if (typicalProp.length === 1) { + typical = typicalProp[0]; + } + } else { + typical = typicalProp; + } + + if (actual === typical) { + // Very unlikely, but just in case. + message = i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.actualSameAsTypicalDescription', + { + defaultMessage: 'actual same as typical', + } + ); + } else { + // For actual / typical gives output of the form: + // 4 / 2 2x higher + // 2 / 10 5x lower + // 1000 / 1 More than 100x higher + // 999 / 1000 Unusually low + // 100 / -100 Unusually high + // 0 / 100 Unexpected zero value + // 1 / 0 Unexpected non-zero value + const isHigher = actual > typical; + iconType = isHigher ? 'sortUp' : 'sortDown'; + if (typical !== 0 && actual !== 0) { + const factor: number = isHigher ? actual / typical : typical / actual; + if (factor > 1.5) { + if (factor <= 100) { + message = isHigher + ? i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThanOneAndHalfxHigherDescription', + { + defaultMessage: '{factor}x higher', + values: { factor: Math.round(factor) }, + } + ) + : i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThanOneAndHalfxLowerDescription', + { + defaultMessage: '{factor}x lower', + values: { factor: Math.round(factor) }, + } + ); + } else { + message = isHigher + ? i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThan100xHigherDescription', + { + defaultMessage: 'More than 100x higher', + } + ) + : i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThan100xLowerDescription', + { + defaultMessage: 'More than 100x lower', + } + ); + } + } else if (factor >= 1.05) { + message = isHigher + ? i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThanOneAndFiveHundredthsxHigherDescription', + { + defaultMessage: '{factor}x higher', + values: { factor: factor.toPrecision(2) }, + } + ) + : i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThanOneAndFiveHundredthsxLowerDescription', + { + defaultMessage: '{factor}x lower', + values: { factor: factor.toPrecision(2) }, + } + ); + } else { + message = isHigher + ? i18n.translate('xpack.ml.formatters.metricChangeDescription.unusuallyHighDescription', { + defaultMessage: 'Unusually high', + }) + : i18n.translate('xpack.ml.formatters.metricChangeDescription.unusuallyLowDescription', { + defaultMessage: 'Unusually low', + }); + } + } else { + if (actual === 0) { + message = i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.unexpectedZeroValueDescription', + { + defaultMessage: 'Unexpected zero value', + } + ); + } else { + message = i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.unexpectedNonZeroValueDescription', + { + defaultMessage: 'Unexpected non-zero value', + } + ); + } + } + } + + return { iconType, message }; +} From d03553971fb4342c45a8dc25473afbeca93af8f5 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 20 Nov 2019 13:17:54 +0100 Subject: [PATCH 05/29] Upgrade Assistant to New Platform Ready (#50163) * - Public NP Shim done - Reviving app + tests wip * Update components to consume via context and props instead of imports (tests working again) * Moved server files to np_ready dir, updated paths and introduced ServerShim and RequestShim * Removed unused comments Fixed use of legacy server components * Fix typings and add app context where needed * getSavedObjectsClient may be null, specifically during tests * Move styles for _index.scss file -> more specific file * Fix typings issue [skip ci] * Migrate to NP router --- .../plugins/upgrade_assistant/common/types.ts | 10 - .../legacy/plugins/upgrade_assistant/index.ts | 40 +++- .../plugins/upgrade_assistant/public/app.tsx | 32 --- .../public/components/_index.scss | 2 - .../components/tabs/checkup/_index.scss | 1 - .../checkup/deprecations/reindex/_index.scss | 2 - .../deprecations/reindex/flyout/_index.scss | 2 - .../components/tabs/overview/_index.scss | 1 - .../plugins/upgrade_assistant/public/index.ts | 7 + .../upgrade_assistant/public/index.tsx | 41 ---- .../upgrade_assistant/public/legacy.ts | 105 ++++++++++ .../public/np_ready/application/app.tsx | 40 ++++ .../np_ready/application/app_context.tsx | 33 +++ .../application/components/_index.scss | 2 + .../application}/components/error_banner.tsx | 0 .../components/latest_minor_banner.tsx | 2 +- .../application}/components/tabs.test.tsx | 17 +- .../application}/components/tabs.tsx | 23 +-- .../__fixtures__/checkup_api_response.json | 0 .../__snapshots__/checkup_tab.test.tsx.snap | 0 .../__snapshots__/filter_bar.test.tsx.snap | 0 .../__snapshots__/group_by_bar.test.tsx.snap | 0 .../components/tabs/checkup/_index.scss | 1 + .../tabs/checkup/checkup_tab.test.tsx | 2 - .../components/tabs/checkup/checkup_tab.tsx | 2 +- .../components/tabs/checkup/constants.tsx | 0 .../components/tabs/checkup/controls.tsx | 0 .../tabs/checkup/deprecations/_cell.scss | 0 .../checkup/deprecations/_deprecations.scss} | 3 - .../tabs/checkup/deprecations/_index.scss | 3 + .../tabs/checkup/deprecations/cell.tsx | 7 +- .../checkup/deprecations/count_summary.tsx | 2 +- .../checkup/deprecations/grouped.test.tsx | 4 +- .../tabs/checkup/deprecations/grouped.tsx | 2 +- .../tabs/checkup/deprecations/health.tsx | 0 .../tabs/checkup/deprecations/index.tsx | 0 .../checkup/deprecations/index_table.test.tsx | 2 - .../tabs/checkup/deprecations/index_table.tsx | 9 +- .../tabs/checkup/deprecations/list.test.tsx | 4 +- .../tabs/checkup/deprecations/list.tsx | 2 +- .../checkup/deprecations/reindex/_button.scss | 0 .../checkup/deprecations/reindex/_index.scss | 2 + .../checkup/deprecations/reindex/button.tsx | 12 +- .../checklist_step.test.tsx.snap | 0 .../__snapshots__/warning_step.test.tsx.snap | 0 .../deprecations/reindex/flyout/_index.scss | 2 + .../reindex/flyout/_step_progress.scss | 0 .../reindex/flyout/_warnings_step.scss | 0 .../reindex/flyout/checklist_step.test.tsx | 2 +- .../reindex/flyout/checklist_step.tsx | 2 +- .../deprecations/reindex/flyout/container.tsx | 0 .../deprecations/reindex/flyout/index.tsx | 0 .../reindex/flyout/progress.test.tsx | 2 +- .../deprecations/reindex/flyout/progress.tsx | 2 +- .../reindex/flyout/step_progress.tsx | 0 .../reindex/flyout/warning_step.test.tsx | 2 +- .../reindex/flyout/warnings_step.tsx | 2 +- .../checkup/deprecations/reindex/index.tsx | 0 .../reindex/polling_service.test.mocks.ts | 2 +- .../reindex/polling_service.test.ts | 33 ++- .../deprecations/reindex/polling_service.ts | 43 ++-- .../tabs/checkup/filter_bar.test.tsx | 0 .../components/tabs/checkup/filter_bar.tsx | 0 .../tabs/checkup/group_by_bar.test.tsx | 0 .../components/tabs/checkup/group_by_bar.tsx | 0 .../components/tabs/checkup/index.tsx | 0 .../components/tabs/overview/_index.scss | 1 + .../components/tabs/overview/_steps.scss | 0 .../overview/deprecation_logging_toggle.tsx | 19 +- .../components/tabs/overview/index.tsx | 2 +- .../components/tabs/overview/steps.tsx | 16 +- .../application}/components/types.ts | 2 +- .../{ => np_ready/application}/index.scss | 2 +- .../public/np_ready/index.ts | 11 + .../public/np_ready/plugin.ts | 25 +++ .../plugins/upgrade_assistant/server/index.ts | 29 +-- .../server/lib/es_version_precheck.test.ts | 125 ------------ .../server/lib/es_version_precheck.ts | 75 ------- .../server/np_ready/index.ts | 11 + .../lib/__fixtures__/fake_deprecations.json | 0 .../lib/__mocks__/es_version_precheck.ts | 0 .../es_migration_apis.test.ts.snap | 0 .../lib/es_deprecation_logging_apis.test.ts | 0 .../lib/es_deprecation_logging_apis.ts | 6 +- .../lib/es_migration_apis.test.ts | 0 .../{ => np_ready}/lib/es_migration_apis.ts | 7 +- .../np_ready/lib/es_version_precheck.test.ts | 151 ++++++++++++++ .../np_ready/lib/es_version_precheck.ts | 103 ++++++++++ .../lib/reindexing/credential_store.test.ts | 2 +- .../lib/reindexing/credential_store.ts | 2 +- .../{ => np_ready}/lib/reindexing/index.ts | 0 .../lib/reindexing/index_settings.test.ts | 2 +- .../lib/reindexing/index_settings.ts | 4 +- .../lib/reindexing/reindex_actions.test.ts | 4 +- .../lib/reindexing/reindex_actions.ts | 4 +- .../lib/reindexing/reindex_service.test.ts | 4 +- .../lib/reindexing/reindex_service.ts | 4 +- .../{ => np_ready}/lib/reindexing/types.ts | 0 .../{ => np_ready}/lib/reindexing/worker.ts | 6 +- .../lib/telemetry/es_ui_open_apis.test.ts | 2 +- .../lib/telemetry/es_ui_open_apis.ts | 15 +- .../lib/telemetry/es_ui_reindex_apis.test.ts | 2 +- .../lib/telemetry/es_ui_reindex_apis.ts | 11 +- .../{ => np_ready}/lib/telemetry/index.ts | 0 .../lib/telemetry/usage_collector.test.ts | 0 .../lib/telemetry/usage_collector.ts | 13 +- .../server/np_ready/plugin.ts | 42 ++++ .../np_ready/routes/__mocks__/request.mock.ts | 12 ++ .../np_ready/routes/__mocks__/routes.mock.ts | 40 ++++ .../routes/cluster_checkup.test.ts | 110 +++++----- .../server/np_ready/routes/cluster_checkup.ts | 38 ++++ .../np_ready/routes/create_request_shim.ts | 16 ++ .../routes/deprecation_logging.test.ts | 91 +++++++++ .../np_ready/routes/deprecation_logging.ts | 57 ++++++ .../routes/reindex_indices.test.ts | 188 ++++++++++------- .../{ => np_ready}/routes/reindex_indices.ts | 151 ++++++++------ .../server/np_ready/routes/telemetry.test.ts | 190 ++++++++++++++++++ .../server/np_ready/routes/telemetry.ts | 56 ++++++ .../server/np_ready/types.ts | 40 ++++ .../server/routes/cluster_checkup.ts | 38 ---- .../server/routes/deprecation_logging.test.ts | 78 ------- .../server/routes/deprecation_logging.ts | 55 ----- .../server/routes/telemetry.test.js | 146 -------------- .../server/routes/telemetry.ts | 56 ------ 124 files changed, 1534 insertions(+), 1039 deletions(-) delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/app.tsx delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/components/_index.scss delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/_index.scss delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_index.scss delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/_index.scss delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_index.scss create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/index.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/index.tsx create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/_index.scss rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/error_banner.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/latest_minor_banner.tsx (98%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs.test.tsx (83%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs.tsx (93%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/__fixtures__/checkup_api_response.json (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap (100%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/_index.scss rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/checkup_tab.test.tsx (98%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/checkup_tab.tsx (99%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/constants.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/controls.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/_cell.scss (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{components/tabs/checkup/deprecations/_index.scss => np_ready/application/components/tabs/checkup/deprecations/_deprecations.scss} (88%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_index.scss rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/cell.tsx (89%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/count_summary.tsx (93%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/grouped.test.tsx (98%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/grouped.tsx (98%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/health.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/index.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/index_table.test.tsx (98%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/index_table.tsx (92%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/list.test.tsx (96%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/list.tsx (97%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/_button.scss (100%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_index.scss rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/button.tsx (95%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/__snapshots__/warning_step.test.tsx.snap (100%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/_index.scss rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/_step_progress.scss (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/_warnings_step.scss (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/checklist_step.test.tsx (98%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/checklist_step.tsx (98%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/container.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/index.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/progress.test.tsx (99%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/progress.tsx (99%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/step_progress.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/warning_step.test.tsx (95%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx (99%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/index.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts (87%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/polling_service.test.ts (75%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/deprecations/reindex/polling_service.ts (82%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/filter_bar.test.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/filter_bar.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/group_by_bar.test.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/group_by_bar.tsx (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/checkup/index.tsx (100%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_index.scss rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/overview/_steps.scss (100%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/overview/deprecation_logging_toggle.tsx (87%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/overview/index.tsx (96%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/tabs/overview/steps.tsx (96%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/components/types.ts (94%) rename x-pack/legacy/plugins/upgrade_assistant/public/{ => np_ready/application}/index.scss (66%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/__fixtures__/fake_deprecations.json (100%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/__mocks__/es_version_precheck.ts (100%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/__snapshots__/es_migration_apis.test.ts.snap (100%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/es_deprecation_logging_apis.test.ts (100%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/es_deprecation_logging_apis.ts (94%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/es_migration_apis.test.ts (100%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/es_migration_apis.ts (96%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/credential_store.test.ts (95%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/credential_store.ts (96%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/index.ts (100%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/index_settings.test.ts (99%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/index_settings.ts (97%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/reindex_actions.test.ts (99%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/reindex_actions.ts (99%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/reindex_service.test.ts (99%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/reindex_service.ts (99%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/types.ts (100%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/reindexing/worker.ts (97%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/telemetry/es_ui_open_apis.test.ts (98%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/telemetry/es_ui_open_apis.ts (75%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/telemetry/es_ui_reindex_apis.test.ts (98%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/telemetry/es_ui_reindex_apis.ts (86%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/telemetry/index.ts (100%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/telemetry/usage_collector.test.ts (100%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/lib/telemetry/usage_collector.ts (87%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/routes/cluster_checkup.test.ts (53%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/routes/reindex_indices.test.ts (58%) rename x-pack/legacy/plugins/upgrade_assistant/server/{ => np_ready}/routes/reindex_indices.ts (56%) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.test.js delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/common/types.ts b/x-pack/legacy/plugins/upgrade_assistant/common/types.ts index 60018173781a0d..ce653e461e13b8 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/common/types.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; import { SavedObject, SavedObjectAttributes } from 'src/core/server'; export enum ReindexStep { @@ -79,15 +78,6 @@ export interface UIReindex { stop: boolean; } -export interface UpgradeAssistantTelemetryServer extends Legacy.Server { - usage: { - collectorSet: { - makeUsageCollector: any; - register: any; - }; - }; -} - export interface UpgradeAssistantTelemetrySavedObject { ui_open: { overview: number; diff --git a/x-pack/legacy/plugins/upgrade_assistant/index.ts b/x-pack/legacy/plugins/upgrade_assistant/index.ts index 7c38fbf02a5647..f1762498246c76 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/index.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/index.ts @@ -3,18 +3,23 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import _ from 'lodash'; import Joi from 'joi'; import { Legacy } from 'kibana'; import { resolve } from 'path'; import mappings from './mappings.json'; -import { initServer } from './server'; +import { plugin } from './server/np_ready'; export function upgradeAssistant(kibana: any) { - return new kibana.Plugin({ + const publicSrc = resolve(__dirname, 'public'); + const npSrc = resolve(publicSrc, 'np_ready'); + + const config: Legacy.PluginSpecOptions = { id: 'upgrade_assistant', configPrefix: 'xpack.upgrade_assistant', require: ['elasticsearch'], uiExports: { + // @ts-ignore managementSections: ['plugins/upgrade_assistant'], savedObjectSchemas: { 'upgrade-assistant-reindex-operation': { @@ -24,10 +29,10 @@ export function upgradeAssistant(kibana: any) { isNamespaceAgnostic: true, }, }, - styleSheetPaths: resolve(__dirname, 'public/index.scss'), + styleSheetPaths: resolve(npSrc, 'application/index.scss'), mappings, }, - publicDir: resolve(__dirname, 'public'), + publicDir: publicSrc, config() { return Joi.object({ @@ -37,7 +42,30 @@ export function upgradeAssistant(kibana: any) { init(server: Legacy.Server) { // Add server routes and initialize the plugin here - initServer(server); + const instance = plugin({} as any); + instance.setup(server.newPlatform.setup.core, { + __LEGACY: { + // Legacy objects + events: server.events, + usage: server.usage, + savedObjects: server.savedObjects, + + // Legacy functions + log: server.log.bind(server), + + // Legacy plugins + plugins: { + elasticsearch: server.plugins.elasticsearch, + xpack_main: server.plugins.xpack_main, + cloud: { + config: { + isCloudEnabled: _.get(server.plugins, 'cloud.config.isCloudEnabled', false), + }, + }, + }, + }, + }); }, - }); + }; + return new kibana.Plugin(config); } diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/app.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/app.tsx deleted file mode 100644 index 3bf3375c43bd98..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/app.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; - -import { EuiPageHeader, EuiPageHeaderSection, EuiTitle } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { NEXT_MAJOR_VERSION } from '../common/version'; -import { UpgradeAssistantTabs } from './components/tabs'; - -export const RootComponent: React.StatelessComponent = () => ( -
- - - -

- -

-
-
-
- -
-); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/_index.scss deleted file mode 100644 index 80260319223018..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './tabs/checkup/index'; -@import './tabs/overview/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/_index.scss deleted file mode 100644 index 430d1e0aedf7bd..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './deprecations/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_index.scss deleted file mode 100644 index 2d52575cffbbbe..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './button'; -@import './flyout/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/_index.scss deleted file mode 100644 index f695ae175fecad..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './step_progress'; -@import './warnings_step'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_index.scss deleted file mode 100644 index a6bbc6ba132988..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './steps'; \ No newline at end of file diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/index.ts b/x-pack/legacy/plugins/upgrade_assistant/public/index.ts new file mode 100644 index 00000000000000..d22b5d64b6b469 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './legacy'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/index.tsx deleted file mode 100644 index 2f631d3771ecb0..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/index.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { wrapInI18nContext } from 'ui/i18n'; -// @ts-ignore -import { management } from 'ui/management'; -// @ts-ignore -import { uiModules } from 'ui/modules'; -// @ts-ignore -import routes from 'ui/routes'; -import { NEXT_MAJOR_VERSION } from '../common/version'; -import { RootComponent } from './app'; - -const BASE_PATH = `/management/elasticsearch/upgrade_assistant`; - -function startApp() { - management.getSection('elasticsearch').register('upgrade_assistant', { - visible: true, - display: i18n.translate('xpack.upgradeAssistant.appTitle', { - defaultMessage: '{version} Upgrade Assistant', - values: { version: `${NEXT_MAJOR_VERSION}.0` }, - }), - order: 100, - url: `#${BASE_PATH}`, - }); - - uiModules.get('kibana').directive('upgradeAssistant', (reactDirective: any) => { - return reactDirective(wrapInI18nContext(RootComponent)); - }); - - routes.when(`${BASE_PATH}/:view?`, { - template: - '', - }); -} - -startApp(); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts b/x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts new file mode 100644 index 00000000000000..3d5144249dfef9 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ComponentType } from 'react'; +import { i18n } from '@kbn/i18n'; + +/* LEGACY IMPORTS */ +import { npSetup } from 'ui/new_platform'; +import { wrapInI18nContext } from 'ui/i18n'; +import { management } from 'ui/management'; +// @ts-ignore +import { uiModules } from 'ui/modules'; +import routes from 'ui/routes'; +import chrome from 'ui/chrome'; +/* LEGACY IMPORTS */ + +import { NEXT_MAJOR_VERSION } from '../common/version'; +import { plugin } from './np_ready'; + +const BASE_PATH = `/management/elasticsearch/upgrade_assistant`; + +export interface LegacyAppMountParameters { + __LEGACY: { renderToElement: (RootComponent: ComponentType) => void }; +} + +export interface LegacyApp { + mount(ctx: any, params: LegacyAppMountParameters): void; +} + +export interface LegacyManagementPlugin { + sections: { + get( + name: string + ): { + registerApp(app: LegacyApp): void; + }; + }; +} + +// Based on /rfcs/text/0006_management_section_service.md +export interface LegacyPlugins { + management: LegacyManagementPlugin; + __LEGACY: { + XSRF: string; + isCloudEnabled: boolean; + }; +} + +function startApp() { + routes.when(`${BASE_PATH}/:view?`, { + template: + '', + }); + + const legacyPluginsShim: LegacyPlugins = { + __LEGACY: { + XSRF: chrome.getXsrfToken(), + isCloudEnabled: chrome.getInjected('isCloudEnabled', false), + }, + management: { + sections: { + get(_: string) { + return { + registerApp(app) { + management.getSection('elasticsearch').register('upgrade_assistant', { + visible: true, + display: i18n.translate('xpack.upgradeAssistant.appTitle', { + defaultMessage: '{version} Upgrade Assistant', + values: { version: `${NEXT_MAJOR_VERSION}.0` }, + }), + order: 100, + url: `#${BASE_PATH}`, + }); + + app.mount( + {}, + { + __LEGACY: { + // While there is not an NP API for registering management section apps yet + renderToElement: RootComponent => { + uiModules + .get('kibana') + .directive('upgradeAssistant', (reactDirective: any) => { + return reactDirective(wrapInI18nContext(RootComponent)); + }); + }, + }, + } + ); + }, + }; + }, + }, + }, + }; + + const pluginInstance = plugin(); + + pluginInstance.setup(npSetup.core, legacyPluginsShim); +} + +startApp(); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx new file mode 100644 index 00000000000000..571967ab114c90 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; + +import { EuiPageHeader, EuiPageHeaderSection, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NEXT_MAJOR_VERSION } from '../../../common/version'; +import { UpgradeAssistantTabs } from './components/tabs'; +import { AppContextProvider, ContextValue, AppContext } from './app_context'; + +type AppDependencies = ContextValue; + +export const RootComponent = (deps: AppDependencies) => { + return ( + +
+ + + +

+ +

+
+
+
+ + {({ http }) => } + +
+
+ ); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx new file mode 100644 index 00000000000000..a48a4efa3bbdfb --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { HttpSetup } from 'src/core/public'; +import React, { createContext, useContext } from 'react'; + +export interface ContextValue { + http: HttpSetup; + isCloudEnabled: boolean; + XSRF: string; +} + +export const AppContext = createContext({} as any); + +export const AppContextProvider = ({ + children, + value, +}: { + children: React.ReactNode; + value: ContextValue; +}) => { + return {children}; +}; + +export const useAppContext = () => { + const ctx = useContext(AppContext); + if (!ctx) { + throw new Error('useAppContext must be called from inside AppContext'); + } + return ctx; +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/_index.scss new file mode 100644 index 00000000000000..bb01107f334f65 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/_index.scss @@ -0,0 +1,2 @@ +@import 'tabs/checkup/index'; +@import 'tabs/overview/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/error_banner.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/error_banner.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/error_banner.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/error_banner.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/latest_minor_banner.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/latest_minor_banner.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/latest_minor_banner.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/latest_minor_banner.tsx index 1f24377eba6cd1..02f090565ebe6b 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/latest_minor_banner.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/latest_minor_banner.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { EuiCallOut, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../common/version'; +import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../../common/version'; export const LatestMinorBanner: React.StatelessComponent = () => ( ({ get: jest.fn(), create: jest.fn(), @@ -23,6 +21,13 @@ import { OverviewTab } from './tabs/overview'; // Used to wait for promises to resolve and renders to finish before reading updates const promisesToResolve = () => new Promise(resolve => setTimeout(resolve, 0)); +const mockHttp = { + basePath: { + prepend: () => 'test', + }, + fetch() {}, +}; + describe('UpgradeAssistantTabs', () => { test('renders loading state', async () => { // @ts-ignore @@ -31,7 +36,7 @@ describe('UpgradeAssistantTabs', () => { /* never resolve */ }) ); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); // Should pass down loading status to child component expect(wrapper.find(OverviewTab).prop('loadingState')).toEqual(LoadingState.Loading); }); @@ -44,7 +49,7 @@ describe('UpgradeAssistantTabs', () => { indices: [], }, }); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); expect(axios.get).toHaveBeenCalled(); await promisesToResolve(); wrapper.update(); @@ -55,7 +60,7 @@ describe('UpgradeAssistantTabs', () => { test('network failure', async () => { // @ts-ignore axios.get.mockRejectedValue(new Error(`oh no!`)); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); await promisesToResolve(); wrapper.update(); // Should pass down error status to child component @@ -65,7 +70,7 @@ describe('UpgradeAssistantTabs', () => { it('upgrade error', async () => { // @ts-ignore axios.get.mockRejectedValue({ response: { status: 426 } }); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); await promisesToResolve(); wrapper.update(); // Should display an informative message if the cluster is currently mid-upgrade diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs.tsx similarity index 93% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs.tsx index 76cc1e33ca06b2..0b154fb20404dc 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs.tsx @@ -16,11 +16,9 @@ import { EuiTabbedContentTab, } from '@elastic/eui'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; +import { HttpSetup } from 'src/core/public'; -import chrome from 'ui/chrome'; -import { kfetch } from 'ui/kfetch'; - -import { UpgradeAssistantStatus } from '../../server/lib/es_migration_apis'; +import { UpgradeAssistantStatus } from '../../../../server/np_ready/lib/es_migration_apis'; import { LatestMinorBanner } from './latest_minor_banner'; import { CheckupTab } from './tabs/checkup'; import { OverviewTab } from './tabs/overview'; @@ -41,13 +39,11 @@ interface TabsState { clusterUpgradeState: ClusterUpgradeState; } -export class UpgradeAssistantTabsUI extends React.Component< - ReactIntl.InjectedIntlProps, - TabsState -> { - constructor(props: ReactIntl.InjectedIntlProps) { - super(props); +type Props = ReactIntl.InjectedIntlProps & { http: HttpSetup }; +export class UpgradeAssistantTabsUI extends React.Component { + constructor(props: Props) { + super(props); this.state = { loadingState: LoadingState.Loading, clusterUpgradeState: ClusterUpgradeState.needsUpgrade, @@ -157,7 +153,9 @@ export class UpgradeAssistantTabsUI extends React.Component< private loadData = async () => { try { this.setState({ loadingState: LoadingState.Loading }); - const resp = await axios.get(chrome.addBasePath('/api/upgrade_assistant/status')); + const resp = await axios.get( + this.props.http.basePath.prepend('/api/upgrade_assistant/status') + ); this.setState({ loadingState: LoadingState.Success, checkupData: resp.data, @@ -246,8 +244,7 @@ export class UpgradeAssistantTabsUI extends React.Component< this.setState({ telemetryState: TelemetryState.Running }); - await kfetch({ - pathname: '/api/upgrade_assistant/telemetry/ui_open', + await this.props.http.fetch('/api/upgrade_assistant/telemetry/ui_open', { method: 'PUT', body: JSON.stringify(set({}, tabName, true)), }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/__fixtures__/checkup_api_response.json b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/__fixtures__/checkup_api_response.json similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/__fixtures__/checkup_api_response.json rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/__fixtures__/checkup_api_response.json diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/_index.scss new file mode 100644 index 00000000000000..d64400a8abdcf4 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/_index.scss @@ -0,0 +1 @@ +@import 'deprecations/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.test.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.test.tsx index 1805cb49e6ee66..9ba5441604ddc0 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.test.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.test.tsx @@ -11,8 +11,6 @@ import { LoadingState } from '../../types'; import AssistanceData from '../__fixtures__/checkup_api_response.json'; import { CheckupTab } from './checkup_tab'; -jest.mock('ui/kfetch'); - const defaultProps = { checkupLabel: 'index', deprecations: AssistanceData.indices, diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.tsx similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.tsx index 5b8fd21f9c1fc1..9aa40663125aed 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NEXT_MAJOR_VERSION } from '../../../../common/version'; +import { NEXT_MAJOR_VERSION } from '../../../../../../common/version'; import { LoadingErrorBanner } from '../../error_banner'; import { GroupByOption, diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/constants.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/constants.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/constants.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/constants.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/controls.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/controls.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/controls.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/controls.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_cell.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_cell.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_cell.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_cell.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_deprecations.scss similarity index 88% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_index.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_deprecations.scss index e370aeac0dfa23..445ef6269afb93 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_index.scss +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_deprecations.scss @@ -1,6 +1,3 @@ -@import './cell'; -@import './reindex/index'; - .upgDeprecations { // Pull the container through the padding of EuiPageContent margin-left: -$euiSizeL; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_index.scss new file mode 100644 index 00000000000000..55aff6b379db54 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_index.scss @@ -0,0 +1,3 @@ +@import 'cell'; +@import 'deprecations'; +@import 'reindex/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/cell.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/cell.tsx similarity index 89% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/cell.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/cell.tsx index 29a0076d00d0ea..98672eb249c9bd 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/cell.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/cell.tsx @@ -17,6 +17,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { ReindexButton } from './reindex'; +import { AppContext } from '../../../../app_context'; interface DeprecationCellProps { items?: Array<{ title?: string; body: string }>; @@ -77,7 +78,11 @@ export const DeprecationCell: StatelessComponent = ({ {reindexIndexName && ( - + + {({ http, XSRF }) => ( + + )} + )} diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/count_summary.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/count_summary.tsx similarity index 93% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/count_summary.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/count_summary.tsx index a66244b0e7886c..d3166292822d76 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/count_summary.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/count_summary.tsx @@ -8,7 +8,7 @@ import React, { Fragment, StatelessComponent } from 'react'; import { EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; export const DeprecationCountSummary: StatelessComponent<{ deprecations: EnrichedDeprecationInfo[]; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.test.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.test.tsx index 6c541742a539b2..28f5f6894b78f2 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.test.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.test.tsx @@ -11,12 +11,10 @@ import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import { EuiBadge, EuiPagination } from '@elastic/eui'; import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; import { GroupByOption, LevelFilterOption } from '../../../types'; import { DeprecationAccordion, filterDeps, GroupedDeprecations } from './grouped'; -jest.mock('ui/kfetch'); - describe('filterDeps', () => { test('filters on levels', () => { const fd = filterDeps(LevelFilterOption.critical); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.tsx index 9ce0b8a8cefd36..9f53c96bce5c6e 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.tsx @@ -19,7 +19,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; import { GroupByOption, LevelFilterOption } from '../../../types'; import { DeprecationCountSummary } from './count_summary'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/health.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/health.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/health.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/health.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.test.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.test.tsx index 040459309f7285..8c211704c7aff7 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.test.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.test.tsx @@ -9,8 +9,6 @@ import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import { IndexDeprecationTableProps, IndexDeprecationTableUI } from './index_table'; -jest.mock('ui/kfetch'); - describe('IndexDeprecationTable', () => { const defaultProps = { indices: [ diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.tsx similarity index 92% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.tsx index 5a1deb59c270ee..eba906edc05095 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.tsx @@ -10,6 +10,7 @@ import React from 'react'; import { EuiBasicTable } from '@elastic/eui'; import { injectI18n } from '@kbn/i18n/react'; import { ReindexButton } from './reindex'; +import { AppContext } from '../../../../app_context'; const PAGE_SIZES = [10, 25, 50, 100, 250, 500, 1000]; @@ -143,7 +144,13 @@ export class IndexDeprecationTableUI extends React.Component< actions: [ { render(indexDep: IndexDeprecationDetails) { - return ; + return ( + + {({ XSRF, http }) => ( + + )} + + ); }, }, ], diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.test.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.test.tsx index 6be89f411f5804..78ded735934641 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.test.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.test.tsx @@ -7,12 +7,10 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; import { GroupByOption } from '../../../types'; import { DeprecationList } from './list'; -jest.mock('ui/kfetch'); - describe('DeprecationList', () => { describe('group by message', () => { const defaultProps = { diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.tsx similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.tsx index cb38b848b3bd7c..256a0580c7617d 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.tsx @@ -7,7 +7,7 @@ import React, { StatelessComponent } from 'react'; import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; import { GroupByOption } from '../../../types'; import { COLOR_MAP, LEVEL_MAP } from '../constants'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_button.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_button.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_button.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_button.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_index.scss new file mode 100644 index 00000000000000..014edc96b05652 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_index.scss @@ -0,0 +1,2 @@ +@import 'button'; +@import 'flyout/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/button.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/button.tsx similarity index 95% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/button.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/button.tsx index 6addd3dae642ab..2a28018a3ae81e 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/button.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/button.tsx @@ -10,14 +10,16 @@ import { Subscription } from 'rxjs'; import { EuiButton, EuiLoadingSpinner } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { kfetch } from 'ui/kfetch'; -import { ReindexStatus, UIReindexOption } from '../../../../../../common/types'; +import { HttpSetup } from 'src/core/public'; +import { ReindexStatus, UIReindexOption } from '../../../../../../../../common/types'; import { LoadingState } from '../../../../types'; import { ReindexFlyout } from './flyout'; import { ReindexPollingService, ReindexState } from './polling_service'; interface ReindexButtonProps { indexName: string; + xsrf: string; + http: HttpSetup; } interface ReindexButtonState { @@ -152,7 +154,8 @@ export class ReindexButton extends React.Component { diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx index 1465812c4803d8..b6e577d913cacf 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx @@ -21,7 +21,7 @@ import { EuiText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ReindexWarning } from '../../../../../../../common/types'; +import { ReindexWarning } from '../../../../../../../../../common/types'; interface CheckedIds { [id: string]: boolean; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/index.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/index.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/index.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts similarity index 87% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts index f70822aef102cb..dc7a758839fe56 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ReindexStatus, ReindexStep } from '../../../../../../common/types'; +import { ReindexStatus, ReindexStep } from '../../../../../../../../common/types'; export const mockClient = { post: jest.fn().mockResolvedValue({ diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts similarity index 75% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts index 9f47f51bc8cde6..cb2a0856f0f2e9 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts @@ -6,8 +6,9 @@ import { mockClient } from './polling_service.test.mocks'; -import { ReindexStatus, ReindexStep } from '../../../../../../common/types'; +import { ReindexStatus, ReindexStep } from '../../../../../../../../common/types'; import { ReindexPollingService } from './polling_service'; +import { httpServiceMock } from 'src/core/public/http/http_service.mock'; describe('ReindexPollingService', () => { beforeEach(() => { @@ -24,7 +25,11 @@ describe('ReindexPollingService', () => { }, }); - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); service.updateStatus(); await new Promise(resolve => setTimeout(resolve, 1200)); // wait for poll interval @@ -45,7 +50,11 @@ describe('ReindexPollingService', () => { }, }); - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); service.updateStatus(); await new Promise(resolve => setTimeout(resolve, 1200)); // wait for poll interval @@ -66,7 +75,11 @@ describe('ReindexPollingService', () => { }, }); - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); service.updateStatus(); await new Promise(resolve => setTimeout(resolve, 1200)); // wait for poll interval @@ -76,7 +89,11 @@ describe('ReindexPollingService', () => { describe('startReindex', () => { it('posts to endpoint', async () => { - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); await service.startReindex(); expect(mockClient.post).toHaveBeenCalledWith('/api/upgrade_assistant/reindex/myIndex'); @@ -85,7 +102,11 @@ describe('ReindexPollingService', () => { describe('cancelReindex', () => { it('posts to cancel endpoint', async () => { - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); await service.cancelReindex(); expect(mockClient.post).toHaveBeenCalledWith('/api/upgrade_assistant/reindex/myIndex/cancel'); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.ts similarity index 82% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.ts rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.ts index 3977a169f4acab..879fafe610982b 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.ts @@ -3,31 +3,21 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import axios from 'axios'; -import chrome from 'ui/chrome'; +import axios, { AxiosInstance } from 'axios'; import { BehaviorSubject } from 'rxjs'; + +import { HttpSetup } from 'src/core/public'; import { IndexGroup, ReindexOperation, ReindexStatus, ReindexStep, ReindexWarning, -} from '../../../../../../common/types'; +} from '../../../../../../../../common/types'; import { LoadingState } from '../../../../types'; const POLL_INTERVAL = 1000; -const XSRF = chrome.getXsrfToken(); - -export const APIClient = axios.create({ - headers: { - Accept: 'application/json', - credentials: 'same-origin', - 'Content-Type': 'application/json', - 'kbn-version': XSRF, - 'kbn-xsrf': XSRF, - }, -}); export interface ReindexState { loadingState: LoadingState; @@ -55,13 +45,24 @@ interface StatusResponse { export class ReindexPollingService { public status$: BehaviorSubject; private pollTimeout?: NodeJS.Timeout; + private APIClient: AxiosInstance; - constructor(private indexName: string) { + constructor(private indexName: string, private xsrf: string, private http: HttpSetup) { this.status$ = new BehaviorSubject({ loadingState: LoadingState.Loading, errorMessage: null, reindexTaskPercComplete: null, }); + + this.APIClient = axios.create({ + headers: { + Accept: 'application/json', + credentials: 'same-origin', + 'Content-Type': 'application/json', + 'kbn-version': this.xsrf, + 'kbn-xsrf': this.xsrf, + }, + }); } public updateStatus = async () => { @@ -69,8 +70,8 @@ export class ReindexPollingService { this.stopPolling(); try { - const { data } = await APIClient.get( - chrome.addBasePath(`/api/upgrade_assistant/reindex/${this.indexName}`) + const { data } = await this.APIClient.get( + this.http.basePath.prepend(`/api/upgrade_assistant/reindex/${this.indexName}`) ); this.updateWithResponse(data); @@ -106,8 +107,8 @@ export class ReindexPollingService { errorMessage: null, cancelLoadingState: undefined, }); - const { data } = await APIClient.post( - chrome.addBasePath(`/api/upgrade_assistant/reindex/${this.indexName}`) + const { data } = await this.APIClient.post( + this.http.basePath.prepend(`/api/upgrade_assistant/reindex/${this.indexName}`) ); this.updateWithResponse({ reindexOp: data }); @@ -124,8 +125,8 @@ export class ReindexPollingService { cancelLoadingState: LoadingState.Loading, }); - await APIClient.post( - chrome.addBasePath(`/api/upgrade_assistant/reindex/${this.indexName}/cancel`) + await this.APIClient.post( + this.http.basePath.prepend(`/api/upgrade_assistant/reindex/${this.indexName}/cancel`) ); } catch (e) { this.status$.next({ diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/filter_bar.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.test.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/filter_bar.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.test.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/filter_bar.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/filter_bar.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/group_by_bar.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.test.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/group_by_bar.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.test.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/group_by_bar.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/group_by_bar.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/index.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/index.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/index.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_index.scss new file mode 100644 index 00000000000000..c64a8f5a5326d0 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_index.scss @@ -0,0 +1 @@ +@import 'steps'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_steps.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_steps.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_steps.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_steps.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/deprecation_logging_toggle.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/deprecation_logging_toggle.tsx similarity index 87% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/deprecation_logging_toggle.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/deprecation_logging_toggle.tsx index 8d107331eb65f0..97eb284c7b771f 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/deprecation_logging_toggle.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/deprecation_logging_toggle.tsx @@ -10,19 +10,25 @@ import React from 'react'; import { EuiLoadingSpinner, EuiSwitch } from '@elastic/eui'; import { injectI18n } from '@kbn/i18n/react'; -import chrome from 'ui/chrome'; +import { HttpSetup } from 'src/core/public'; + import { LoadingState } from '../../types'; +interface DeprecationLoggingTabProps extends ReactIntl.InjectedIntlProps { + xsrf: string; + http: HttpSetup; +} + interface DeprecationLoggingTabState { loadingState: LoadingState; loggingEnabled?: boolean; } export class DeprecationLoggingToggleUI extends React.Component< - ReactIntl.InjectedIntlProps, + DeprecationLoggingTabProps, DeprecationLoggingTabState > { - constructor(props: ReactIntl.InjectedIntlProps) { + constructor(props: DeprecationLoggingTabProps) { super(props); this.state = { @@ -83,7 +89,7 @@ export class DeprecationLoggingToggleUI extends React.Component< try { this.setState({ loadingState: LoadingState.Loading }); const resp = await axios.get( - chrome.addBasePath('/api/upgrade_assistant/deprecation_logging') + this.props.http.basePath.prepend('/api/upgrade_assistant/deprecation_logging') ); this.setState({ loadingState: LoadingState.Success, @@ -96,18 +102,19 @@ export class DeprecationLoggingToggleUI extends React.Component< private toggleLogging = async () => { try { + const { http, xsrf } = this.props; // Optimistically toggle the UI const newEnabled = !this.state.loggingEnabled; this.setState({ loadingState: LoadingState.Loading, loggingEnabled: newEnabled }); const resp = await axios.put( - chrome.addBasePath('/api/upgrade_assistant/deprecation_logging'), + http.basePath.prepend('/api/upgrade_assistant/deprecation_logging'), { isEnabled: newEnabled, }, { headers: { - 'kbn-xsrf': chrome.getXsrfToken(), + 'kbn-xsrf': xsrf, }, } ); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/index.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/index.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/index.tsx index 834f5f4afe5f66..51968a9b864aef 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/index.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/index.tsx @@ -19,7 +19,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NEXT_MAJOR_VERSION } from '../../../../common/version'; +import { NEXT_MAJOR_VERSION } from '../../../../../../common/version'; import { LoadingErrorBanner } from '../../error_banner'; import { LoadingState, UpgradeAssistantTabProps } from '../../types'; import { Steps } from './steps'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/steps.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/steps.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/steps.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/steps.tsx index d43a86d2b0e061..d1e88ba8b4b0ce 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/steps.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/steps.tsx @@ -18,11 +18,11 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; -import chrome from 'ui/chrome'; -import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../../common/version'; +import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../../../../common/version'; import { UpgradeAssistantTabProps } from '../../types'; import { DeprecationLoggingToggle } from './deprecation_logging_toggle'; +import { useAppContext } from '../../../app_context'; // Leaving these here even if unused so they are picked up for i18n static analysis // Keep this until last minor release (when next major is also released). @@ -54,7 +54,7 @@ const WAIT_FOR_RELEASE_STEP = { // Swap in this step for the one above it on the last minor release. // @ts-ignore -const START_UPGRADE_STEP = { +const START_UPGRADE_STEP = (isCloudEnabled: boolean) => ({ title: i18n.translate('xpack.upgradeAssistant.overviewTab.steps.startUpgradeStep.stepTitle', { defaultMessage: 'Start your upgrade', }), @@ -62,7 +62,7 @@ const START_UPGRADE_STEP = {

- {chrome.getInjected('isCloudEnabled', false) ? ( + {isCloudEnabled ? ( ), -}; +}); export const StepsUI: StatelessComponent = ({ checkupData, setSelectedTabIndex, intl }) => { @@ -100,6 +100,9 @@ export const StepsUI: StatelessComponent - + ), @@ -264,6 +267,7 @@ export const StepsUI: StatelessComponent ); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/types.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/types.ts similarity index 94% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/types.ts rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/types.ts index dc31308a1ea340..2d9a373f20b7e9 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/types.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/types.ts @@ -9,7 +9,7 @@ import React from 'react'; import { EnrichedDeprecationInfo, UpgradeAssistantStatus, -} from '../../server/lib/es_migration_apis'; +} from '../../../../server/np_ready/lib/es_migration_apis'; export interface UpgradeAssistantTabProps { alertBanner?: React.ReactNode; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/index.scss similarity index 66% rename from x-pack/legacy/plugins/upgrade_assistant/public/index.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/index.scss index 999cca93fcd7a0..6000af5498cd6e 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/index.scss +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/index.scss @@ -1,3 +1,3 @@ @import 'src/legacy/ui/public/styles/_styling_constants'; -@import './components/index'; +@import 'components/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts new file mode 100644 index 00000000000000..020d6972f8280c --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { UpgradeAssistantUIPlugin } from './plugin'; + +export const plugin = () => { + return new UpgradeAssistantUIPlugin(); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts new file mode 100644 index 00000000000000..16a0c9632fb25c --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Plugin, CoreSetup } from 'src/core/public'; +import { RootComponent } from './application/app'; +import { LegacyPlugins } from '../legacy'; + +export class UpgradeAssistantUIPlugin implements Plugin { + async setup( + { http }: CoreSetup, + { management, __LEGACY: { XSRF, isCloudEnabled } }: LegacyPlugins + ) { + const appRegistrar = management.sections.get('kibana'); + return appRegistrar.registerApp({ + mount(__, { __LEGACY: { renderToElement } }) { + return renderToElement(() => RootComponent({ http, XSRF, isCloudEnabled })); + }, + }); + } + async start() {} + async stop() {} +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/index.ts b/x-pack/legacy/plugins/upgrade_assistant/server/index.ts index 5fcdbe136a4f2a..8b0704283509d2 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/index.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/index.ts @@ -4,31 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; -import { UpgradeAssistantTelemetryServer } from '../common/types'; -import { credentialStoreFactory } from './lib/reindexing/credential_store'; -import { makeUpgradeAssistantUsageCollector } from './lib/telemetry'; -import { registerClusterCheckupRoutes } from './routes/cluster_checkup'; -import { registerDeprecationLoggingRoutes } from './routes/deprecation_logging'; -import { registerReindexIndicesRoutes, registerReindexWorker } from './routes/reindex_indices'; -import { registerTelemetryRoutes } from './routes/telemetry'; - -export function initServer(server: Legacy.Server) { - registerClusterCheckupRoutes(server); - registerDeprecationLoggingRoutes(server); - - // The ReindexWorker uses a map of request headers that contain the authentication credentials - // for a given reindex. We cannot currently store these in an the .kibana index b/c we do not - // want to expose these credentials to any unauthenticated users. We also want to avoid any need - // to add a user for a special index just for upgrading. This in-memory cache allows us to - // process jobs without the browser staying on the page, but will require that jobs go into - // a paused state if no Kibana nodes have the required credentials. - const credentialStore = credentialStoreFactory(); - - const worker = registerReindexWorker(server, credentialStore); - registerReindexIndicesRoutes(server, worker, credentialStore); - - // Bootstrap the needed routes and the collector for the telemetry - registerTelemetryRoutes(server as UpgradeAssistantTelemetryServer); - makeUpgradeAssistantUsageCollector(server as UpgradeAssistantTelemetryServer); -} +export { plugin } from './np_ready'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts deleted file mode 100644 index 9a0fca6d4139c2..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { SemVer } from 'semver'; -import { CURRENT_VERSION } from '../../common/version'; -import { - EsVersionPrecheck, - getAllNodeVersions, - verifyAllMatchKibanaVersion, -} from './es_version_precheck'; - -describe('getAllNodeVersions', () => { - it('returns a list of unique node versions', async () => { - const callCluster = jest.fn().mockResolvedValue({ - nodes: { - node1: { version: '7.0.0' }, - node2: { version: '7.0.0' }, - node3: { version: '6.0.0' }, - }, - }); - - await expect(getAllNodeVersions(callCluster)).resolves.toEqual([ - new SemVer('6.0.0'), - new SemVer('7.0.0'), - ]); - }); -}); - -describe('verifyAllMatchKibanaVersion', () => { - it('throws if any are higher version', () => { - expect(() => - verifyAllMatchKibanaVersion([new SemVer('99999.0.0')]) - ).toThrowErrorMatchingInlineSnapshot( - `"There are some nodes running a different version of Elasticsearch"` - ); - }); - - it('throws if any are lower version', () => { - expect(() => - verifyAllMatchKibanaVersion([new SemVer('0.0.0')]) - ).toThrowErrorMatchingInlineSnapshot( - `"There are some nodes running a different version of Elasticsearch"` - ); - }); - - it('does not throw if all are same major', () => { - const versions = [ - CURRENT_VERSION, - CURRENT_VERSION.inc('minor'), - CURRENT_VERSION.inc('minor').inc('minor'), - ]; - - expect(() => verifyAllMatchKibanaVersion(versions)).not.toThrow(); - }); -}); - -describe('EsVersionPrecheck', () => { - it('throws a 403 when callCluster fails with a 403', async () => { - const fakeCallWithRequest = jest.fn().mockRejectedValue({ status: 403 }); - const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest })); - const fakeRequest = { - server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } }, - } as any; - - await expect(EsVersionPrecheck.method(fakeRequest, {} as any)).rejects.toHaveProperty( - 'output.statusCode', - 403 - ); - }); - - it('throws a 426 message w/ allNodesUpgraded = false when nodes are not on same version', async () => { - const fakeCallWithRequest = jest.fn().mockResolvedValue({ - nodes: { - node1: { version: CURRENT_VERSION.raw }, - node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, - }, - }); - const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest })); - const fakeRequest = { - server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } }, - } as any; - - const result = EsVersionPrecheck.method(fakeRequest, {} as any); - await expect(result).rejects.toHaveProperty('output.statusCode', 426); - await expect(result).rejects.toHaveProperty( - 'output.payload.attributes.allNodesUpgraded', - false - ); - }); - - it('throws a 426 message w/ allNodesUpgraded = true when nodes are on next version', async () => { - const fakeCallWithRequest = jest.fn().mockResolvedValue({ - nodes: { - node1: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, - node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, - }, - }); - const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest })); - const fakeRequest = { - server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } }, - } as any; - - const result = EsVersionPrecheck.method(fakeRequest, {} as any); - await expect(result).rejects.toHaveProperty('output.statusCode', 426); - await expect(result).rejects.toHaveProperty('output.payload.attributes.allNodesUpgraded', true); - }); - - it('returns true when nodes are on same version', async () => { - const fakeCallWithRequest = jest.fn().mockResolvedValue({ - nodes: { - node1: { version: CURRENT_VERSION.raw }, - node2: { version: CURRENT_VERSION.raw }, - }, - }); - const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest })); - const fakeRequest = { - server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } }, - } as any; - - await expect(EsVersionPrecheck.method(fakeRequest, {} as any)).resolves.toBe(true); - }); -}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.ts b/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.ts deleted file mode 100644 index d84d5f54444723..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.ts +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import Boom from 'boom'; -import { Request, RouteOptionsPreObject } from 'hapi'; -import { uniq } from 'lodash'; -import { SemVer } from 'semver'; - -import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { CURRENT_VERSION } from '../../common/version'; - -/** - * Returns an array of all the unique Elasticsearch Node Versions in the Elasticsearch cluster. - * @param request - */ -export const getAllNodeVersions = async (callCluster: CallCluster) => { - // Get the version information for all nodes in the cluster. - const { nodes } = (await callCluster('nodes.info', { - filterPath: 'nodes.*.version', - })) as { nodes: { [nodeId: string]: { version: string } } }; - - const versionStrings = Object.values(nodes).map(({ version }) => version); - - return uniq(versionStrings) - .sort() - .map(version => new SemVer(version)); -}; - -export const verifyAllMatchKibanaVersion = (allNodeVersions: SemVer[]) => { - // Determine if all nodes in the cluster are running the same major version as Kibana. - const numDifferentVersion = allNodeVersions.filter( - esNodeVersion => esNodeVersion.major !== CURRENT_VERSION.major - ).length; - const numSameVersion = allNodeVersions.filter( - esNodeVersion => esNodeVersion.major === CURRENT_VERSION.major - ).length; - - if (numDifferentVersion) { - const error = new Boom(`There are some nodes running a different version of Elasticsearch`, { - // 426 means "Upgrade Required" and is used when semver compatibility is not met. - statusCode: 426, - }); - - error.output.payload.attributes = { allNodesUpgraded: !numSameVersion }; - throw error; - } -}; - -export const EsVersionPrecheck = { - assign: 'esVersionCheck', - async method(request: Request) { - const { callWithRequest } = request.server.plugins.elasticsearch.getCluster('admin'); - const callCluster = callWithRequest.bind(callWithRequest, request) as CallCluster; - - let allNodeVersions: SemVer[]; - - try { - allNodeVersions = await getAllNodeVersions(callCluster); - } catch (e) { - if (e.status === 403) { - throw Boom.forbidden(e.message); - } - - throw e; - } - - // This will throw if there is an issue - verifyAllMatchKibanaVersion(allNodeVersions); - - return true; - }, -} as RouteOptionsPreObject; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts new file mode 100644 index 00000000000000..cf1b78e1e3920f --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { PluginInitializerContext } from 'src/core/server'; +import { UpgradeAssistantServerPlugin } from './plugin'; + +export const plugin = (ctx: PluginInitializerContext) => { + return new UpgradeAssistantServerPlugin(); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__fixtures__/fake_deprecations.json similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__fixtures__/fake_deprecations.json diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/__mocks__/es_version_precheck.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__mocks__/es_version_precheck.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/__mocks__/es_version_precheck.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__mocks__/es_version_precheck.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/__snapshots__/es_migration_apis.test.ts.snap b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__snapshots__/es_migration_apis.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/__snapshots__/es_migration_apis.test.ts.snap rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__snapshots__/es_migration_apis.test.ts.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.test.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.test.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.ts similarity index 94% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.ts index 2cf0a8f5020fdf..199d3894084427 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.ts @@ -5,8 +5,8 @@ */ import { get } from 'lodash'; -import { Legacy } from 'kibana'; import { CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; +import { RequestShim } from '../types'; interface DeprecationLoggingStatus { isEnabled: boolean; @@ -14,7 +14,7 @@ interface DeprecationLoggingStatus { export async function getDeprecationLoggingStatus( callWithRequest: CallClusterWithRequest, - req: Legacy.Request + req: RequestShim ): Promise { const response = await callWithRequest(req, 'cluster.getSettings', { includeDefaults: true, @@ -27,7 +27,7 @@ export async function getDeprecationLoggingStatus( export async function setDeprecationLogging( callWithRequest: CallClusterWithRequest, - req: Legacy.Request, + req: RequestShim, isEnabled: boolean ): Promise { const response = await callWithRequest(req, 'cluster.putSettings', { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.test.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.test.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.ts similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.ts index 8ed85d19c411a0..b52c4c374266f7 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.ts @@ -4,15 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; - -import { Request } from 'hapi'; import { CallClusterWithRequest, DeprecationAPIResponse, DeprecationInfo, } from 'src/legacy/core_plugins/elasticsearch'; +import { RequestShim } from '../types'; + export interface EnrichedDeprecationInfo extends DeprecationInfo { index?: string; node?: string; @@ -27,7 +26,7 @@ export interface UpgradeAssistantStatus { export async function getUpgradeAssistantStatus( callWithRequest: CallClusterWithRequest, - req: Request, + req: RequestShim, isCloudEnabled: boolean ): Promise { const deprecations = await callWithRequest(req, 'transport.request', { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts new file mode 100644 index 00000000000000..bbabe557df4d4a --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts @@ -0,0 +1,151 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SemVer } from 'semver'; +import { IScopedClusterClient, kibanaResponseFactory } from 'src/core/server'; +import { CURRENT_VERSION } from '../../../common/version'; +import { + esVersionCheck, + getAllNodeVersions, + verifyAllMatchKibanaVersion, +} from './es_version_precheck'; + +describe('getAllNodeVersions', () => { + it('returns a list of unique node versions', async () => { + const adminClient = ({ + callAsInternalUser: jest.fn().mockResolvedValue({ + nodes: { + node1: { version: '7.0.0' }, + node2: { version: '7.0.0' }, + node3: { version: '6.0.0' }, + }, + }), + } as unknown) as IScopedClusterClient; + + await expect(getAllNodeVersions(adminClient)).resolves.toEqual([ + new SemVer('6.0.0'), + new SemVer('7.0.0'), + ]); + }); +}); + +describe('verifyAllMatchKibanaVersion', () => { + it('detects higher version nodes', () => { + const result = verifyAllMatchKibanaVersion([new SemVer('99999.0.0')]); + expect(result.allNodesMatch).toBe(false); + expect(result.allNodesUpgraded).toBe(true); + }); + + it('detects lower version nodes', () => { + const result = verifyAllMatchKibanaVersion([new SemVer('0.0.0')]); + expect(result.allNodesMatch).toBe(false); + expect(result.allNodesUpgraded).toBe(true); + }); + + it('detects if all are on same major correctly', () => { + const versions = [ + CURRENT_VERSION, + CURRENT_VERSION.inc('minor'), + CURRENT_VERSION.inc('minor').inc('minor'), + ]; + + const result = verifyAllMatchKibanaVersion(versions); + expect(result.allNodesMatch).toBe(true); + expect(result.allNodesUpgraded).toBe(false); + }); + + it('detects partial matches', () => { + const versions = [ + new SemVer('0.0.0'), + CURRENT_VERSION.inc('minor'), + CURRENT_VERSION.inc('minor').inc('minor'), + ]; + + const result = verifyAllMatchKibanaVersion(versions); + expect(result.allNodesMatch).toBe(false); + expect(result.allNodesUpgraded).toBe(false); + }); +}); + +describe('EsVersionPrecheck', () => { + it('returns a 403 when callCluster fails with a 403', async () => { + const fakeCall = jest.fn().mockRejectedValue({ status: 403 }); + + const ctx = { + core: { + elasticsearch: { + adminClient: { + callAsInternalUser: fakeCall, + }, + }, + }, + } as any; + + const result = await esVersionCheck(ctx, kibanaResponseFactory); + expect(result).toHaveProperty('status', 403); + }); + + it('returns a 426 message w/ allNodesUpgraded = false when nodes are not on same version', async () => { + const ctx = { + core: { + elasticsearch: { + adminClient: { + callAsInternalUser: jest.fn().mockResolvedValue({ + nodes: { + node1: { version: CURRENT_VERSION.raw }, + node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + }, + }), + }, + }, + }, + } as any; + + const result = await esVersionCheck(ctx, kibanaResponseFactory); + expect(result).toHaveProperty('status', 426); + expect(result).toHaveProperty('payload.attributes.allNodesUpgraded', false); + }); + + it('returns a 426 message w/ allNodesUpgraded = true when nodes are on next version', async () => { + const ctx = { + core: { + elasticsearch: { + adminClient: { + callAsInternalUser: jest.fn().mockResolvedValue({ + nodes: { + node1: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + }, + }), + }, + }, + }, + } as any; + + const result = await esVersionCheck(ctx, kibanaResponseFactory); + expect(result).toHaveProperty('status', 426); + expect(result).toHaveProperty('payload.attributes.allNodesUpgraded', true); + }); + + it('returns undefined when nodes are on same version', async () => { + const ctx = { + core: { + elasticsearch: { + adminClient: { + callAsInternalUser: jest.fn().mockResolvedValue({ + nodes: { + node1: { version: CURRENT_VERSION.raw }, + node2: { version: CURRENT_VERSION.raw }, + }, + }), + }, + }, + }, + } as any; + + await expect(esVersionCheck(ctx, kibanaResponseFactory)).resolves.toBe(undefined); + }); +}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts new file mode 100644 index 00000000000000..2fb3effe437938 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { uniq } from 'lodash'; +import { SemVer } from 'semver'; +import { + IScopedClusterClient, + KibanaRequest, + KibanaResponseFactory, + RequestHandler, + RequestHandlerContext, +} from 'src/core/server'; +import { CURRENT_VERSION } from '../../../common/version'; + +/** + * Returns an array of all the unique Elasticsearch Node Versions in the Elasticsearch cluster. + */ +export const getAllNodeVersions = async (adminClient: IScopedClusterClient) => { + // Get the version information for all nodes in the cluster. + const { nodes } = (await adminClient.callAsInternalUser('nodes.info', { + filterPath: 'nodes.*.version', + })) as { nodes: { [nodeId: string]: { version: string } } }; + + const versionStrings = Object.values(nodes).map(({ version }) => version); + + return uniq(versionStrings) + .sort() + .map(version => new SemVer(version)); +}; + +export const verifyAllMatchKibanaVersion = (allNodeVersions: SemVer[]) => { + // Determine if all nodes in the cluster are running the same major version as Kibana. + const numDifferentVersion = allNodeVersions.filter( + esNodeVersion => esNodeVersion.major !== CURRENT_VERSION.major + ).length; + + const numSameVersion = allNodeVersions.filter( + esNodeVersion => esNodeVersion.major === CURRENT_VERSION.major + ).length; + + if (numDifferentVersion) { + return { + allNodesMatch: false, + // If Kibana is talking to nodes and none have the same major version as Kibana, they must a be of + // a higher major version. + allNodesUpgraded: numSameVersion === 0, + }; + } + return { + allNodesMatch: true, + allNodesUpgraded: false, + }; +}; + +/** + * This is intended as controller/handler level code so it knows about HTTP + */ +export const esVersionCheck = async ( + ctx: RequestHandlerContext, + response: KibanaResponseFactory +) => { + const { adminClient } = ctx.core.elasticsearch; + let allNodeVersions: SemVer[]; + + try { + allNodeVersions = await getAllNodeVersions(adminClient); + } catch (e) { + if (e.status === 403) { + return response.forbidden({ body: e.message }); + } + + throw e; + } + + const result = verifyAllMatchKibanaVersion(allNodeVersions); + if (!result.allNodesMatch) { + return response.customError({ + // 426 means "Upgrade Required" and is used when semver compatibility is not met. + statusCode: 426, + body: { + message: 'There are some nodes running a different version of Elasticsearch', + attributes: { + allNodesUpgraded: result.allNodesUpgraded, + }, + }, + }); + } +}; + +export const versionCheckHandlerWrapper = (handler: RequestHandler) => async ( + ctx: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory +) => { + const errorResponse = await esVersionCheck(ctx, response); + if (errorResponse) { + return errorResponse; + } + return handler(ctx, request, response); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.test.ts similarity index 95% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.test.ts index ce892df0de9469..06fa755472238f 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ReindexSavedObject } from '../../../common/types'; +import { ReindexSavedObject } from '../../../../common/types'; import { Credential, credentialStoreFactory } from './credential_store'; describe('credentialStore', () => { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.ts similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.ts index 32f5ec9977b72e..a051d16b5779f8 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.ts @@ -8,7 +8,7 @@ import { createHash } from 'crypto'; import { Request } from 'hapi'; import stringify from 'json-stable-stringify'; -import { ReindexSavedObject } from '../../../common/types'; +import { ReindexSavedObject } from '../../../../common/types'; export type Credential = Request['headers']; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.test.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.test.ts index 9ec06b72f02e2c..7b346cc87edf6d 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; import { generateNewIndexName, getReindexWarnings, diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.ts similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.ts index f6dc471d0945d3..0b95bc628fbb41 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.ts @@ -5,8 +5,8 @@ */ import { flow, omit } from 'lodash'; -import { ReindexWarning } from '../../../common/types'; -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; +import { ReindexWarning } from '../../../../common/types'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; import { FlatSettings } from './types'; export interface ParsedIndexName { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.test.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.test.ts index 4569fdfa33a83b..3fb855958a5d08 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.test.ts @@ -13,8 +13,8 @@ import { ReindexSavedObject, ReindexStatus, ReindexStep, -} from '../../../common/types'; -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; +} from '../../../../common/types'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; import { LOCK_WINDOW, ReindexActions, reindexActionsFactory } from './reindex_actions'; describe('ReindexActions', () => { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.ts index a162186ff0059c..6683f80c8e7791 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.ts @@ -7,7 +7,7 @@ import moment from 'moment'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { SavedObjectsFindResponse, SavedObjectsClientContract } from 'src/core/server'; +import { SavedObjectsFindResponse, SavedObjectsClientContract } from 'kibana/server'; import { IndexGroup, REINDEX_OP_TYPE, @@ -15,7 +15,7 @@ import { ReindexSavedObject, ReindexStatus, ReindexStep, -} from '../../../common/types'; +} from '../../../../common/types'; import { generateNewIndexName } from './index_settings'; import { FlatSettings } from './types'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.test.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.test.ts index 1216a8d2c4c24e..9cd41c8cbe8264 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.test.ts @@ -10,8 +10,8 @@ import { ReindexSavedObject, ReindexStatus, ReindexStep, -} from '../../../common/types'; -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; +} from '../../../../common/types'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; import { isMlIndex, isWatcherIndex, diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.ts index 41a4552b722de6..0e6095f98b6ff0 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.ts @@ -8,14 +8,14 @@ import Boom from 'boom'; import { Server } from 'hapi'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { XPackInfo } from '../../../../xpack_main/server/lib/xpack_info'; +import { XPackInfo } from '../../../../../xpack_main/server/lib/xpack_info'; import { IndexGroup, ReindexSavedObject, ReindexStatus, ReindexStep, ReindexWarning, -} from '../../../common/types'; +} from '../../../../common/types'; import { generateNewIndexName, getReindexWarnings, diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/types.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/types.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/types.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/types.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/worker.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/worker.ts similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/worker.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/worker.ts index 669eea623851ce..628a47be9f5e77 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/worker.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/worker.ts @@ -5,11 +5,11 @@ */ import { CallCluster, CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; import { Request, Server } from 'src/legacy/server/kbn_server'; -import { SavedObjectsClientContract } from 'src/core/server'; +import { SavedObjectsClientContract } from 'kibana/server'; import moment from 'moment'; -import { XPackInfo } from '../../../../xpack_main/server/lib/xpack_info'; -import { ReindexSavedObject, ReindexStatus } from '../../../common/types'; +import { XPackInfo } from '../../../../../xpack_main/server/lib/xpack_info'; +import { ReindexSavedObject, ReindexStatus } from '../../../../common/types'; import { CredentialStore } from './credential_store'; import { reindexActionsFactory } from './reindex_actions'; import { ReindexService, reindexServiceFactory } from './reindex_service'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.test.ts similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.test.ts index 94df444e2c1bbe..4c378ba25430e4 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; +import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../../common/types'; import { upsertUIOpenOption } from './es_ui_open_apis'; /** diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts similarity index 75% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts index 7036dcc4ea1a71..b52b3b812b7f9b 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts @@ -4,19 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; import { UIOpen, UIOpenOption, UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE, - UpgradeAssistantTelemetryServer, -} from '../../../common/types'; +} from '../../../../common/types'; +import { RequestShim, ServerShim } from '../../types'; -async function incrementUIOpenOptionCounter( - server: UpgradeAssistantTelemetryServer, - uiOpenOptionCounter: UIOpenOption -) { +async function incrementUIOpenOptionCounter(server: ServerShim, uiOpenOptionCounter: UIOpenOption) { const { getSavedObjectsRepository } = server.savedObjects; const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); const internalRepository = getSavedObjectsRepository(callWithInternalUser); @@ -28,10 +24,7 @@ async function incrementUIOpenOptionCounter( ); } -export async function upsertUIOpenOption( - server: UpgradeAssistantTelemetryServer, - req: Legacy.Request -): Promise { +export async function upsertUIOpenOption(server: ServerShim, req: RequestShim): Promise { const { overview, cluster, indices } = req.payload as UIOpen; if (overview) { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.test.ts similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.test.ts index a8a78470aabbe4..26302de74743f1 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; +import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../../common/types'; import { upsertUIReindexOption } from './es_ui_reindex_apis'; /** diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts similarity index 86% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts index 3cb965523a80b5..626d51b298e72a 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts @@ -4,17 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; import { UIReindex, UIReindexOption, UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE, - UpgradeAssistantTelemetryServer, -} from '../../../common/types'; +} from '../../../../common/types'; +import { RequestShim, ServerShim } from '../../types'; async function incrementUIReindexOptionCounter( - server: UpgradeAssistantTelemetryServer, + server: ServerShim, uiOpenOptionCounter: UIReindexOption ) { const { getSavedObjectsRepository } = server.savedObjects; @@ -29,8 +28,8 @@ async function incrementUIReindexOptionCounter( } export async function upsertUIReindexOption( - server: UpgradeAssistantTelemetryServer, - req: Legacy.Request + server: ServerShim, + req: RequestShim ): Promise { const { close, open, start, stop } = req.payload as UIReindex; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/index.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/index.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/index.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/index.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.test.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.test.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.ts similarity index 87% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.ts index 3a9b11a57f070c..47a2cd5d51fd4e 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.ts @@ -13,8 +13,8 @@ import { UpgradeAssistantTelemetry, UpgradeAssistantTelemetrySavedObject, UpgradeAssistantTelemetrySavedObjectAttributes, - UpgradeAssistantTelemetryServer, -} from '../../../common/types'; +} from '../../../../common/types'; +import { ServerShim } from '../../types'; import { isDeprecationLoggingEnabled } from '../es_deprecation_logging_apis'; async function getSavedObjectAttributesFromRepo( @@ -43,7 +43,7 @@ async function getDeprecationLoggingStatusValue(callCluster: any): Promise { const { getSavedObjectsRepository } = server.savedObjects; const savedObjectsRepository = getSavedObjectsRepository(callCluster); @@ -97,13 +97,12 @@ export async function fetchUpgradeAssistantMetrics( }; } -export function makeUpgradeAssistantUsageCollector(server: UpgradeAssistantTelemetryServer) { - const kbnServer = server as UpgradeAssistantTelemetryServer; - const upgradeAssistantUsageCollector = kbnServer.usage.collectorSet.makeUsageCollector({ +export function makeUpgradeAssistantUsageCollector(server: ServerShim) { + const upgradeAssistantUsageCollector = server.usage.collectorSet.makeUsageCollector({ type: UPGRADE_ASSISTANT_TYPE, isReady: () => true, fetch: async (callCluster: any) => fetchUpgradeAssistantMetrics(callCluster, server), }); - kbnServer.usage.collectorSet.register(upgradeAssistantUsageCollector); + server.usage.collectorSet.register(upgradeAssistantUsageCollector); } diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts new file mode 100644 index 00000000000000..7bc33142ca3213 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { Plugin, CoreSetup, CoreStart } from 'src/core/server'; +import { ServerShim, ServerShimWithRouter } from './types'; +import { credentialStoreFactory } from './lib/reindexing/credential_store'; +import { makeUpgradeAssistantUsageCollector } from './lib/telemetry'; +import { registerClusterCheckupRoutes } from './routes/cluster_checkup'; +import { registerDeprecationLoggingRoutes } from './routes/deprecation_logging'; +import { registerReindexIndicesRoutes, registerReindexWorker } from './routes/reindex_indices'; + +import { registerTelemetryRoutes } from './routes/telemetry'; + +export class UpgradeAssistantServerPlugin implements Plugin { + setup({ http }: CoreSetup, { __LEGACY }: { __LEGACY: ServerShim }) { + const router = http.createRouter(); + const shimWithRouter: ServerShimWithRouter = { ...__LEGACY, router }; + registerClusterCheckupRoutes(shimWithRouter); + registerDeprecationLoggingRoutes(shimWithRouter); + + // The ReindexWorker uses a map of request headers that contain the authentication credentials + // for a given reindex. We cannot currently store these in an the .kibana index b/c we do not + // want to expose these credentials to any unauthenticated users. We also want to avoid any need + // to add a user for a special index just for upgrading. This in-memory cache allows us to + // process jobs without the browser staying on the page, but will require that jobs go into + // a paused state if no Kibana nodes have the required credentials. + const credentialStore = credentialStoreFactory(); + + const worker = registerReindexWorker(__LEGACY, credentialStore); + registerReindexIndicesRoutes(shimWithRouter, worker, credentialStore); + + // Bootstrap the needed routes and the collector for the telemetry + registerTelemetryRoutes(shimWithRouter); + makeUpgradeAssistantUsageCollector(__LEGACY); + } + + start(core: CoreStart, plugins: any) {} + + stop(): void {} +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts new file mode 100644 index 00000000000000..d09a66dbb43269 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +export const createRequestMock = (opts?: { + headers?: any; + params?: Record; + payload?: Record; +}) => { + return Object.assign({ headers: {} }, opts || {}); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts new file mode 100644 index 00000000000000..3769bc389123e2 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { RequestHandler } from 'kibana/server'; + +/** + * Creates a very crude mock of the new platform router implementation. This enables use to test + * controller/handler logic without making HTTP requests to an actual server. This does not enable + * us to test whether our paths actual match, only the response codes of controllers given certain + * inputs. This should be replaced by a more wholistic solution (like functional tests) eventually. + * + * This also bypasses any validation installed on the route. + */ +export const createMockRouter = () => { + const paths: Record>> = {}; + + const assign = (method: string) => ( + { path }: { path: string }, + handler: RequestHandler + ) => { + paths[method] = { + ...(paths[method] || {}), + ...{ [path]: handler }, + }; + }; + + return { + getHandler({ method, pathPattern }: { method: string; pathPattern: string }) { + return paths[method][pathPattern]; + }, + get: assign('get'), + post: assign('post'), + put: assign('put'), + patch: assign('patch'), + }; +}; + +export type MockRouter = ReturnType; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.test.ts similarity index 53% rename from x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.test.ts index 04a05dc2b0e9cb..6afb9d2a5e9357 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.test.ts @@ -3,33 +3,20 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { kibanaResponseFactory } from 'src/core/server'; +import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; -import Boom from 'boom'; -import { Server } from 'hapi'; - -jest.mock('../lib/es_version_precheck'); -import { EsVersionPrecheck } from '../lib/es_version_precheck'; -import { registerClusterCheckupRoutes } from './cluster_checkup'; +jest.mock('../lib/es_version_precheck', () => ({ + versionCheckHandlerWrapper: (a: any) => a, +})); // Need to require to get mock on named export to work. // eslint-disable-next-line @typescript-eslint/no-var-requires const MigrationApis = require('../lib/es_migration_apis'); MigrationApis.getUpgradeAssistantStatus = jest.fn(); -function register(plugins = {}) { - const server = new Server(); - server.plugins = { - elasticsearch: { - getCluster: () => ({ callWithRequest: jest.fn() } as any), - } as any, - ...plugins, - } as any; - server.config = () => ({ get: () => '' } as any); - - registerClusterCheckupRoutes(server); - - return server; -} +import { registerClusterCheckupRoutes } from './cluster_checkup'; /** * Since these route callbacks are so thin, these serve simply as integration tests @@ -37,50 +24,65 @@ function register(plugins = {}) { * more thoroughly in the es_migration_apis test. */ describe('cluster checkup API', () => { - const spy = jest.spyOn(MigrationApis, 'getUpgradeAssistantStatus'); - afterEach(() => jest.clearAllMocks()); - describe('with cloud enabled', () => { - it('is provided to getUpgradeAssistantStatus', async () => { - const server = register({ + let mockRouter: MockRouter; + let serverShim: any; + let ctxMock: any; + + beforeEach(() => { + mockRouter = createMockRouter(); + ctxMock = { + core: {}, + }; + serverShim = { + router: mockRouter, + plugins: { cloud: { config: { isCloudEnabled: true, }, }, - }); + elasticsearch: { + getCluster: () => ({ callWithRequest: jest.fn() } as any), + } as any, + }, + }; + registerClusterCheckupRoutes(serverShim); + }); + + describe('with cloud enabled', () => { + it('is provided to getUpgradeAssistantStatus', async () => { + const spy = jest.spyOn(MigrationApis, 'getUpgradeAssistantStatus'); MigrationApis.getUpgradeAssistantStatus.mockResolvedValue({ cluster: [], indices: [], nodes: [], }); - await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); + await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(ctxMock, createRequestMock(), kibanaResponseFactory); expect(spy.mock.calls[0][2]).toBe(true); }); }); describe('GET /api/upgrade_assistant/reindex/{indexName}.json', () => { - const server = register(); - it('returns state', async () => { MigrationApis.getUpgradeAssistantStatus.mockResolvedValue({ cluster: [], indices: [], nodes: [], }); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(ctxMock, createRequestMock(), kibanaResponseFactory); - expect(resp.statusCode).toEqual(200); - expect(resp.payload).toMatchInlineSnapshot( + expect(resp.status).toEqual(200); + expect(JSON.stringify(resp.payload)).toMatchInlineSnapshot( `"{\\"cluster\\":[],\\"indices\\":[],\\"nodes\\":[]}"` ); }); @@ -90,35 +92,23 @@ describe('cluster checkup API', () => { e.status = 403; MigrationApis.getUpgradeAssistantStatus.mockRejectedValue(e); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(ctxMock, createRequestMock(), kibanaResponseFactory); - expect(resp.statusCode).toEqual(403); + expect(resp.status).toEqual(403); }); it('returns an 500 error if it throws', async () => { MigrationApis.getUpgradeAssistantStatus.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); - expect(resp.statusCode).toEqual(500); - }); - - it('returns a 426 if EsVersionCheck throws', async () => { - (EsVersionPrecheck.method as jest.Mock).mockRejectedValue( - new Boom(`blah`, { statusCode: 426 }) - ); - - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(ctxMock, createRequestMock(), kibanaResponseFactory); - expect(resp.statusCode).toEqual(426); + expect(resp.status).toEqual(500); }); }); }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts new file mode 100644 index 00000000000000..3cfa567755b0fc --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import { ServerShimWithRouter } from '../types'; +import { getUpgradeAssistantStatus } from '../lib/es_migration_apis'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; + +import { createRequestShim } from './create_request_shim'; + +export function registerClusterCheckupRoutes(server: ServerShimWithRouter) { + const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); + const isCloudEnabled = _.get(server.plugins, 'cloud.config.isCloudEnabled', false); + + server.router.get( + { + path: '/api/upgrade_assistant/status', + validate: false, + }, + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + return response.ok({ + body: await getUpgradeAssistantStatus(callWithRequest, reqShim, isCloudEnabled), + }); + } catch (e) { + if (e.status === 403) { + return response.forbidden(e.message); + } + + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts new file mode 100644 index 00000000000000..b1a5c8b72d0e0a --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { KibanaRequest } from 'kibana/server'; +import { RequestShim } from '../types'; + +export const createRequestShim = (req: KibanaRequest): RequestShim => { + return { + headers: req.headers as Record, + payload: req.body || (req as any).payload, + params: req.params, + }; +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts new file mode 100644 index 00000000000000..c488f999b538ef --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { kibanaResponseFactory } from 'src/core/server'; +import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; + +jest.mock('../lib/es_version_precheck', () => ({ + versionCheckHandlerWrapper: (a: any) => a, +})); + +import { registerDeprecationLoggingRoutes } from './deprecation_logging'; + +/** + * Since these route callbacks are so thin, these serve simply as integration tests + * to ensure they're wired up to the lib functions correctly. Business logic is tested + * more thoroughly in the es_deprecation_logging_apis test. + */ +describe('deprecation logging API', () => { + let mockRouter: MockRouter; + let serverShim: any; + let callWithRequest: any; + const ctxMock: any = {}; + + beforeEach(() => { + mockRouter = createMockRouter(); + callWithRequest = jest.fn(); + serverShim = { + router: mockRouter, + plugins: { + cloud: { + config: { + isCloudEnabled: true, + }, + }, + elasticsearch: { + getCluster: () => ({ callWithRequest } as any), + } as any, + }, + }; + registerDeprecationLoggingRoutes(serverShim); + }); + + describe('GET /api/upgrade_assistant/deprecation_logging', () => { + it('returns isEnabled', async () => { + callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'WARN' } } }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/deprecation_logging', + })(ctxMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ isEnabled: true }); + }); + + it('returns an error if it throws', async () => { + callWithRequest.mockRejectedValue(new Error(`scary error!`)); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/deprecation_logging', + })(ctxMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.status).toEqual(500); + }); + }); + + describe('PUT /api/upgrade_assistant/deprecation_logging', () => { + it('returns isEnabled', async () => { + callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'ERROR' } } }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/deprecation_logging', + })(ctxMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.payload).toEqual({ isEnabled: false }); + }); + + it('returns an error if it throws', async () => { + callWithRequest.mockRejectedValue(new Error(`scary error!`)); + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/deprecation_logging', + })(ctxMock, { body: { isEnabled: false } }, kibanaResponseFactory); + + expect(resp.status).toEqual(500); + }); + }); +}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts new file mode 100644 index 00000000000000..7e19ef3fb60472 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; + +import { + getDeprecationLoggingStatus, + setDeprecationLogging, +} from '../lib/es_deprecation_logging_apis'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { ServerShimWithRouter } from '../types'; +import { createRequestShim } from './create_request_shim'; + +export function registerDeprecationLoggingRoutes(server: ServerShimWithRouter) { + const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); + + server.router.get( + { + path: '/api/upgrade_assistant/deprecation_logging', + validate: false, + }, + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + const result = await getDeprecationLoggingStatus(callWithRequest, reqShim); + return response.ok({ body: result }); + } catch (e) { + return response.internalError({ body: e }); + } + }) + ); + + server.router.put( + { + path: '/api/upgrade_assistant/deprecation_logging', + validate: { + body: schema.object({ + isEnabled: schema.boolean(), + }), + }, + }, + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + const { isEnabled } = reqShim.payload as { isEnabled: boolean }; + return response.ok({ + body: await setDeprecationLogging(callWithRequest, reqShim, isEnabled), + }); + } catch (e) { + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.test.ts similarity index 58% rename from x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.test.ts index 264c98526622c3..d520324239656b 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.test.ts @@ -4,7 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Server } from 'hapi'; +import { savedObjectsClientMock } from 'src/core/server/mocks'; +import { kibanaResponseFactory } from 'src/core/server'; +import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; const mockReindexService = { hasRequiredPrivileges: jest.fn(), @@ -18,14 +21,22 @@ const mockReindexService = { cancelReindexing: jest.fn(), }; -jest.mock('../lib/es_version_precheck'); +jest.mock('../lib/es_version_precheck', () => ({ + versionCheckHandlerWrapper: (a: any) => a, +})); + jest.mock('../lib/reindexing', () => { return { reindexServiceFactory: () => mockReindexService, }; }); -import { IndexGroup, ReindexSavedObject, ReindexStatus, ReindexWarning } from '../../common/types'; +import { + IndexGroup, + ReindexSavedObject, + ReindexStatus, + ReindexWarning, +} from '../../../common/types'; import { credentialStoreFactory } from '../lib/reindexing/credential_store'; import { registerReindexIndicesRoutes } from './reindex_indices'; @@ -35,28 +46,36 @@ import { registerReindexIndicesRoutes } from './reindex_indices'; * more thoroughly in the es_migration_apis test. */ describe('reindex API', () => { - const server = new Server(); - server.plugins = { - elasticsearch: { - getCluster: () => ({ callWithRequest: jest.fn() } as any), - } as any, - xpack_main: { - info: {}, - }, - } as any; - server.config = () => ({ get: () => '' } as any); - server.decorate('request', 'getSavedObjectsClient', () => jest.fn()); + let serverShim: any; + let mockRouter: MockRouter; + let ctxMock: any; const credentialStore = credentialStoreFactory(); - const worker = { includes: jest.fn(), forceRefresh: jest.fn(), } as any; - registerReindexIndicesRoutes(server, worker, credentialStore); - beforeEach(() => { + ctxMock = { + core: { + savedObjects: savedObjectsClientMock.create(), + }, + }; + mockRouter = createMockRouter(); + serverShim = { + router: mockRouter, + plugins: { + xpack_main: { + info: jest.fn(), + }, + elasticsearch: { + getCluster: () => ({ callWithRequest: jest.fn() } as any), + } as any, + }, + }; + registerReindexIndicesRoutes(serverShim, worker, credentialStore); + mockReindexService.hasRequiredPrivileges.mockResolvedValue(true); mockReindexService.detectReindexWarnings.mockReset(); mockReindexService.getIndexGroup.mockReset(); @@ -73,6 +92,8 @@ describe('reindex API', () => { credentialStore.clear(); }); + afterEach(() => jest.clearAllMocks()); + describe('GET /api/upgrade_assistant/reindex/{indexName}', () => { it('returns the attributes of the reindex operation and reindex warnings', async () => { mockReindexService.findReindexOperation.mockResolvedValueOnce({ @@ -80,18 +101,18 @@ describe('reindex API', () => { }); mockReindexService.detectReindexWarnings.mockResolvedValueOnce([ReindexWarning.allField]); - const resp = await server.inject({ - method: 'GET', - url: `/api/upgrade_assistant/reindex/wowIndex`, - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'wowIndex' } }), kibanaResponseFactory); // It called into the service correctly expect(mockReindexService.findReindexOperation).toHaveBeenCalledWith('wowIndex'); expect(mockReindexService.detectReindexWarnings).toHaveBeenCalledWith('wowIndex'); // It returned the right results - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data.reindexOp).toEqual({ indexName: 'wowIndex', status: ReindexStatus.inProgress }); expect(data.warnings).toEqual([0]); }); @@ -100,13 +121,13 @@ describe('reindex API', () => { mockReindexService.findReindexOperation.mockResolvedValueOnce(null); mockReindexService.detectReindexWarnings.mockResolvedValueOnce(null); - const resp = await server.inject({ - method: 'GET', - url: `/api/upgrade_assistant/reindex/anIndex`, - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'anIndex' } }), kibanaResponseFactory); - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data.reindexOp).toBeNull(); expect(data.warnings).toBeNull(); }); @@ -116,13 +137,13 @@ describe('reindex API', () => { mockReindexService.detectReindexWarnings.mockResolvedValueOnce([]); mockReindexService.getIndexGroup.mockReturnValue(IndexGroup.ml); - const resp = await server.inject({ - method: 'GET', - url: `/api/upgrade_assistant/reindex/.ml-state`, - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'anIndex' } }), kibanaResponseFactory); - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data.indexGroup).toEqual(IndexGroup.ml); }); }); @@ -133,17 +154,17 @@ describe('reindex API', () => { attributes: { indexName: 'theIndex' }, }); - const resp = await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - }); + const resp = await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'theIndex' } }), kibanaResponseFactory); // It called create correctly expect(mockReindexService.createReindexOperation).toHaveBeenCalledWith('theIndex'); // It returned the right results - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data).toEqual({ indexName: 'theIndex' }); }); @@ -152,10 +173,10 @@ describe('reindex API', () => { attributes: { indexName: 'theIndex' }, }); - await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - }); + await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'theIndex' } }), kibanaResponseFactory); expect(worker.forceRefresh).toHaveBeenCalled(); }); @@ -166,13 +187,19 @@ describe('reindex API', () => { } as ReindexSavedObject; mockReindexService.createReindexOperation.mockResolvedValueOnce(reindexOp); - await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - headers: { - 'kbn-auth-x': 'HERE!', - }, - }); + await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })( + ctxMock, + createRequestMock({ + headers: { + 'kbn-auth-x': 'HERE!', + }, + params: { indexName: 'theIndex' }, + }), + kibanaResponseFactory + ); expect(credentialStore.get(reindexOp)!['kbn-auth-x']).toEqual('HERE!'); }); @@ -185,30 +212,41 @@ describe('reindex API', () => { attributes: { indexName: 'theIndex', status: ReindexStatus.inProgress }, }); - const resp = await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - }); - + const resp = await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })( + ctxMock, + createRequestMock({ + params: { indexName: 'theIndex' }, + }), + kibanaResponseFactory + ); // It called resume correctly expect(mockReindexService.resumeReindexOperation).toHaveBeenCalledWith('theIndex'); expect(mockReindexService.createReindexOperation).not.toHaveBeenCalled(); // It returned the right results - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data).toEqual({ indexName: 'theIndex', status: ReindexStatus.inProgress }); }); it('returns a 403 if required privileges fails', async () => { mockReindexService.hasRequiredPrivileges.mockResolvedValueOnce(false); - const resp = await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - }); - - expect(resp.statusCode).toEqual(403); + const resp = await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })( + ctxMock, + createRequestMock({ + params: { indexName: 'theIndex' }, + }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(403); }); }); @@ -216,13 +254,19 @@ describe('reindex API', () => { it('returns a 501', async () => { mockReindexService.cancelReindexing.mockResolvedValueOnce({}); - const resp = await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/cancelMe/cancel', - }); - - expect(resp.statusCode).toEqual(200); - expect(resp.payload).toMatchInlineSnapshot(`"{\\"acknowledged\\":true}"`); + const resp = await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}/cancel', + })( + ctxMock, + createRequestMock({ + params: { indexName: 'cancelMe' }, + }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ acknowledged: true }); expect(mockReindexService.cancelReindexing).toHaveBeenCalledWith('cancelMe'); }); }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts similarity index 56% rename from x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts index 43e4c9899d2334..c22f12316bd027 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts @@ -4,18 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import Boom from 'boom'; -import { Server } from 'hapi'; - +import { schema } from '@kbn/config-schema'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { SavedObjectsClientContract } from 'src/core/server'; -import { ReindexStatus } from '../../common/types'; -import { EsVersionPrecheck } from '../lib/es_version_precheck'; +import { SavedObjectsClientContract } from 'kibana/server'; +import { ReindexStatus } from '../../../common/types'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; import { reindexServiceFactory, ReindexWorker } from '../lib/reindexing'; import { CredentialStore } from '../lib/reindexing/credential_store'; import { reindexActionsFactory } from '../lib/reindexing/reindex_actions'; +import { ServerShim, ServerShimWithRouter } from '../types'; +import { createRequestShim } from './create_request_shim'; -export function registerReindexWorker(server: Server, credentialStore: CredentialStore) { +export function registerReindexWorker(server: ServerShim, credentialStore: CredentialStore) { const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster( 'admin' ); @@ -29,11 +29,8 @@ export function registerReindexWorker(server: Server, credentialStore: Credentia // Cannot pass server.log directly because it's value changes during startup (?). // Use this function to proxy through. - const log: Server['log'] = ( - tags: string | string[], - data?: string | object | (() => any), - timestamp?: number - ) => server.log(tags, data, timestamp); + const log = (tags: string | string[], data?: string | object | (() => any), timestamp?: number) => + server.log(tags, data, timestamp); const worker = new ReindexWorker( savedObjectsClient, @@ -54,7 +51,7 @@ export function registerReindexWorker(server: Server, credentialStore: Credentia } export function registerReindexIndicesRoutes( - server: Server, + server: ServerShimWithRouter, worker: ReindexWorker, credentialStore: CredentialStore ) { @@ -63,16 +60,20 @@ export function registerReindexIndicesRoutes( const BASE_PATH = '/api/upgrade_assistant/reindex'; // Start reindex for an index - server.route({ - path: `${BASE_PATH}/{indexName}`, - method: 'POST', - options: { - pre: [EsVersionPrecheck], + server.router.post( + { + path: `${BASE_PATH}/{indexName}`, + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, }, - async handler(request) { - const client = request.getSavedObjectsClient(); - const { indexName } = request.params; - const callCluster = callWithRequest.bind(null, request) as CallCluster; + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + const { indexName } = reqShim.params; + const { client } = ctx.core.savedObjects; + const callCluster = callWithRequest.bind(null, reqShim) as CallCluster; const reindexActions = reindexActionsFactory(client, callCluster); const reindexService = reindexServiceFactory( callCluster, @@ -83,7 +84,9 @@ export function registerReindexIndicesRoutes( try { if (!(await reindexService.hasRequiredPrivileges(indexName))) { - throw Boom.forbidden(`You do not have adequate privileges to reindex this index.`); + return response.forbidden({ + body: `You do not have adequate privileges to reindex this index.`, + }); } const existingOp = await reindexService.findReindexOperation(indexName); @@ -95,33 +98,33 @@ export function registerReindexIndicesRoutes( : await reindexService.createReindexOperation(indexName); // Add users credentials for the worker to use - credentialStore.set(reindexOp, request.headers); + credentialStore.set(reindexOp, reqShim.headers); // Kick the worker on this node to immediately pickup the new reindex operation. worker.forceRefresh(); - return reindexOp.attributes; + return response.ok({ body: reindexOp.attributes }); } catch (e) { - if (!e.isBoom) { - return Boom.boomify(e, { statusCode: 500 }); - } - - return e; + return response.internalError({ body: e }); } - }, - }); + }) + ); // Get status - server.route({ - path: `${BASE_PATH}/{indexName}`, - method: 'GET', - options: { - pre: [EsVersionPrecheck], + server.router.get( + { + path: `${BASE_PATH}/{indexName}`, + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, }, - async handler(request) { - const client = request.getSavedObjectsClient(); - const { indexName } = request.params; - const callCluster = callWithRequest.bind(null, request) as CallCluster; + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + const { client } = ctx.core.savedObjects; + const { indexName } = reqShim.params; + const callCluster = callWithRequest.bind(null, reqShim) as CallCluster; const reindexActions = reindexActionsFactory(client, callCluster); const reindexService = reindexServiceFactory( callCluster, @@ -139,33 +142,43 @@ export function registerReindexIndicesRoutes( : []; const indexGroup = reindexService.getIndexGroup(indexName); - return { - reindexOp: reindexOp ? reindexOp.attributes : null, - warnings, - indexGroup, - hasRequiredPrivileges, - }; + return response.ok({ + body: { + reindexOp: reindexOp ? reindexOp.attributes : null, + warnings, + indexGroup, + hasRequiredPrivileges, + }, + }); } catch (e) { if (!e.isBoom) { - return Boom.boomify(e, { statusCode: 500 }); + return response.internalError({ body: e }); } - - return e; + return response.customError({ + body: { + message: e.message, + }, + statusCode: e.statusCode, + }); } - }, - }); + }) + ); // Cancel reindex - server.route({ - path: `${BASE_PATH}/{indexName}/cancel`, - method: 'POST', - options: { - pre: [EsVersionPrecheck], + server.router.post( + { + path: `${BASE_PATH}/{indexName}/cancel`, + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, }, - async handler(request) { - const client = request.getSavedObjectsClient(); - const { indexName } = request.params; - const callCluster = callWithRequest.bind(null, request) as CallCluster; + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + const { indexName } = reqShim.params; + const { client } = ctx.core.savedObjects; + const callCluster = callWithRequest.bind(null, reqShim) as CallCluster; const reindexActions = reindexActionsFactory(client, callCluster); const reindexService = reindexServiceFactory( callCluster, @@ -177,14 +190,18 @@ export function registerReindexIndicesRoutes( try { await reindexService.cancelReindexing(indexName); - return { acknowledged: true }; + return response.ok({ body: { acknowledged: true } }); } catch (e) { if (!e.isBoom) { - return Boom.boomify(e, { statusCode: 500 }); + return response.internalError({ body: e }); } - - return e; + return response.customError({ + body: { + message: e.message, + }, + statusCode: e.statusCode, + }); } - }, - }); + }) + ); } diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts new file mode 100644 index 00000000000000..582c75e3701b64 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts @@ -0,0 +1,190 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { kibanaResponseFactory } from 'src/core/server'; +import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; + +jest.mock('../lib/telemetry/es_ui_open_apis', () => ({ + upsertUIOpenOption: jest.fn(), +})); + +jest.mock('../lib/telemetry/es_ui_reindex_apis', () => ({ + upsertUIReindexOption: jest.fn(), +})); + +import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; +import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; +import { registerTelemetryRoutes } from './telemetry'; + +/** + * Since these route callbacks are so thin, these serve simply as integration tests + * to ensure they're wired up to the lib functions correctly. Business logic is tested + * more thoroughly in the lib/telemetry tests. + */ +describe('Upgrade Assistant Telemetry API', () => { + let serverShim: any; + let mockRouter: MockRouter; + let ctxMock: any; + beforeEach(() => { + ctxMock = {}; + mockRouter = createMockRouter(); + serverShim = { + router: mockRouter, + plugins: { + xpack_main: { + info: jest.fn(), + }, + elasticsearch: { + getCluster: () => ({ callWithRequest: jest.fn() } as any), + } as any, + }, + }; + registerTelemetryRoutes(serverShim); + }); + afterEach(() => jest.clearAllMocks()); + + describe('PUT /api/upgrade_assistant/telemetry/ui_open', () => { + it('returns correct payload with single option', async () => { + const returnPayload = { + overview: true, + cluster: false, + indices: false, + }; + + (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_open', + })(ctxMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns correct payload with multiple option', async () => { + const returnPayload = { + overview: true, + cluster: true, + indices: true, + }; + + (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_open', + })( + ctxMock, + createRequestMock({ + payload: { + overview: true, + cluster: true, + indices: true, + }, + }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns an error if it throws', async () => { + (upsertUIOpenOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_open', + })( + ctxMock, + createRequestMock({ + payload: { + overview: false, + }, + }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(500); + }); + }); + + describe('PUT /api/upgrade_assistant/telemetry/ui_reindex', () => { + it('returns correct payload with single option', async () => { + const returnPayload = { + close: false, + open: false, + start: true, + stop: false, + }; + + (upsertUIReindexOption as jest.Mock).mockRejectedValue(returnPayload); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_reindex', + })( + ctxMock, + createRequestMock({ + payload: { + overview: false, + }, + }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns correct payload with multiple option', async () => { + const returnPayload = { + close: true, + open: true, + start: true, + stop: true, + }; + + (upsertUIReindexOption as jest.Mock).mockRejectedValue(returnPayload); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_reindex', + })( + ctxMock, + createRequestMock({ + payload: { + close: true, + open: true, + start: true, + stop: true, + }, + }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns an error if it throws', async () => { + (upsertUIReindexOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_reindex', + })( + ctxMock, + createRequestMock({ + payload: { + start: false, + }, + }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(500); + }); + }); +}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts new file mode 100644 index 00000000000000..f08c49809033db --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; +import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; +import { ServerShimWithRouter } from '../types'; +import { createRequestShim } from './create_request_shim'; + +export function registerTelemetryRoutes(server: ServerShimWithRouter) { + server.router.put( + { + path: '/api/upgrade_assistant/telemetry/ui_open', + validate: { + body: schema.object({ + overview: schema.boolean({ defaultValue: false }), + cluster: schema.boolean({ defaultValue: false }), + indices: schema.boolean({ defaultValue: false }), + }), + }, + }, + async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + return response.ok({ body: await upsertUIOpenOption(server, reqShim) }); + } catch (e) { + return response.internalError({ body: e }); + } + } + ); + + server.router.put( + { + path: '/api/upgrade_assistant/telemetry/ui_reindex', + validate: { + body: schema.object({ + close: schema.boolean({ defaultValue: false }), + open: schema.boolean({ defaultValue: false }), + start: schema.boolean({ defaultValue: false }), + stop: schema.boolean({ defaultValue: false }), + }), + }, + }, + async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + return response.ok({ body: await upsertUIReindexOption(server, reqShim) }); + } catch (e) { + return response.internalError({ body: e }); + } + } + ); +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts new file mode 100644 index 00000000000000..dc4ecbc806320b --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { Legacy } from 'kibana'; +import { IRouter } from 'src/core/server'; +import { ElasticsearchPlugin } from 'src/legacy/core_plugins/elasticsearch'; +import { XPackMainPlugin } from '../../../xpack_main/xpack_main'; + +export interface ServerShim { + usage: { + collectorSet: { + makeUsageCollector: any; + register: any; + }; + }; + plugins: { + elasticsearch: ElasticsearchPlugin; + xpack_main: XPackMainPlugin; + cloud: { + config: { + isCloudEnabled: boolean; + }; + }; + }; + log: any; + events: any; + savedObjects: Legacy.SavedObjectsService; +} + +export interface ServerShimWithRouter extends ServerShim { + router: IRouter; +} + +export interface RequestShim { + headers: Record; + payload: any; + params: any; +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.ts b/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.ts deleted file mode 100644 index 21c7bc4e5e65d7..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import Boom from 'boom'; -import { Legacy } from 'kibana'; -import _ from 'lodash'; - -import { getUpgradeAssistantStatus } from '../lib/es_migration_apis'; -import { EsVersionPrecheck } from '../lib/es_version_precheck'; - -export function registerClusterCheckupRoutes(server: Legacy.Server) { - const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); - const isCloudEnabled = _.get(server.plugins, 'cloud.config.isCloudEnabled', false); - - server.route({ - path: '/api/upgrade_assistant/status', - method: 'GET', - options: { - pre: [EsVersionPrecheck], - }, - async handler(request) { - try { - return await getUpgradeAssistantStatus(callWithRequest, request, isCloudEnabled); - } catch (e) { - if (e.status === 403) { - return Boom.forbidden(e.message); - } - - return Boom.boomify(e, { - statusCode: 500, - }); - } - }, - }); -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts deleted file mode 100644 index e7918835d461db..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Server } from 'hapi'; - -jest.mock('../lib/es_version_precheck'); -import { registerDeprecationLoggingRoutes } from './deprecation_logging'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the es_deprecation_logging_apis test. - */ -describe('deprecation logging API', () => { - const callWithRequest = jest.fn(); - const server = new Server(); - server.plugins = { - elasticsearch: { - getCluster: () => ({ callWithRequest } as any), - } as any, - } as any; - - registerDeprecationLoggingRoutes(server); - - describe('GET /api/upgrade_assistant/deprecation_logging', () => { - it('returns isEnabled', async () => { - callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'WARN' } } }); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/deprecation_logging', - }); - - expect(resp.statusCode).toEqual(200); - expect(JSON.parse(resp.payload)).toEqual({ isEnabled: true }); - }); - - it('returns an error if it throws', async () => { - callWithRequest.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/deprecation_logging', - }); - - expect(resp.statusCode).toEqual(500); - }); - }); - - describe('PUT /api/upgrade_assistant/deprecation_logging', () => { - it('returns isEnabled', async () => { - callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'ERROR' } } }); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/deprecation_logging', - payload: { - isEnabled: false, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual({ isEnabled: false }); - }); - - it('returns an error if it throws', async () => { - callWithRequest.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/deprecation_logging', - payload: { - isEnabled: false, - }, - }); - - expect(resp.statusCode).toEqual(500); - }); - }); -}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.ts b/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.ts deleted file mode 100644 index d16a87916ad7d2..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import Boom from 'boom'; -import Joi from 'joi'; -import { Legacy } from 'kibana'; - -import { - getDeprecationLoggingStatus, - setDeprecationLogging, -} from '../lib/es_deprecation_logging_apis'; -import { EsVersionPrecheck } from '../lib/es_version_precheck'; - -export function registerDeprecationLoggingRoutes(server: Legacy.Server) { - const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); - - server.route({ - path: '/api/upgrade_assistant/deprecation_logging', - method: 'GET', - options: { - pre: [EsVersionPrecheck], - }, - async handler(request) { - try { - return await getDeprecationLoggingStatus(callWithRequest, request); - } catch (e) { - return Boom.boomify(e, { statusCode: 500 }); - } - }, - }); - - server.route({ - path: '/api/upgrade_assistant/deprecation_logging', - method: 'PUT', - options: { - pre: [EsVersionPrecheck], - validate: { - payload: Joi.object({ - isEnabled: Joi.boolean(), - }), - }, - }, - async handler(request) { - try { - const { isEnabled } = request.payload as { isEnabled: boolean }; - return await setDeprecationLogging(callWithRequest, request, isEnabled); - } catch (e) { - return Boom.boomify(e, { statusCode: 500 }); - } - }, - }); -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.test.js b/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.test.js deleted file mode 100644 index a3706231f2297a..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.test.js +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -jest.mock('../lib/telemetry/es_ui_open_apis', () => ({ - upsertUIOpenOption: jest.fn(), -})); - -jest.mock('../lib/telemetry/es_ui_reindex_apis', () => ({ - upsertUIReindexOption: jest.fn(), -})); - -import { Server } from 'hapi'; -import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; -import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; -import { registerTelemetryRoutes } from './telemetry'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the lib/telemetry tests. - */ -describe('Upgrade Assistant Telemetry API', () => { - const server = new Server(); - - registerTelemetryRoutes(server); - - describe('PUT /api/upgrade_assistant/telemetry/ui_open', () => { - it('returns correct payload with single option', async () => { - const returnPayload = { - overview: true, - cluster: false, - indices: false, - }; - - upsertUIOpenOption.mockResolvedValue(returnPayload); - - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_open', - payload: { - overview: true, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual(returnPayload); - }); - - it('returns correct payload with multiple option', async () => { - const returnPayload = { - overview: true, - cluster: true, - indices: true, - }; - - upsertUIOpenOption.mockResolvedValue(returnPayload); - - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_open', - payload: { - overview: true, - cluster: true, - indices: true, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual(returnPayload); - }); - - it('returns an error if it throws', async () => { - upsertUIOpenOption.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_open', - payload: { - overview: false, - }, - }); - - expect(resp.statusCode).toEqual(500); - }); - }); - - describe('PUT /api/upgrade_assistant/telemetry/ui_reindex', () => { - it('returns correct payload with single option', async () => { - const returnPayload = { - close: false, - open: false, - start: true, - stop: false, - }; - - upsertUIReindexOption.mockResolvedValue(returnPayload); - - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_reindex', - payload: { - start: true, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual(returnPayload); - }); - - it('returns correct payload with multiple option', async () => { - const returnPayload = { - close: true, - open: true, - start: true, - stop: true, - }; - - upsertUIReindexOption.mockResolvedValue(returnPayload); - - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_reindex', - payload: { - close: true, - open: true, - start: true, - stop: true, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual(returnPayload); - }); - - it('returns an error if it throws', async () => { - upsertUIReindexOption.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_reindex', - payload: { - start: false, - }, - }); - - expect(resp.statusCode).toEqual(500); - }); - }); -}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.ts b/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.ts deleted file mode 100644 index 6def6d1e72ea33..00000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import Boom from 'boom'; -import Joi from 'joi'; -import { UpgradeAssistantTelemetryServer } from '../../common/types'; -import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; -import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; - -export function registerTelemetryRoutes(server: UpgradeAssistantTelemetryServer) { - server.route({ - path: '/api/upgrade_assistant/telemetry/ui_open', - method: 'PUT', - options: { - validate: { - payload: Joi.object({ - overview: Joi.boolean().default(false), - cluster: Joi.boolean().default(false), - indices: Joi.boolean().default(false), - }), - }, - }, - async handler(request) { - try { - return await upsertUIOpenOption(server, request); - } catch (e) { - return Boom.boomify(e, { statusCode: 500 }); - } - }, - }); - - server.route({ - path: '/api/upgrade_assistant/telemetry/ui_reindex', - method: 'PUT', - options: { - validate: { - payload: Joi.object({ - close: Joi.boolean().default(false), - open: Joi.boolean().default(false), - start: Joi.boolean().default(false), - stop: Joi.boolean().default(false), - }), - }, - }, - async handler(request) { - try { - return await upsertUIReindexOption(server, request); - } catch (e) { - return Boom.boomify(e, { statusCode: 500 }); - } - }, - }); -} From 3a915b22a04dc85e257a1cc8802178dc541d83ca Mon Sep 17 00:00:00 2001 From: Artyom Gospodarsky Date: Wed, 20 Nov 2019 16:30:33 +0300 Subject: [PATCH 06/29] Use NP registry instead of ui/registry/field_formats (#48108) * Create Field Format Provider * Pass Field Format as a start dependency * Register utils in the new field formats * Fix types issue * Make FieldFormats instance as a service * Exclude importing of register.js * Remove uiExports/fieldFormats imports * Migrate some dependencies to new Field Format * Migrate field format to new instance * Fix type errors * Fix Jest tests * Move from getFieldFormat to npSetup * Fix types errors * Fix reviews * Fix types errors * Fix types * fix CI * Bind getConfig to FieldFormatRegisty * Mock FieldFormat in FieldItem * Fix DataPanel tests * Fix DataPanel tests * Fix Jest tests * Create a fieldFormats mock for mocha tests * fix CI * fix CI * Mock fieldFormatsRegistry in all visualizations * Fix 'should create scripted field' functional test * Change FieldFormat.from return type * Fix reviews * Fix mocha test * Fix mocha tests * Encapsulate FieldFormatRegistry * Pretty field_item.tsx * Fix reviews * Fix PR comments * Fix CI * Replace any by a specific type * Fix mocha tests * Remove config from url converter * Expand Field Format ID type for creating custom converters * Fix a jest test * Update migration doc * Add quote and semicolon * Fix types errors which doesn't relate to the aim of PR --- .../plugin/development-uiexports.asciidoc | 1 - src/core/MIGRATION.md | 38 +++ .../stubbed_logstash_index_pattern.js | 3 +- .../public/index_patterns/fields/field.ts | 6 +- .../index_patterns/index_pattern.test.ts | 12 +- .../index_patterns/index_pattern.ts | 22 +- .../index_patterns/index_patterns.test.ts | 6 - .../index_patterns/index_patterns.ts | 4 - .../index_patterns/index_patterns_service.ts | 13 +- .../data/public/index_patterns/services.ts | 5 + src/legacy/core_plugins/data/public/plugin.ts | 1 + src/legacy/core_plugins/kibana/index.js | 1 - .../public/dashboard/dashboard_state.test.ts | 6 - .../__tests__/directives/field_chooser.js | 1 - .../field_formats/__tests__/_conformance.js | 142 ----------- .../core_plugins/kibana/public/kibana.js | 1 - .../core_plugins/timelion/public/app.js | 2 - .../public/__tests__/metric_vis_controller.js | 6 +- .../public/components/lib/tick_formatter.js | 6 +- .../public/components/vis_types/table/vis.js | 9 +- .../mixin/field_formats_mixin.ts | 4 +- .../mixin/field_formats_service.ts | 6 +- .../build_hierarchical_data.test.js | 11 +- src/legacy/ui/public/agg_types/agg_config.ts | 10 +- .../ui/public/agg_types/agg_type.test.ts | 9 +- src/legacy/ui/public/agg_types/agg_type.ts | 8 +- .../ui/public/agg_types/buckets/date_range.ts | 15 +- .../ui/public/agg_types/buckets/ip_range.ts | 15 +- .../ui/public/agg_types/buckets/terms.ts | 7 +- .../public/agg_types/metrics/cardinality.ts | 8 +- .../ui/public/agg_types/metrics/count.ts | 9 +- .../agg_types/metrics/metric_agg_type.ts | 4 +- .../agg_types/metrics/percentile_ranks.ts | 17 +- .../ui/public/field_editor/field_editor.js | 22 +- .../public/field_editor/field_editor.test.js | 34 ++- .../new_platform/new_platform.karma_mock.js | 26 +- .../ui/public/registry/field_formats.js | 186 -------------- .../saved_objects/__tests__/saved_object.js | 5 +- .../ui/public/time_buckets/time_buckets.js | 7 +- .../ui/public/vis/__tests__/_agg_config.js | 16 +- .../loader/pipeline_helpers/utilities.ts | 35 +-- .../field_formats/converters/boolean.test.ts | 2 +- .../field_formats/converters/boolean.ts | 4 +- .../common/field_formats/converters/bytes.ts | 3 +- .../field_formats/converters/color.test.ts | 92 +++---- .../common/field_formats/converters/color.ts | 4 +- .../common/field_formats/converters/custom.ts | 6 +- .../common/field_formats/converters/date.ts | 17 +- .../field_formats/converters/date_nanos.ts | 17 +- .../field_formats/converters/date_server.ts | 12 +- .../field_formats/converters/duration.test.ts | 5 +- .../field_formats/converters/duration.ts | 4 +- .../field_formats/converters/ip.test.ts | 2 +- .../common/field_formats/converters/ip.ts | 4 +- .../common/field_formats/converters/number.ts | 3 +- .../field_formats/converters/numeral.ts | 9 +- .../field_formats/converters/percent.ts | 6 +- .../converters/relative_date.test.ts | 2 +- .../field_formats/converters/relative_date.ts | 8 +- .../common/field_formats/converters/source.ts | 14 +- .../field_formats/converters/static_lookup.ts | 4 +- .../field_formats/converters/string.test.ts | 63 +++-- .../common/field_formats/converters/string.ts | 4 +- .../field_formats/converters/truncate.test.ts | 8 +- .../field_formats/converters/truncate.ts | 4 +- .../common/field_formats/converters/url.ts | 4 +- .../common/field_formats/field_format.test.ts | 2 +- .../data/common/field_formats/field_format.ts | 28 ++- .../data/common/field_formats/index.ts | 2 +- .../data/common/field_formats/types.ts | 20 ++ .../data/common/kbn_field_types/types.ts | 3 +- .../field_formats_provider/field_formats.ts | 226 ++++++++++++++++++ .../field_formats_service.ts | 87 +++++++ .../public/field_formats_provider/index.ts | 21 ++ .../public/field_formats_provider/types.ts} | 8 +- src/plugins/data/public/index.ts | 2 + src/plugins/data/public/mocks.ts | 21 +- src/plugins/data/public/plugin.ts | 8 +- src/plugins/data/public/types.ts | 11 +- .../public/stub_field_formats.ts} | 69 +++--- src/test_utils/public/stub_index_pattern.js | 14 +- .../plugins/kbn_tp_run_pipeline/public/app.js | 1 - x-pack/legacy/plugins/canvas/public/app.js | 1 - .../dashboard_mode/public/dashboard_viewer.js | 1 - x-pack/legacy/plugins/graph/public/index.ts | 1 - .../indexpattern_plugin/datapanel.test.tsx | 1 - .../indexpattern_plugin/field_item.test.tsx | 95 ++++---- .../public/indexpattern_plugin/field_item.tsx | 37 +-- .../metric_expression.test.tsx | 2 +- x-pack/legacy/plugins/maps/public/index.js | 1 - x-pack/legacy/plugins/ml/public/app.js | 2 - .../ml/public/util/chart_utils.test.js | 6 - .../plugins/ml/public/util/time_buckets.js | 6 +- 93 files changed, 962 insertions(+), 754 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js delete mode 100644 src/legacy/ui/public/registry/field_formats.js create mode 100644 src/plugins/data/public/field_formats_provider/field_formats.ts create mode 100644 src/plugins/data/public/field_formats_provider/field_formats_service.ts create mode 100644 src/plugins/data/public/field_formats_provider/index.ts rename src/{legacy/ui/public/registry/field_formats.d.ts => plugins/data/public/field_formats_provider/types.ts} (84%) rename src/{legacy/core_plugins/kibana/public/field_formats/register.js => test_utils/public/stub_field_formats.ts} (60%) diff --git a/docs/developer/plugin/development-uiexports.asciidoc b/docs/developer/plugin/development-uiexports.asciidoc index de713416ae2cd5..6368446f7fb437 100644 --- a/docs/developer/plugin/development-uiexports.asciidoc +++ b/docs/developer/plugin/development-uiexports.asciidoc @@ -8,7 +8,6 @@ An aggregate list of available UiExport types: | Type | Purpose | hacks | Any module that should be included in every application | visTypes | Modules that register providers with the `ui/registry/vis_types` registry. -| fieldFormats | Modules that register providers with the `ui/registry/field_formats` registry. | inspectorViews | Modules that register custom inspector views via the `viewRegistry` in `ui/inspector`. | chromeNavControls | Modules that register providers with the `ui/registry/chrome_nav_controls` registry. | navbarExtensions | Modules that register providers with the `ui/registry/navbar_extensions` registry. diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 0dcc8d55d31a48..a849068b9dde18 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -9,6 +9,7 @@ - [Challenges on the server](#challenges-on-the-server) - [Challenges in the browser](#challenges-in-the-browser) - [Plan of action](#plan-of-action) + - [Shared application plugins](#shared-application-plugins) - [Server-side plan of action](#server-side-plan-of-action) - [De-couple from hapi.js server and request objects](#de-couple-from-hapijs-server-and-request-objects) - [Introduce new plugin definition shim](#introduce-new-plugin-definition-shim) @@ -314,6 +315,43 @@ First, decouple your plugin's business logic from the dependencies that are not Once those things are finished for any given plugin, it can officially be switched to the new plugin system. +### Shared application plugins + +Some services have been already moved to the new platform. + +Below you can find their new locations: + +| Service | Old place | New place in the NP | +| --------------- | ----------------------------------------- | --------------------------------------------------- | +| *FieldFormats* | ui/registry/field_formats | plugins/data/public | + +The `FieldFormats` service has been moved to the `data` plugin in the New Platform. If your plugin has any imports from `ui/registry/field_formats`, you'll need to update your imports as follows: + +Use it in your New Platform plugin: + +```ts +class MyPlugin { + setup (core, { data }) { + data.fieldFormats.register(myFieldFormat); + // ... + } + start (core, { data }) { + data.fieldFormats.getType(myFieldFormatId); + // ... + } +} +``` + +Or, in your legacy platform plugin, consume it through the `ui/new_platform` module: + +```ts +import { npSetup, npStart } from 'ui/new_platform'; + +npSetup.plugins.data.fieldFormats.register(myFieldFormat); +npStart.plugins.data.fieldFormats.getType(myFieldFormatId); +// ... +``` + ## Server-side plan of action Legacy server-side plugins access functionality from core and other plugins at runtime via function arguments, which is similar to how they must be architected to use the new plugin system. This greatly simplifies the plan of action for migrating server-side plugins. diff --git a/src/fixtures/stubbed_logstash_index_pattern.js b/src/fixtures/stubbed_logstash_index_pattern.js index e1fa5db8b7140b..9f6d648477d29d 100644 --- a/src/fixtures/stubbed_logstash_index_pattern.js +++ b/src/fixtures/stubbed_logstash_index_pattern.js @@ -21,6 +21,7 @@ import StubIndexPattern from 'test_utils/stub_index_pattern'; import stubbedLogstashFields from 'fixtures/logstash_fields'; import { getKbnFieldType } from '../plugins/data/common'; +import { mockUiSettings } from '../legacy/ui/public/new_platform/new_platform.karma_mock'; export default function stubbedLogstashIndexPatternService() { const mockLogstashFields = stubbedLogstashFields(); @@ -40,7 +41,7 @@ export default function stubbedLogstashIndexPatternService() { }; }); - const indexPattern = new StubIndexPattern('logstash-*', cfg => cfg, 'time', fields); + const indexPattern = new StubIndexPattern('logstash-*', cfg => cfg, 'time', fields, mockUiSettings); indexPattern.id = 'logstash-*'; indexPattern.isTimeNanosBased = () => false; diff --git a/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts b/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts index 6084b4c106452c..91964655f6f3e7 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts @@ -17,15 +17,13 @@ * under the License. */ -// @ts-ignore -import { fieldFormats } from 'ui/registry/field_formats'; import { i18n } from '@kbn/i18n'; // @ts-ignore import { ObjDefine } from './obj_define'; // @ts-ignore import { shortenDottedString } from '../../../../../core_plugins/kibana/common/utils/shorten_dotted_string'; import { IndexPattern } from '../index_patterns'; -import { getNotifications } from '../services'; +import { getNotifications, getFieldFormats } from '../services'; import { FieldFormat, @@ -104,6 +102,8 @@ export class Field implements FieldType { let format = spec.format; if (!format || !(format instanceof FieldFormat)) { + const fieldFormats = getFieldFormats(); + format = indexPattern.fieldFormatMap[spec.name] || fieldFormats.getDefaultInstance(spec.type, spec.esTypes); diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts index 2d43faf49f63db..ee9f9b493ebf25 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts @@ -27,17 +27,14 @@ import mockLogStashFields from '../../../../../../fixtures/logstash_fields'; import { stubbedSavedObjectIndexPattern } from '../../../../../../fixtures/stubbed_saved_object_index_pattern'; import { Field } from '../index_patterns_service'; -import { setNotifications } from '../services'; +import { setNotifications, setFieldFormats } from '../services'; // Temporary disable eslint, will be removed after moving to new platform folder // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { notificationServiceMock } from '../../../../../../core/public/notifications/notifications_service.mock'; +import { FieldFormatRegisty } from '../../../../../../plugins/data/public'; -jest.mock('ui/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn(), - }, -})); +jest.mock('ui/new_platform'); jest.mock('../../../../../../plugins/kibana_utils/public', () => { const originalModule = jest.requireActual('../../../../../../plugins/kibana_utils/public'); @@ -142,6 +139,9 @@ describe('IndexPattern', () => { // create an indexPattern instance for each test beforeEach(() => { setNotifications(notifications); + setFieldFormats(({ + getDefaultInstance: jest.fn(), + } as unknown) as FieldFormatRegisty); return create(indexPatternId).then((pattern: IndexPattern) => { indexPattern = pattern; diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts index 12aa3c2fb0d51a..f77342c7bc2744 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts @@ -19,8 +19,6 @@ import _, { each, reject } from 'lodash'; import { i18n } from '@kbn/i18n'; -// @ts-ignore -import { fieldFormats } from 'ui/registry/field_formats'; import { SavedObjectsClientContract } from 'src/core/public'; import { DuplicateField, @@ -30,6 +28,12 @@ import { MappingObject, } from '../../../../../../plugins/kibana_utils/public'; +import { + ES_FIELD_TYPES, + KBN_FIELD_TYPES, + IIndexPattern, +} from '../../../../../../plugins/data/public'; + import { findIndexPatternByTitle, getRoutes } from '../utils'; import { IndexPatternMissingIndices } from '../errors'; import { Field, FieldList, FieldListInterface, FieldType } from '../fields'; @@ -37,8 +41,7 @@ import { createFieldsFetcher } from './_fields_fetcher'; import { formatHitProvider } from './format_hit'; import { flattenHitWrapper } from './flatten_hit'; import { IIndexPatternsApiClient } from './index_patterns_api_client'; -import { ES_FIELD_TYPES, IIndexPattern } from '../../../../../../plugins/data/public'; -import { getNotifications } from '../services'; +import { getNotifications, getFieldFormats } from '../services'; const MAX_ATTEMPTS_TO_RESOLVE_CONFLICTS = 3; const type = 'index-pattern'; @@ -114,7 +117,10 @@ export class IndexPattern implements IIndexPattern { this.fields = new FieldList(this, [], this.shortDotsEnable); this.fieldsFetcher = createFieldsFetcher(this, apiClient, this.getConfig('metaFields')); this.flattenHit = flattenHitWrapper(this, this.getConfig('metaFields')); - this.formatHit = formatHitProvider(this, fieldFormats.getDefaultInstance('string')); + this.formatHit = formatHitProvider( + this, + getFieldFormats().getDefaultInstance(KBN_FIELD_TYPES.STRING) + ); this.formatField = this.formatHit.formatField; } @@ -125,12 +131,14 @@ export class IndexPattern implements IIndexPattern { } private deserializeFieldFormatMap(mapping: any) { - const FieldFormat = fieldFormats.getType(mapping.id); + const FieldFormat = getFieldFormats().getType(mapping.id); + return FieldFormat && new FieldFormat(mapping.params, this.getConfig); } private initFields(input?: any) { const newValue = input || this.fields; + this.fields = new FieldList(this, newValue, this.shortDotsEnable); } @@ -451,6 +459,7 @@ export class IndexPattern implements IIndexPattern { const { toasts } = getNotifications(); toasts.addDanger(message); + throw err; } @@ -492,6 +501,7 @@ export class IndexPattern implements IIndexPattern { if (err instanceof IndexPatternMissingIndices) { toasts.addDanger((err as any).message); + return []; } diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts index 8a5c78d13c251c..0a5d1bfcae21f9 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts @@ -29,12 +29,6 @@ jest.mock('../errors', () => ({ IndexPatternMissingIndices: jest.fn(), })); -jest.mock('ui/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn(), - }, -})); - jest.mock('./index_pattern', () => { class IndexPattern { init = async () => { diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts index 2c58af9deaf49d..c8e80b3aede20e 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts @@ -24,8 +24,6 @@ import { UiSettingsClientContract, HttpServiceBase, } from 'src/core/public'; -// @ts-ignore -import { fieldFormats } from 'ui/registry/field_formats'; import { createIndexPatternCache } from './_pattern_cache'; import { IndexPattern } from './index_pattern'; @@ -34,8 +32,6 @@ import { IndexPatternsApiClient, GetFieldsOptions } from './index_patterns_api_c const indexPatternCache = createIndexPatternCache(); export class IndexPatterns { - fieldFormats: fieldFormats; - private config: UiSettingsClientContract; private savedObjectsClient: SavedObjectsClientContract; private savedObjectsCache?: Array>> | null; diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts index 9ce1b5f2e4a208..c9c52400b1f19c 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts @@ -23,9 +23,10 @@ import { HttpServiceBase, NotificationsStart, } from 'src/core/public'; +import { FieldFormatsStart } from '../../../../../plugins/data/public'; import { Field, FieldList, FieldListInterface, FieldType } from './fields'; import { createIndexPatternSelect } from './components'; -import { setNotifications } from './services'; +import { setNotifications, setFieldFormats } from './services'; import { createFlattenHitWrapper, @@ -40,6 +41,7 @@ export interface IndexPatternDependencies { savedObjectsClient: SavedObjectsClientContract; http: HttpServiceBase; notifications: NotificationsStart; + fieldFormats: FieldFormatsStart; } /** @@ -64,8 +66,15 @@ export class IndexPatternsService { return this.setupApi; } - public start({ uiSettings, savedObjectsClient, http, notifications }: IndexPatternDependencies) { + public start({ + uiSettings, + savedObjectsClient, + http, + notifications, + fieldFormats, + }: IndexPatternDependencies) { setNotifications(notifications); + setFieldFormats(fieldFormats); return { ...this.setupApi, diff --git a/src/legacy/core_plugins/data/public/index_patterns/services.ts b/src/legacy/core_plugins/data/public/index_patterns/services.ts index 5cc087548d6fb1..ecd898b28de636 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/services.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/services.ts @@ -19,7 +19,12 @@ import { NotificationsStart } from 'src/core/public'; import { createGetterSetter } from '../../../../../plugins/kibana_utils/public'; +import { FieldFormatsStart } from '../../../../../plugins/data/public'; export const [getNotifications, setNotifications] = createGetterSetter( 'Notifications' ); + +export const [getFieldFormats, setFieldFormats] = createGetterSetter( + 'FieldFormats' +); diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index 2059f61fde59ed..da24576655d2b3 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -94,6 +94,7 @@ export class DataPlugin implements Plugin ({ - fieldFormats: { - getDefaultInstance: jest.fn(), - }, -})); - jest.mock('ui/state_management/state', () => ({ State: {}, })); diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js index a5b55e50eb90e9..bac56f008233c0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js @@ -241,7 +241,6 @@ describe('discover field chooser directives', function () { $scope.computeDetails(field); expect(field.details.buckets).to.not.be(undefined); expect(field.details.buckets[0].value).to.be(40.141592); - expect(field.details.buckets[0].display).to.be('40.142'); }); diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js deleted file mode 100644 index 1c63d2efc7e0bc..00000000000000 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import expect from '@kbn/expect'; -import { fieldFormats } from 'ui/registry/field_formats'; -import { npStart } from 'ui/new_platform'; -import { FieldFormat } from '../../../../../../plugins/data/public'; - -const config = npStart.core.uiSettings; - -const formatIds = [ - 'bytes', - 'date', - 'date_nanos', - 'duration', - 'ip', - 'number', - 'percent', - 'color', - 'string', - 'url', - '_source', - 'truncate', - 'boolean', - 'relative_date', - 'static_lookup' -]; - -// eslint-disable-next-line import/no-default-export -export default describe('conformance', function () { - - const getConfig = (...args) => config.get(...args); - - formatIds.forEach(function (id) { - let instance; - let Type; - - beforeEach(function () { - Type = fieldFormats.getType(id); - instance = fieldFormats.getInstance(id); - }); - - describe(id + ' Type', function () { - it('has an id', function () { - expect(Type.id).to.be.a('string'); - }); - - it('has a title', function () { - expect(Type.title).to.be.a('string'); - }); - - it('declares compatible field formats as a string or array', function () { - expect(Type.fieldType).to.be.ok(); - expect(_.isString(Type.fieldType) || Array.isArray(Type.fieldType)).to.be(true); - }); - }); - - describe(id + ' Instance', function () { - it('extends FieldFormat', function () { - expect(instance).to.be.a(FieldFormat); - }); - }); - }); - - it('registers all of the fieldFormats', function () { - expect(_.difference(fieldFormats.raw, formatIds.map(fieldFormats.getType))).to.eql([]); - }); - - describe('Bytes format', basicPatternTests('bytes', require('numeral'))); - describe('Percent Format', basicPatternTests('percent', require('numeral'))); - describe('Date Format', basicPatternTests('date', require('moment'))); - - describe('Number Format', function () { - basicPatternTests('number', require('numeral'))(); - - it('tries to parse strings', function () { - const number = new (fieldFormats.getType('number'))({ pattern: '0.0b' }, getConfig); - expect(number.convert(123.456)).to.be('123.5B'); - expect(number.convert('123.456')).to.be('123.5B'); - }); - - }); - - function basicPatternTests(id, lib) { - const confKey = id === 'date' ? 'dateFormat' : 'format:' + id + ':defaultPattern'; - - return function () { - it('converts using the format:' + id + ':defaultPattern config', function () { - const inst = fieldFormats.getInstance(id); - [ - '0b', - '0 b', - '0.[000] b', - '0.[000]b', - '0.[0]b' - ].forEach(function (pattern) { - const original = config.get(confKey); - const num = _.random(-10000, 10000, true); - config.set(confKey, pattern); - expect(inst.convert(num)).to.be(lib(num).format(pattern)); - config.set(confKey, original); - }); - }); - - it('uses the pattern param if available', function () { - const original = config.get(confKey); - const num = _.random(-10000, 10000, true); - const defFormat = '0b'; - const customFormat = '0.00000%'; - - config.set(confKey, defFormat); - const defInst = fieldFormats.getInstance(id); - - const Type = fieldFormats.getType(id); - const customInst = new Type({ pattern: customFormat }, getConfig); - - expect(defInst.convert(num)).to.not.be(customInst.convert(num)); - expect(defInst.convert(num)).to.be(lib(num).format(defFormat)); - expect(customInst.convert(num)).to.be(lib(num).format(customFormat)); - - config.set(confKey, original); - }); - }; - } -}); diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index 14fc2ec6ead000..98def2252b75c7 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -31,7 +31,6 @@ import 'uiExports/visTypes'; import 'uiExports/visEditorTypes'; import 'uiExports/visualize'; import 'uiExports/savedObjectTypes'; -import 'uiExports/fieldFormats'; import 'uiExports/fieldFormatEditors'; import 'uiExports/navbarExtensions'; import 'uiExports/contextMenuActions'; diff --git a/src/legacy/core_plugins/timelion/public/app.js b/src/legacy/core_plugins/timelion/public/app.js index 5bc5355d7c0612..04edfc5b611418 100644 --- a/src/legacy/core_plugins/timelion/public/app.js +++ b/src/legacy/core_plugins/timelion/public/app.js @@ -30,8 +30,6 @@ import { timefilter } from 'ui/timefilter'; import { npStart } from 'ui/new_platform'; import { getSavedSheetBreadcrumbs, getCreateBreadcrumbs } from './breadcrumbs'; -// import the uiExports that we want to "use" -import 'uiExports/fieldFormats'; import 'uiExports/savedObjectTypes'; require('ui/autoload/all'); diff --git a/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis_controller.js b/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis_controller.js index 8dd2b093c6f91c..9f58d00d382715 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis_controller.js +++ b/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis_controller.js @@ -51,7 +51,7 @@ describe('metric_vis - controller', function () { expect(metrics.length).to.be(1); expect(metrics[0].label).to.be('Count'); - expect(metrics[0].value).to.be(4301021); + expect(metrics[0].value).to.be('4301021'); }); it('should support multi-value metrics', function () { @@ -66,8 +66,8 @@ describe('metric_vis - controller', function () { expect(metrics.length).to.be(2); expect(metrics[0].label).to.be('1st percentile of bytes'); - expect(metrics[0].value).to.be(182); + expect(metrics[0].value).to.be('182'); expect(metrics[1].label).to.be('99th percentile of bytes'); - expect(metrics[1].value).to.be(445842.4634666484); + expect(metrics[1].value).to.be('445842.4634666484'); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/tick_formatter.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/tick_formatter.js index 0459d11c74ef0d..1192b678ae1488 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/tick_formatter.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/tick_formatter.js @@ -19,10 +19,14 @@ import handlebars from 'handlebars/dist/handlebars'; import { isNumber } from 'lodash'; -import { fieldFormats } from 'ui/registry/field_formats'; +import { npStart } from 'ui/new_platform'; import { inputFormats, outputFormats, isDuration } from '../lib/durations'; + + export const createTickFormatter = (format = '0,0.[00]', template, getConfig = null) => { + const fieldFormats = npStart.plugins.data.fieldFormats; + if (!template) template = '{{value}}'; const render = handlebars.compile(template, { knownHelpersOnly: true }); let formatter; diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js index 8af175d116556e..10fc34fccd2cc6 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js @@ -20,18 +20,17 @@ import _, { isArray, last, get } from 'lodash'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { fieldFormats } from 'ui/registry/field_formats'; +import { npStart } from 'ui/new_platform'; import { createTickFormatter } from '../../lib/tick_formatter'; import { calculateLabel } from '../../../../common/calculate_label'; import { isSortable } from './is_sortable'; import { EuiToolTip, EuiIcon } from '@elastic/eui'; import { replaceVars } from '../../lib/replace_vars'; +import { FIELD_FORMAT_IDS } from '../../../../../../../plugins/data/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { METRIC_TYPES } from '../../../../common/metric_types'; -const DateFormat = fieldFormats.getType('date'); - function getColor(rules, colorKey, value) { let color; if (rules) { @@ -49,6 +48,10 @@ function getColor(rules, colorKey, value) { export class TableVis extends Component { constructor(props) { super(props); + + const fieldFormats = npStart.plugins.data.fieldFormats; + const DateFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); + this.dateFormatter = new DateFormat({}, this.props.getConfig); } diff --git a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts b/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts index 66466b96abe837..370c3127062423 100644 --- a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts +++ b/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts @@ -20,10 +20,10 @@ import { has } from 'lodash'; import { Legacy } from 'kibana'; import { FieldFormatsService } from './field_formats_service'; -import { FieldFormat } from '../../../../plugins/data/public'; +import { IFieldFormatType } from '../../../../plugins/data/public'; export function fieldFormatsMixin(kbnServer: any, server: Legacy.Server) { - const fieldFormatClasses: Array = []; + const fieldFormatClasses: IFieldFormatType[] = []; // for use outside of the request context, for special cases server.decorate('server', 'fieldFormatServiceFactory', async function(uiSettings) { diff --git a/src/legacy/ui/field_formats/mixin/field_formats_service.ts b/src/legacy/ui/field_formats/mixin/field_formats_service.ts index c0800fcd4162bf..c5bc25333985b5 100644 --- a/src/legacy/ui/field_formats/mixin/field_formats_service.ts +++ b/src/legacy/ui/field_formats/mixin/field_formats_service.ts @@ -18,7 +18,7 @@ */ import { indexBy, Dictionary } from 'lodash'; -import { FieldFormat } from '../../../../plugins/data/public'; +import { FieldFormat, IFieldFormatType } from '../../../../plugins/data/common'; interface FieldFormatConfig { id: string; @@ -27,9 +27,9 @@ interface FieldFormatConfig { export class FieldFormatsService { getConfig: any; - _fieldFormats: Dictionary; + _fieldFormats: Dictionary; - constructor(fieldFormatClasses: Array, getConfig: Function) { + constructor(fieldFormatClasses: IFieldFormatType[], getConfig: Function) { this._fieldFormats = indexBy(fieldFormatClasses, 'id'); this.getConfig = getConfig; } diff --git a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js b/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js index ce7d87c228fbd0..49d814c33209c3 100644 --- a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js +++ b/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js @@ -20,16 +20,7 @@ import { buildHierarchicalData } from './build_hierarchical_data'; import { legacyResponseHandlerProvider } from '../../vis/response_handlers/legacy'; -jest.mock('../../registry/field_formats', () => { - return { fieldFormats: { - getType: id => { - if(id === '1') { return jest.fn(); } - if(id === 'agg_1') { return jest.fn(); } - } - } - }; -} -); +jest.mock('ui/new_platform'); jest.mock('../../chrome', () => ({ getUiSettingsClient: jest.fn() diff --git a/src/legacy/ui/public/agg_types/agg_config.ts b/src/legacy/ui/public/agg_types/agg_config.ts index becfaf8c89e273..de1a6059774e77 100644 --- a/src/legacy/ui/public/agg_types/agg_config.ts +++ b/src/legacy/ui/public/agg_types/agg_config.ts @@ -26,16 +26,14 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { AggType } from './agg_type'; import { FieldParamType } from './param_types/field'; import { AggGroupNames } from '../vis/editors/default/agg_groups'; import { writeParams } from './agg_params'; import { AggConfigs } from './agg_configs'; import { Schema } from '../vis/editors/default/schemas'; -import { ContentType } from '../../../../plugins/data/public'; - -// @ts-ignore -import { fieldFormats } from '../registry/field_formats'; +import { ContentType, KBN_FIELD_TYPES } from '../../../../plugins/data/public'; export interface AggConfigOptions { enabled: boolean; @@ -378,14 +376,16 @@ export class AggConfig { if (format) { return format.getConverterFor(contentType); } + return this.fieldOwnFormatter(contentType, defaultFormat); } fieldOwnFormatter(contentType?: ContentType, defaultFormat?: any) { + const fieldFormats = npStart.plugins.data.fieldFormats; const field = this.getField(); let format = field && field.format; if (!format) format = defaultFormat; - if (!format) format = fieldFormats.getDefaultInstance('string'); + if (!format) format = fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); return format.getConverterFor(contentType); } diff --git a/src/legacy/ui/public/agg_types/agg_type.test.ts b/src/legacy/ui/public/agg_types/agg_type.test.ts index 1c1453b74fe983..9b34910e81e88b 100644 --- a/src/legacy/ui/public/agg_types/agg_type.test.ts +++ b/src/legacy/ui/public/agg_types/agg_type.test.ts @@ -19,15 +19,10 @@ import { AggType, AggTypeConfig } from './agg_type'; import { AggConfig } from './agg_config'; +import { npStart } from 'ui/new_platform'; jest.mock('ui/new_platform'); -jest.mock('ui/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn(() => 'default'), - }, -})); - describe('AggType Class', () => { describe('constructor', () => { it("requires a valid config object as it's first param", () => { @@ -158,6 +153,8 @@ describe('AggType Class', () => { }); it('returns default formatter', () => { + npStart.plugins.data.fieldFormats.getDefaultInstance = jest.fn(() => 'default') as any; + const aggType = new AggType({ name: 'name', title: 'title', diff --git a/src/legacy/ui/public/agg_types/agg_type.ts b/src/legacy/ui/public/agg_types/agg_type.ts index 7be8ec1406d3cf..5216affb3e52dc 100644 --- a/src/legacy/ui/public/agg_types/agg_type.ts +++ b/src/legacy/ui/public/agg_types/agg_type.ts @@ -19,6 +19,7 @@ import { constant, noop, identity } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { AggParam, initParams } from './agg_params'; import { AggConfig } from '../vis'; @@ -27,8 +28,7 @@ import { SearchSource } from '../courier'; import { Adapters } from '../inspector'; import { BaseParamType } from './param_types/base'; -// @ts-ignore -import { FieldFormat, fieldFormats } from '../registry/field_formats'; +import { KBN_FIELD_TYPES, FieldFormat } from '../../../../plugins/data/public'; export interface AggTypeConfig< TAggConfig extends AggConfig = AggConfig, @@ -62,7 +62,9 @@ export interface AggTypeConfig< const getFormat = (agg: AggConfig) => { const field = agg.getField(); - return field ? field.format : fieldFormats.getDefaultInstance('string'); + const fieldFormats = npStart.plugins.data.fieldFormats; + + return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); }; export class AggType { diff --git a/src/legacy/ui/public/agg_types/buckets/date_range.ts b/src/legacy/ui/public/agg_types/buckets/date_range.ts index 908d921d123138..860d76ff2aa7bb 100644 --- a/src/legacy/ui/public/agg_types/buckets/date_range.ts +++ b/src/legacy/ui/public/agg_types/buckets/date_range.ts @@ -23,13 +23,15 @@ import { npStart } from 'ui/new_platform'; import { BUCKET_TYPES } from './bucket_agg_types'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; -import { FieldFormat, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; import { DateRangesParamEditor } from '../../vis/editors/default/controls/date_ranges'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; // @ts-ignore import { dateRange } from '../../utils/date_range'; +import { + KBN_FIELD_TYPES, + TEXT_CONTEXT_TYPE, + FieldFormat, +} from '../../../../../plugins/data/public'; const dateRangeTitle = i18n.translate('common.ui.aggTypes.buckets.dateRangeTitle', { defaultMessage: 'Date Range', @@ -48,7 +50,12 @@ export const dateRangeBucketAgg = new BucketAggType({ return { from, to }; }, getFormat(agg) { - const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('date')); + const fieldFormats = npStart.plugins.data.fieldFormats; + + const formatter = agg.fieldOwnFormatter( + TEXT_CONTEXT_TYPE, + fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE) + ); const DateRangeFormat = FieldFormat.from(function(range: DateRangeKey) { return dateRange.toString(range, formatter); }); diff --git a/src/legacy/ui/public/agg_types/buckets/ip_range.ts b/src/legacy/ui/public/agg_types/buckets/ip_range.ts index 7ef415ff8d0c40..35155a482734ce 100644 --- a/src/legacy/ui/public/agg_types/buckets/ip_range.ts +++ b/src/legacy/ui/public/agg_types/buckets/ip_range.ts @@ -19,17 +19,20 @@ import { noop, map, omit, isNull } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { IpRangeTypeParamEditor } from '../../vis/editors/default/controls/ip_range_type'; import { IpRangesParamEditor } from '../../vis/editors/default/controls/ip_ranges'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; -import { FieldFormat, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; import { ipRange } from '../../utils/ip_range'; import { BUCKET_TYPES } from './bucket_agg_types'; // @ts-ignore import { createFilterIpRange } from './create_filter/ip_range'; +import { + KBN_FIELD_TYPES, + TEXT_CONTEXT_TYPE, + FieldFormat, +} from '../../../../../plugins/data/public'; const ipRangeTitle = i18n.translate('common.ui.aggTypes.buckets.ipRangeTitle', { defaultMessage: 'IPv4 Range', @@ -50,7 +53,11 @@ export const ipRangeBucketAgg = new BucketAggType({ return { type: 'range', from: bucket.from, to: bucket.to }; }, getFormat(agg) { - const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('ip')); + const fieldFormats = npStart.plugins.data.fieldFormats; + const formatter = agg.fieldOwnFormatter( + TEXT_CONTEXT_TYPE, + fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.IP) + ); const IpRangeFormat = FieldFormat.from(function(range: IpRangeKey) { return ipRange.toString(range, formatter); }); diff --git a/src/legacy/ui/public/agg_types/buckets/terms.ts b/src/legacy/ui/public/agg_types/buckets/terms.ts index c0f870c27f10d7..89e33784fb5fb8 100644 --- a/src/legacy/ui/public/agg_types/buckets/terms.ts +++ b/src/legacy/ui/public/agg_types/buckets/terms.ts @@ -41,7 +41,7 @@ import { OtherBucketParamEditor } from '../../vis/editors/default/controls/other import { AggConfigs } from '../agg_configs'; import { Adapters } from '../../../../../plugins/inspector/public'; -import { ContentType, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; +import { ContentType, FieldFormat, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; // @ts-ignore import { Schemas } from '../../vis/editors/default/schemas'; @@ -75,7 +75,7 @@ export const termsBucketAgg = new BucketAggType({ const params = agg.params; return agg.getFieldDisplayName() + ': ' + params.order.text; }, - getFormat(bucket) { + getFormat(bucket): FieldFormat { return { getConverterFor: (type: ContentType) => { return (val: any) => { @@ -91,10 +91,11 @@ export const termsBucketAgg = new BucketAggType({ basePath: chrome.getBasePath(), }; const converter = bucket.params.field.format.getConverterFor(type); + return converter(val, undefined, undefined, parsedUrl); }; }, - }; + } as FieldFormat; }, createFilter: createFilterTerms, postFlightRequest: async ( diff --git a/src/legacy/ui/public/agg_types/metrics/cardinality.ts b/src/legacy/ui/public/agg_types/metrics/cardinality.ts index 221e1c6d6b0832..301ae2c80116c0 100644 --- a/src/legacy/ui/public/agg_types/metrics/cardinality.ts +++ b/src/legacy/ui/public/agg_types/metrics/cardinality.ts @@ -18,10 +18,10 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { MetricAggType } from './metric_agg_type'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; import { METRIC_TYPES } from './metric_agg_types'; +import { KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; const uniqueCountTitle = i18n.translate('common.ui.aggTypes.metrics.uniqueCountTitle', { defaultMessage: 'Unique Count', @@ -37,7 +37,9 @@ export const cardinalityMetricAgg = new MetricAggType({ }); }, getFormat() { - return fieldFormats.getDefaultInstance('number'); + const fieldFormats = npStart.plugins.data.fieldFormats; + + return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, params: [ { diff --git a/src/legacy/ui/public/agg_types/metrics/count.ts b/src/legacy/ui/public/agg_types/metrics/count.ts index 12964c8873e97f..b5b844e8658d65 100644 --- a/src/legacy/ui/public/agg_types/metrics/count.ts +++ b/src/legacy/ui/public/agg_types/metrics/count.ts @@ -18,12 +18,11 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; +import { KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; - export const countMetricAgg = new MetricAggType({ name: METRIC_TYPES.COUNT, title: i18n.translate('common.ui.aggTypes.metrics.countTitle', { @@ -36,7 +35,9 @@ export const countMetricAgg = new MetricAggType({ }); }, getFormat() { - return fieldFormats.getDefaultInstance('number'); + const fieldFormats = npStart.plugins.data.fieldFormats; + + return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, getValue(agg, bucket) { return bucket.doc_count; diff --git a/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts b/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts index 7428bd6caa22d1..a466b9f8526078 100644 --- a/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts +++ b/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts @@ -18,6 +18,7 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { AggType, AggTypeConfig } from '../agg_type'; import { AggParamType } from '../param_types/agg'; import { AggConfig } from '../agg_config'; @@ -72,8 +73,9 @@ export class MetricAggType< this.getFormat = config.getFormat || (agg => { + const registeredFormats = npStart.plugins.data.fieldFormats; const field = agg.getField(); - return field ? field.format : fieldFormats.getDefaultInstance('number'); + return field ? field.format : registeredFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }); this.subtype = diff --git a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts index 4fabe137f1bc81..ead5122278b5a2 100644 --- a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts +++ b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts @@ -18,24 +18,27 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { PercentileRanksEditor } from '../../vis/editors/default/controls/percentile_ranks'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { getPercentileValue } from './percentiles_get_value'; import { METRIC_TYPES } from './metric_agg_types'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; -import { KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; +import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; // required by the values editor export type IPercentileRanksAggConfig = IResponseAggConfig; +const getFieldFormats = () => npStart.plugins.data.fieldFormats; + const valueProps = { makeLabel(this: IPercentileRanksAggConfig) { + const fieldFormats = getFieldFormats(); const field = this.getField(); - const format = (field && field.format) || fieldFormats.getDefaultInstance('number'); + const format = + (field && field.format) || fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); const customLabel = this.getParam('customLabel'); const label = customLabel || this.getFieldDisplayName(); @@ -81,7 +84,11 @@ export const percentileRanksMetricAgg = new MetricAggType new ValueAggConfig(value)); }, getFormat() { - return fieldFormats.getInstance('percent') || fieldFormats.getDefaultInstance('number'); + const fieldFormats = getFieldFormats(); + return ( + fieldFormats.getInstance(FIELD_FORMAT_IDS.PERCENT) || + fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER) + ); }, getValue(agg, bucket) { return getPercentileValue(agg, bucket) / 100; diff --git a/src/legacy/ui/public/field_editor/field_editor.js b/src/legacy/ui/public/field_editor/field_editor.js index 896fb8fc5ddd81..f3c5990caae64a 100644 --- a/src/legacy/ui/public/field_editor/field_editor.js +++ b/src/legacy/ui/public/field_editor/field_editor.js @@ -27,10 +27,6 @@ import { getSupportedScriptingLanguages, } from 'ui/scripting_languages'; -import { - fieldFormats -} from 'ui/registry/field_formats'; - import { getDocLink } from 'ui/documentation_links'; @@ -39,6 +35,8 @@ import { toastNotifications } from 'ui/notify'; +import { npStart } from 'ui/new_platform'; + import { EuiBasicTable, EuiButton, @@ -84,7 +82,10 @@ import { FormattedMessage } from '@kbn/i18n/react'; // This loads Ace editor's "groovy" mode, used below to highlight the script. import 'brace/mode/groovy'; +const getFieldFormats = () => npStart.plugins.data.fieldFormats; + export class FieldEditor extends PureComponent { + static propTypes = { indexPattern: PropTypes.object.isRequired, field: PropTypes.object.isRequired, @@ -141,9 +142,10 @@ export class FieldEditor extends PureComponent { const fieldTypes = get(FIELD_TYPES_BY_LANG, field.lang, DEFAULT_FIELD_TYPES); field.type = fieldTypes.includes(field.type) ? field.type : fieldTypes[0]; - const DefaultFieldFormat = fieldFormats.getDefaultType(field.type, field.esTypes); + const fieldFormats = getFieldFormats(); + const fieldTypeFormats = [ - getDefaultFormat(DefaultFieldFormat), + getDefaultFormat(fieldFormats.getDefaultType(field.type, field.esTypes)), ...fieldFormats.getByFieldType(field.type), ]; @@ -169,12 +171,14 @@ export class FieldEditor extends PureComponent { onTypeChange = (type) => { const { getConfig } = this.props.helpers; const { field } = this.state; + const fieldFormats = getFieldFormats(); const DefaultFieldFormat = fieldFormats.getDefaultType(type); + field.type = type; const fieldTypeFormats = [ getDefaultFormat(DefaultFieldFormat), - ...fieldFormats.getByFieldType(field.type), + ...getFieldFormats().getByFieldType(field.type), ]; const FieldFormat = fieldTypeFormats[0]; @@ -202,6 +206,7 @@ export class FieldEditor extends PureComponent { const { getConfig } = this.props.helpers; const { field, fieldTypeFormats } = this.state; const FieldFormat = fieldTypeFormats.find((format) => format.id === formatId) || fieldTypeFormats[0]; + field.format = new FieldFormat(params, getConfig); this.setState({ @@ -684,6 +689,7 @@ export class FieldEditor extends PureComponent { } saveField = async () => { + const fieldFormat = this.state.field.format; const field = this.state.field.toActualField(); const { indexPattern } = this.props; const { fieldFormatId } = this.state; @@ -721,7 +727,7 @@ export class FieldEditor extends PureComponent { if (!fieldFormatId) { indexPattern.fieldFormatMap[field.name] = undefined; } else { - indexPattern.fieldFormatMap[field.name] = field.format; + indexPattern.fieldFormatMap[field.name] = fieldFormat; } return indexPattern.save() diff --git a/src/legacy/ui/public/field_editor/field_editor.test.js b/src/legacy/ui/public/field_editor/field_editor.test.js index 34503238f437d7..72eebee960b527 100644 --- a/src/legacy/ui/public/field_editor/field_editor.test.js +++ b/src/legacy/ui/public/field_editor/field_editor.test.js @@ -20,9 +20,12 @@ jest.mock('ui/kfetch', () => ({})); import React from 'react'; + +import { npStart } from 'ui/new_platform'; import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; jest.mock('brace/mode/groovy', () => ({})); +jest.mock('ui/new_platform'); import { FieldEditor } from './field_editor'; @@ -46,6 +49,10 @@ jest.mock('@elastic/eui', () => ({ EuiSpacer: 'eui-spacer', EuiText: 'eui-text', EuiTextArea: 'eui-textArea', + htmlIdGenerator: () => 42, + palettes: { + euiPaletteColorBlind: { colors: ['red'] } + } })); jest.mock('ui/scripting_languages', () => ({ @@ -54,26 +61,6 @@ jest.mock('ui/scripting_languages', () => ({ getDeprecatedScriptingLanguages: () => ['testlang'], })); -jest.mock('ui/registry/field_formats', () => { - class Format { - static id = 'test_format'; static title = 'Test format'; - params() {} - } - - return { - fieldFormats: { - getDefaultType: () => { - return Format; - }, - getByFieldType: (fieldType) => { - if(fieldType === 'number') { - return [Format]; - } - } - }, - }; -}); - jest.mock('ui/documentation_links', () => ({ getDocLink: (doc) => `(docLink for ${doc})`, })); @@ -133,6 +120,13 @@ describe('FieldEditor', () => { indexPattern = { fields, }; + + npStart.plugins.data.fieldFormats.getDefaultType = jest.fn(() => Format); + npStart.plugins.data.fieldFormats.getByFieldType = jest.fn((fieldType) => { + if(fieldType === 'number') { + return [Format]; + } + }); }); it('should render create new scripted field correctly', async () => { diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 5c269c7b019aa2..8703e8750fda48 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -18,6 +18,7 @@ */ import sinon from 'sinon'; +import { getFieldFormatsRegistry } from '../../../../test_utils/public/stub_field_formats'; const mockObservable = () => { return { @@ -25,9 +26,24 @@ const mockObservable = () => { }; }; +export const mockUiSettings = { + get: (item) => { + return mockUiSettings[item]; + }, + getUpdate$: () => ({ + subscribe: sinon.fake(), + }), + 'query:allowLeadingWildcards': true, + 'query:queryString:options': {}, + 'courier:ignoreFilterIfFieldNotInIndex': true, + 'dateFormat:tz': 'Browser', + 'format:defaultTypeMap': {}, +}; + export const npSetup = { core: { - chrome: {} + chrome: {}, + uiSettings: mockUiSettings, }, plugins: { embeddable: { @@ -61,6 +77,7 @@ export const npSetup = { history: sinon.fake(), } }, + fieldFormats: getFieldFormatsRegistry(mockUiSettings), }, share: { register: () => {}, @@ -81,6 +98,9 @@ export const npSetup = { registerAction: sinon.fake(), registerTrigger: sinon.fake(), }, + feature_catalogue: { + register: sinon.fake(), + }, }, }; @@ -164,6 +184,7 @@ export const npStart = { history: sinon.fake(), }, }, + fieldFormats: getFieldFormatsRegistry(mockUiSettings), }, share: { toggleShareContextMenu: () => {}, @@ -185,6 +206,9 @@ export const npStart = { getTriggerActions: sinon.fake(), getTriggerCompatibleActions: sinon.fake(), }, + feature_catalogue: { + register: sinon.fake(), + }, }, }; diff --git a/src/legacy/ui/public/registry/field_formats.js b/src/legacy/ui/public/registry/field_formats.js deleted file mode 100644 index 9e03ef2e3cdd9a..00000000000000 --- a/src/legacy/ui/public/registry/field_formats.js +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { memoize, forOwn, isFunction } from 'lodash'; -import { npStart } from 'ui/new_platform'; - -class FieldFormatRegistry { - constructor() { - this.fieldFormats = new Map(); - this._uiSettings = npStart.core.uiSettings; - this.getConfig = (...args) => this._uiSettings.get(...args); - this._defaultMap = []; - this.init(); - } - - init() { - this.parseDefaultTypeMap(this._uiSettings.get('format:defaultTypeMap')); - - this._uiSettings.getUpdate$().subscribe(({ key, newValue }) => { - if (key === 'format:defaultTypeMap') { - this.parseDefaultTypeMap(newValue); - } - }); - } - - /** - * Get the id of the default type for this field type - * using the format:defaultTypeMap config map - * - * @param {String} fieldType - the field type - * @param {String[]} esTypes - Array of ES data types - * @return {Object} - */ - getDefaultConfig = (fieldType, esTypes) => { - const type = this.getDefaultTypeName(fieldType, esTypes); - return this._defaultMap[type] || this._defaultMap._default_; - }; - - /** - * Get a FieldFormat type (class) by it's id. - * - * @param {String} formatId - the format id - * @return {Function} - */ - getType = (formatId) => { - return this.fieldFormats.get(formatId); - }; - /** - * Get the default FieldFormat type (class) for - * a field type, using the format:defaultTypeMap. - * used by the field editor - * - * @param {String} fieldType - * @param {String} esTypes - Array of ES data types - * @return {Function} - */ - getDefaultType = (fieldType, esTypes) => { - const config = this.getDefaultConfig(fieldType, esTypes); - return this.getType(config.id); - }; - - /** - * Get the name of the default type for ES types like date_nanos - * using the format:defaultTypeMap config map - * - * @param {String[]} esTypes - Array of ES data types - * @return {String|undefined} - */ - getTypeNameByEsTypes = (esTypes) => { - if(!Array.isArray(esTypes)) { - return; - } - return esTypes.find(type => this._defaultMap[type] && this._defaultMap[type].es); - }; - /** - * Get the default FieldFormat type name for - * a field type, using the format:defaultTypeMap. - * - * @param {String} fieldType - * @param {String[]} esTypes - * @return {string} - */ - getDefaultTypeName = (fieldType, esTypes) => { - return this.getTypeNameByEsTypes(esTypes) || fieldType; - }; - - /** - * Get the singleton instance of the FieldFormat type by it's id. - * - * @param {String} formatId - * @return {FieldFormat} - */ - getInstance = memoize(function (formatId) { - const FieldFormat = this.getType(formatId); - if (!FieldFormat) { - throw new Error(`Field Format '${formatId}' not found!`); - } - return new FieldFormat(null, this.getConfig); - }); - - /** - * Get the default fieldFormat instance for a field format. - * - * @param {String} fieldType - * @param {String[]} esTypes - * @return {FieldFormat} - */ - getDefaultInstancePlain(fieldType, esTypes) { - const conf = this.getDefaultConfig(fieldType, esTypes); - - const FieldFormat = this.getType(conf.id); - return new FieldFormat(conf.params, this.getConfig); - } - /** - * Returns a cache key built by the given variables for caching in memoized - * Where esType contains fieldType, fieldType is returned - * -> kibana types have a higher priority in that case - * -> would lead to failing tests that match e.g. date format with/without esTypes - * https://lodash.com/docs#memoize - * - * @param {String} fieldType - * @param {String[]} esTypes - * @return {string} - */ - getDefaultInstanceCacheResolver(fieldType, esTypes) { - return Array.isArray(esTypes) && esTypes.indexOf(fieldType) === -1 - ? [fieldType, ...esTypes].join('-') - : fieldType; - } - - /** - * Get filtered list of field formats by format type - * - * @param {String} fieldType - * @return {FieldFormat[]} - */ - - getByFieldType(fieldType) { - return [ ...this.fieldFormats.values()] - .filter(format => format.fieldType.indexOf(fieldType) !== -1); - } - - /** - * Get the default fieldFormat instance for a field format. - * It's a memoized function that builds and reads a cache - * - * @param {String} fieldType - * @param {String[]} esTypes - * @return {FieldFormat} - */ - getDefaultInstance = memoize(this.getDefaultInstancePlain, this.getDefaultInstanceCacheResolver); - - parseDefaultTypeMap(value) { - this._defaultMap = value; - forOwn(this, function (fn) { - if (isFunction(fn) && fn.cache) { - // clear all memoize caches - fn.cache = new memoize.Cache(); - } - }); - } - - register = derivedFieldFormat => { - this.fieldFormats.set(derivedFieldFormat.id, derivedFieldFormat); - - return this; - }; -} - -export const fieldFormats = new FieldFormatRegistry(); diff --git a/src/legacy/ui/public/saved_objects/__tests__/saved_object.js b/src/legacy/ui/public/saved_objects/__tests__/saved_object.js index ff53d48de758a4..56124a047ba6d0 100644 --- a/src/legacy/ui/public/saved_objects/__tests__/saved_object.js +++ b/src/legacy/ui/public/saved_objects/__tests__/saved_object.js @@ -26,6 +26,7 @@ import { SavedObjectProvider } from '../saved_object'; import StubIndexPattern from 'test_utils/stub_index_pattern'; import { SavedObjectsClientProvider } from '../saved_objects_client_provider'; import { InvalidJSONProperty } from '../../../../../plugins/kibana_utils/public'; +import { mockUiSettings } from '../../new_platform/new_platform.karma_mock'; const getConfig = cfg => cfg; @@ -337,7 +338,7 @@ describe('Saved Object', function () { type: 'dashboard', }); }); - const indexPattern = new StubIndexPattern('my-index', getConfig, null, []); + const indexPattern = new StubIndexPattern('my-index', getConfig, null, [], mockUiSettings); indexPattern.title = indexPattern.id; savedObject.searchSource.setField('index', indexPattern); return savedObject @@ -725,7 +726,7 @@ describe('Saved Object', function () { const savedObject = new SavedObject(config); sinon.stub(savedObject, 'hydrateIndexPattern').callsFake(() => { - const indexPattern = new StubIndexPattern(indexPatternId, getConfig, null, []); + const indexPattern = new StubIndexPattern(indexPatternId, getConfig, null, [], mockUiSettings); indexPattern.title = indexPattern.id; savedObject.searchSource.setField('index', indexPattern); return Promise.resolve(indexPattern); diff --git a/src/legacy/ui/public/time_buckets/time_buckets.js b/src/legacy/ui/public/time_buckets/time_buckets.js index bcd5cd161edd3a..c875d7820373ea 100644 --- a/src/legacy/ui/public/time_buckets/time_buckets.js +++ b/src/legacy/ui/public/time_buckets/time_buckets.js @@ -20,13 +20,14 @@ import _ from 'lodash'; import moment from 'moment'; import chrome from '../chrome'; +import { npStart } from 'ui/new_platform'; import { parseInterval } from '../utils/parse_interval'; import { calcAutoIntervalLessThan, calcAutoIntervalNear } from './calc_auto_interval'; import { convertDurationToNormalizedEsInterval, convertIntervalToEsInterval, } from './calc_es_interval'; -import { fieldFormats } from '../registry/field_formats'; +import { FIELD_FORMAT_IDS } from '../../../../plugins/data/public'; const config = chrome.getUiSettingsClient(); @@ -311,7 +312,9 @@ TimeBuckets.prototype.getScaledDateFormat = function () { }; TimeBuckets.prototype.getScaledDateFormatter = function () { - const DateFieldFormat = fieldFormats.getType('date'); + const fieldFormats = npStart.plugins.data.fieldFormats; + const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); + return new DateFieldFormat({ pattern: this.getScaledDateFormat() }, getConfig); diff --git a/src/legacy/ui/public/vis/__tests__/_agg_config.js b/src/legacy/ui/public/vis/__tests__/_agg_config.js index 2e2e0c31bdb8af..9b0398cf8853e1 100644 --- a/src/legacy/ui/public/vis/__tests__/_agg_config.js +++ b/src/legacy/ui/public/vis/__tests__/_agg_config.js @@ -24,7 +24,6 @@ import { Vis } from '..'; import { AggType } from '../../agg_types/agg_type'; import { AggConfig } from '../../agg_types/agg_config'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { fieldFormats } from '../../registry/field_formats'; describe('AggConfig', function () { @@ -439,12 +438,15 @@ describe('AggConfig', function () { } ] }); - expect(vis.aggs.aggs[0].fieldFormatter()).to.be(fieldFormats.getDefaultInstance('number').getConverterFor()); + + const fieldFormatter = vis.aggs.aggs[0].fieldFormatter(); + + expect(fieldFormatter).to.be.defined; + expect(fieldFormatter('text')).to.be('text'); }); }); describe('#fieldFormatter - no custom getFormat handler', function () { - const visStateAggWithoutCustomGetFormat = { aggs: [ { @@ -467,13 +469,17 @@ describe('AggConfig', function () { it('returns the string format if the field does not have a format', function () { const agg = vis.aggs.aggs[0]; agg.params.field = { type: 'number', format: null }; - expect(agg.fieldFormatter()).to.be(fieldFormats.getDefaultInstance('string').getConverterFor()); + const fieldFormatter = agg.fieldFormatter(); + expect(fieldFormatter).to.be.defined; + expect(fieldFormatter('text')).to.be('text'); }); it('returns the string format if their is no field', function () { const agg = vis.aggs.aggs[0]; delete agg.params.field; - expect(agg.fieldFormatter()).to.be(fieldFormats.getDefaultInstance('string').getConverterFor()); + const fieldFormatter = agg.fieldFormatter(); + expect(fieldFormatter).to.be.defined; + expect(fieldFormatter('text')).to.be('text'); }); it('returns the html converter if "html" is passed in', function () { diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts index 6598da76f60ba1..f49e0f08e87324 100644 --- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts +++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts @@ -20,14 +20,13 @@ import { i18n } from '@kbn/i18n'; import { identity } from 'lodash'; import { AggConfig, Vis } from 'ui/vis'; +import { npStart } from 'ui/new_platform'; import { SerializedFieldFormat } from 'src/plugins/expressions/public'; -import { FieldFormat } from '../../../../../../plugins/data/public'; +import { IFieldFormatId, FieldFormat } from '../../../../../../plugins/data/public'; import { tabifyGetColumns } from '../../../agg_response/tabify/_get_columns'; import chrome from '../../../chrome'; -// @ts-ignore -import { fieldFormats } from '../../../registry/field_formats'; import { dateRange } from '../../../utils/date_range'; import { ipRange } from '../../../utils/ip_range'; import { DateRangeKey } from '../../../agg_types/buckets/date_range'; @@ -45,18 +44,22 @@ function isTermsFieldFormat( return serializedFieldFormat.id === 'terms'; } -const config = chrome.getUiSettingsClient(); +const getConfig = (key: string, defaultOverride?: any): any => + npStart.core.uiSettings.get(key, defaultOverride); +const DefaultFieldFormat = FieldFormat.from(identity); -const getConfig = (...args: any[]): any => config.get(...args); -const getDefaultFieldFormat = () => ({ convert: identity }); +const getFieldFormat = (id?: IFieldFormatId, params: object = {}): FieldFormat => { + const fieldFormats = npStart.plugins.data.fieldFormats; -const getFieldFormat = (id: string | undefined, params: object = {}) => { - const Format = fieldFormats.getType(id); - if (Format) { - return new Format(params, getConfig); - } else { - return getDefaultFieldFormat(); + if (id) { + const Format = fieldFormats.getType(id); + + if (Format) { + return new Format(params, getConfig); + } } + + return new DefaultFieldFormat(); }; export const createFormat = (agg: AggConfig): SerializedFieldFormat => { @@ -93,9 +96,9 @@ export const createFormat = (agg: AggConfig): SerializedFieldFormat => { export type FormatFactory = (mapping?: SerializedFieldFormat) => FieldFormat; -export const getFormat: FormatFactory = (mapping = {}) => { +export const getFormat: FormatFactory = mapping => { if (!mapping) { - return getDefaultFieldFormat(); + return new DefaultFieldFormat(); } const { id } = mapping; if (id === 'range') { @@ -145,6 +148,7 @@ export const getFormat: FormatFactory = (mapping = {}) => { pathname: window.location.pathname, basePath: chrome.getBasePath(), }; + // @ts-ignore return format.convert(val, undefined, undefined, parsedUrl); }; }, @@ -161,9 +165,10 @@ export const getFormat: FormatFactory = (mapping = {}) => { pathname: window.location.pathname, basePath: chrome.getBasePath(), }; + // @ts-ignore return format.convert(val, type, undefined, parsedUrl); }, - }; + } as FieldFormat; } else { return getFieldFormat(id, mapping.params); } diff --git a/src/plugins/data/common/field_formats/converters/boolean.test.ts b/src/plugins/data/common/field_formats/converters/boolean.test.ts index 2a548a6c1b1797..3650df65176115 100644 --- a/src/plugins/data/common/field_formats/converters/boolean.test.ts +++ b/src/plugins/data/common/field_formats/converters/boolean.test.ts @@ -23,7 +23,7 @@ describe('Boolean Format', () => { let boolean: Record; beforeEach(() => { - boolean = new BoolFormat(); + boolean = new BoolFormat({}, jest.fn()); }); [ diff --git a/src/plugins/data/common/field_formats/converters/boolean.ts b/src/plugins/data/common/field_formats/converters/boolean.ts index 96e353592d6760..6cc6c71465d50b 100644 --- a/src/plugins/data/common/field_formats/converters/boolean.ts +++ b/src/plugins/data/common/field_formats/converters/boolean.ts @@ -19,11 +19,11 @@ import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; import { asPrettyString } from '../utils'; export class BoolFormat extends FieldFormat { - static id = 'boolean'; + static id = FIELD_FORMAT_IDS.BOOLEAN; static title = 'Boolean'; static fieldType = [KBN_FIELD_TYPES.BOOLEAN, KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.STRING]; diff --git a/src/plugins/data/common/field_formats/converters/bytes.ts b/src/plugins/data/common/field_formats/converters/bytes.ts index 146f7afe74ccb4..6c6df5eb7367d8 100644 --- a/src/plugins/data/common/field_formats/converters/bytes.ts +++ b/src/plugins/data/common/field_formats/converters/bytes.ts @@ -18,9 +18,10 @@ */ import { NumeralFormat } from './numeral'; +import { FIELD_FORMAT_IDS } from '../types'; export class BytesFormat extends NumeralFormat { - static id = 'bytes'; + static id = FIELD_FORMAT_IDS.BYTES; static title = 'Bytes'; id = BytesFormat.id; diff --git a/src/plugins/data/common/field_formats/converters/color.test.ts b/src/plugins/data/common/field_formats/converters/color.test.ts index b7fcbf61227ebe..f7aa26d449c7bb 100644 --- a/src/plugins/data/common/field_formats/converters/color.test.ts +++ b/src/plugins/data/common/field_formats/converters/color.test.ts @@ -23,16 +23,19 @@ import { HTML_CONTEXT_TYPE } from '../content_types'; describe('Color Format', () => { describe('field is a number', () => { test('should add colors if the value is in range', () => { - const colorer = new ColorFormat({ - fieldType: 'number', - colors: [ - { - range: '100:150', - text: 'blue', - background: 'yellow', - }, - ], - }); + const colorer = new ColorFormat( + { + fieldType: 'number', + colors: [ + { + range: '100:150', + text: 'blue', + background: 'yellow', + }, + ], + }, + jest.fn() + ); expect(colorer.convert(99, HTML_CONTEXT_TYPE)).toBe('99'); expect(colorer.convert(100, HTML_CONTEXT_TYPE)).toBe( @@ -45,16 +48,19 @@ describe('Color Format', () => { }); test('should not convert invalid ranges', () => { - const colorer = new ColorFormat({ - fieldType: 'number', - colors: [ - { - range: '100150', - text: 'blue', - background: 'yellow', - }, - ], - }); + const colorer = new ColorFormat( + { + fieldType: 'number', + colors: [ + { + range: '100150', + text: 'blue', + background: 'yellow', + }, + ], + }, + jest.fn() + ); expect(colorer.convert(99, HTML_CONTEXT_TYPE)).toBe('99'); }); @@ -62,16 +68,19 @@ describe('Color Format', () => { describe('field is a string', () => { test('should add colors if the regex matches', () => { - const colorer = new ColorFormat({ - fieldType: 'string', - colors: [ - { - regex: 'A.*', - text: 'blue', - background: 'yellow', - }, - ], - }); + const colorer = new ColorFormat( + { + fieldType: 'string', + colors: [ + { + regex: 'A.*', + text: 'blue', + background: 'yellow', + }, + ], + }, + jest.fn() + ); const converter = colorer.getConverterFor(HTML_CONTEXT_TYPE) as Function; expect(converter('B', HTML_CONTEXT_TYPE)).toBe('B'); @@ -97,16 +106,19 @@ describe('Color Format', () => { }); test('returns original value (escaped) when regex is invalid', () => { - const colorer = new ColorFormat({ - fieldType: 'string', - colors: [ - { - regex: 'A.*', - text: 'blue', - background: 'yellow', - }, - ], - }); + const colorer = new ColorFormat( + { + fieldType: 'string', + colors: [ + { + regex: 'A.*', + text: 'blue', + background: 'yellow', + }, + ], + }, + jest.fn() + ); const converter = colorer.getConverterFor(HTML_CONTEXT_TYPE) as Function; expect(converter('<', HTML_CONTEXT_TYPE)).toBe('<'); diff --git a/src/plugins/data/common/field_formats/converters/color.ts b/src/plugins/data/common/field_formats/converters/color.ts index 6ba8bb97332e83..ffc72ba9a2c306 100644 --- a/src/plugins/data/common/field_formats/converters/color.ts +++ b/src/plugins/data/common/field_formats/converters/color.ts @@ -20,14 +20,14 @@ import { findLast, cloneDeep, template, escape } from 'lodash'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { HtmlContextTypeConvert } from '../types'; +import { HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; import { asPrettyString } from '../utils'; import { DEFAULT_CONVERTER_COLOR } from '../constants'; const convertTemplate = template('<%- val %>'); export class ColorFormat extends FieldFormat { - static id = 'color'; + static id = FIELD_FORMAT_IDS.COLOR; static title = 'Color'; static fieldType = [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.STRING]; diff --git a/src/plugins/data/common/field_formats/converters/custom.ts b/src/plugins/data/common/field_formats/converters/custom.ts index 8ab31e5784566d..687870306c8731 100644 --- a/src/plugins/data/common/field_formats/converters/custom.ts +++ b/src/plugins/data/common/field_formats/converters/custom.ts @@ -18,13 +18,11 @@ */ import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; - -const ID = 'custom'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export const createCustomFieldFormat = (convert: TextContextTypeConvert) => class CustomFieldFormat extends FieldFormat { - static id = ID; + static id = FIELD_FORMAT_IDS.CUSTOM; textConvert = convert; }; diff --git a/src/plugins/data/common/field_formats/converters/date.ts b/src/plugins/data/common/field_formats/converters/date.ts index 0017d5afb0608f..06af64d9c17c2b 100644 --- a/src/plugins/data/common/field_formats/converters/date.ts +++ b/src/plugins/data/common/field_formats/converters/date.ts @@ -19,28 +19,23 @@ import { memoize, noop } from 'lodash'; import moment from 'moment'; -import { FieldFormat, KBN_FIELD_TYPES, TextContextTypeConvert } from '../../index'; +import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; +import { FieldFormat } from '../field_format'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class DateFormat extends FieldFormat { - static id = 'date'; + static id = FIELD_FORMAT_IDS.DATE; static title = 'Date'; static fieldType = KBN_FIELD_TYPES.DATE; - private getConfig: Function; private memoizedConverter: Function = noop; private memoizedPattern: string = ''; private timeZone: string = ''; - constructor(params: Record, getConfig: Function) { - super(params); - - this.getConfig = getConfig; - } - getParamDefaults() { return { - pattern: this.getConfig('dateFormat'), - timezone: this.getConfig('dateFormat:tz'), + pattern: this.getConfig!('dateFormat'), + timezone: this.getConfig!('dateFormat:tz'), }; } diff --git a/src/plugins/data/common/field_formats/converters/date_nanos.ts b/src/plugins/data/common/field_formats/converters/date_nanos.ts index aef47f362bc978..8b0f8b111694ee 100644 --- a/src/plugins/data/common/field_formats/converters/date_nanos.ts +++ b/src/plugins/data/common/field_formats/converters/date_nanos.ts @@ -21,7 +21,7 @@ import moment, { Moment } from 'moment'; import { memoize, noop } from 'lodash'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; /** * Analyse the given moment.js format pattern for the fractional sec part (S,SS,SSS...) @@ -69,26 +69,19 @@ export function formatWithNanos( } export class DateNanosFormat extends FieldFormat { - static id = 'date_nanos'; + static id = FIELD_FORMAT_IDS.DATE_NANOS; static title = 'Date Nanos'; static fieldType = KBN_FIELD_TYPES.DATE; - private getConfig: Function; private memoizedConverter: Function = noop; private memoizedPattern: string = ''; private timeZone: string = ''; - constructor(params: Record, getConfig: Function) { - super(params); - - this.getConfig = getConfig; - } - getParamDefaults() { return { - pattern: this.getConfig('dateNanosFormat'), - fallbackPattern: this.getConfig('dateFormat'), - timezone: this.getConfig('dateFormat:tz'), + pattern: this.getConfig!('dateNanosFormat'), + fallbackPattern: this.getConfig!('dateFormat'), + timezone: this.getConfig!('dateFormat:tz'), }; } diff --git a/src/plugins/data/common/field_formats/converters/date_server.ts b/src/plugins/data/common/field_formats/converters/date_server.ts index 7ed2745a256c42..0c214e424f1632 100644 --- a/src/plugins/data/common/field_formats/converters/date_server.ts +++ b/src/plugins/data/common/field_formats/converters/date_server.ts @@ -21,22 +21,20 @@ import { memoize, noop } from 'lodash'; import moment from 'moment-timezone'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class DateFormat extends FieldFormat { - static id = 'date'; + static id = FIELD_FORMAT_IDS.DATE; static title = 'Date'; static fieldType = KBN_FIELD_TYPES.DATE; - private getConfig: Function; private memoizedConverter: Function = noop; private memoizedPattern: string = ''; private timeZone: string = ''; constructor(params: Record, getConfig: Function) { - super(params); + super(params, getConfig); - this.getConfig = getConfig; this.memoizedConverter = memoize((val: any) => { if (val == null) { return '-'; @@ -66,8 +64,8 @@ export class DateFormat extends FieldFormat { getParamDefaults() { return { - pattern: this.getConfig('dateFormat'), - timezone: this.getConfig('dateFormat:tz'), + pattern: this.getConfig!('dateFormat'), + timezone: this.getConfig!('dateFormat:tz'), }; } diff --git a/src/plugins/data/common/field_formats/converters/duration.test.ts b/src/plugins/data/common/field_formats/converters/duration.test.ts index b892884475eec8..d6205d54bd702f 100644 --- a/src/plugins/data/common/field_formats/converters/duration.test.ts +++ b/src/plugins/data/common/field_formats/converters/duration.test.ts @@ -142,7 +142,10 @@ describe('Duration Format', () => { test(`should format ${input} ${inputFormat} through ${outputFormat}${ outputPrecision ? `, ${outputPrecision} decimals` : '' }`, () => { - const duration = new DurationFormat({ inputFormat, outputFormat, outputPrecision }); + const duration = new DurationFormat( + { inputFormat, outputFormat, outputPrecision }, + jest.fn() + ); expect(duration.convert(input)).toBe(output); }); }); diff --git a/src/plugins/data/common/field_formats/converters/duration.ts b/src/plugins/data/common/field_formats/converters/duration.ts index 5eed523214ab3f..d02de1a2fd8893 100644 --- a/src/plugins/data/common/field_formats/converters/duration.ts +++ b/src/plugins/data/common/field_formats/converters/duration.ts @@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n'; import moment, { unitOfTime, Duration } from 'moment'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; const ratioToSeconds: Record = { picoseconds: 0.000000000001, @@ -166,7 +166,7 @@ function parseInputAsDuration(val: number, inputFormat: string) { } export class DurationFormat extends FieldFormat { - static id = 'duration'; + static id = FIELD_FORMAT_IDS.DURATION; static title = 'Duration'; static fieldType = KBN_FIELD_TYPES.NUMBER; static inputFormats = inputFormats; diff --git a/src/plugins/data/common/field_formats/converters/ip.test.ts b/src/plugins/data/common/field_formats/converters/ip.test.ts index cc42d41adc4a13..a9a02d1a43ea80 100644 --- a/src/plugins/data/common/field_formats/converters/ip.test.ts +++ b/src/plugins/data/common/field_formats/converters/ip.test.ts @@ -23,7 +23,7 @@ describe('IP Address Format', () => { let ip: Record; beforeEach(() => { - ip = new IpFormat(); + ip = new IpFormat({}, jest.fn()); }); test('converts a value from a decimal to a string', () => { diff --git a/src/plugins/data/common/field_formats/converters/ip.ts b/src/plugins/data/common/field_formats/converters/ip.ts index 669f7d1b605d76..3e011e8d7dde8f 100644 --- a/src/plugins/data/common/field_formats/converters/ip.ts +++ b/src/plugins/data/common/field_formats/converters/ip.ts @@ -19,10 +19,10 @@ import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class IpFormat extends FieldFormat { - static id = 'ip'; + static id = FIELD_FORMAT_IDS.IP; static title = 'IP Address'; static fieldType = KBN_FIELD_TYPES.IP; diff --git a/src/plugins/data/common/field_formats/converters/number.ts b/src/plugins/data/common/field_formats/converters/number.ts index e0c22f5350716f..6969c1551e1ccb 100644 --- a/src/plugins/data/common/field_formats/converters/number.ts +++ b/src/plugins/data/common/field_formats/converters/number.ts @@ -18,9 +18,10 @@ */ import { NumeralFormat } from './numeral'; +import { FIELD_FORMAT_IDS } from '../types'; export class NumberFormat extends NumeralFormat { - static id = 'number'; + static id = FIELD_FORMAT_IDS.NUMBER; static title = 'Number'; id = NumberFormat.id; diff --git a/src/plugins/data/common/field_formats/converters/numeral.ts b/src/plugins/data/common/field_formats/converters/numeral.ts index f7bf7ddfd1701c..d8e46a480294f4 100644 --- a/src/plugins/data/common/field_formats/converters/numeral.ts +++ b/src/plugins/data/common/field_formats/converters/numeral.ts @@ -37,15 +37,8 @@ export abstract class NumeralFormat extends FieldFormat { abstract id: string; abstract title: string; - protected getConfig: Function; - - constructor(params: Record, getConfig: Function) { - super(params); - this.getConfig = getConfig; - } - getParamDefaults = () => ({ - pattern: this.getConfig(`format:${this.id}:defaultPattern`), + pattern: this.getConfig!(`format:${this.id}:defaultPattern`), }); protected getConvertedValue(val: any): string { diff --git a/src/plugins/data/common/field_formats/converters/percent.ts b/src/plugins/data/common/field_formats/converters/percent.ts index f810f123773623..2ae32c7c77f076 100644 --- a/src/plugins/data/common/field_formats/converters/percent.ts +++ b/src/plugins/data/common/field_formats/converters/percent.ts @@ -18,17 +18,17 @@ */ import { NumeralFormat } from './numeral'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class PercentFormat extends NumeralFormat { - static id = 'percent'; + static id = FIELD_FORMAT_IDS.PERCENT; static title = 'Percentage'; id = PercentFormat.id; title = PercentFormat.title; getParamDefaults = () => ({ - pattern: this.getConfig('format:percent:defaultPattern'), + pattern: this.getConfig!('format:percent:defaultPattern'), fractional: true, }); diff --git a/src/plugins/data/common/field_formats/converters/relative_date.test.ts b/src/plugins/data/common/field_formats/converters/relative_date.test.ts index bde5aec0a5ab51..6311402a34b462 100644 --- a/src/plugins/data/common/field_formats/converters/relative_date.test.ts +++ b/src/plugins/data/common/field_formats/converters/relative_date.test.ts @@ -24,7 +24,7 @@ describe('Relative Date Format', () => { let convert: Function; beforeEach(() => { - const relativeDate = new RelativeDateFormat({}); + const relativeDate = new RelativeDateFormat({}, jest.fn()); convert = relativeDate.convert.bind(relativeDate); }); diff --git a/src/plugins/data/common/field_formats/converters/relative_date.ts b/src/plugins/data/common/field_formats/converters/relative_date.ts index caab8c3a2d7da7..273b2cef28a030 100644 --- a/src/plugins/data/common/field_formats/converters/relative_date.ts +++ b/src/plugins/data/common/field_formats/converters/relative_date.ts @@ -20,17 +20,13 @@ import moment from 'moment'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class RelativeDateFormat extends FieldFormat { - static id = 'relative_date'; + static id = FIELD_FORMAT_IDS.RELATIVE_DATE; static title = 'Relative Date'; static fieldType = KBN_FIELD_TYPES.DATE; - constructor(params: Record) { - super(params); - } - textConvert: TextContextTypeConvert = val => { if (val === null || val === undefined) { return '-'; diff --git a/src/plugins/data/common/field_formats/converters/source.ts b/src/plugins/data/common/field_formats/converters/source.ts index 35eb14ca59ebb2..54977c7e669761 100644 --- a/src/plugins/data/common/field_formats/converters/source.ts +++ b/src/plugins/data/common/field_formats/converters/source.ts @@ -24,7 +24,7 @@ import { noWhiteSpace } from '../../../../../legacy/core_plugins/kibana/common/u import { shortenDottedString } from '../../../../../legacy/core_plugins/kibana/common/utils/shorten_dotted_string'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert, HtmlContextTypeConvert } from '../types'; +import { TextContextTypeConvert, HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; const templateHtml = `

@@ -37,18 +37,10 @@ const templateHtml = ` const doTemplate = template(noWhiteSpace(templateHtml)); export class SourceFormat extends FieldFormat { - static id = '_source'; + static id = FIELD_FORMAT_IDS._SOURCE; static title = '_source'; static fieldType = KBN_FIELD_TYPES._SOURCE; - private getConfig: Function; - - constructor(params: Record, getConfig: Function) { - super(params); - - this.getConfig = getConfig; - } - textConvert: TextContextTypeConvert = value => JSON.stringify(value); htmlConvert: HtmlContextTypeConvert = (value, field, hit) => { @@ -62,7 +54,7 @@ export class SourceFormat extends FieldFormat { const formatted = field.indexPattern.formatHit(hit); const highlightPairs: any[] = []; const sourcePairs: any[] = []; - const isShortDots = this.getConfig('shortDots:enable'); + const isShortDots = this.getConfig!('shortDots:enable'); keys(formatted).forEach(key => { const pairs = highlights[key] ? highlightPairs : sourcePairs; diff --git a/src/plugins/data/common/field_formats/converters/static_lookup.ts b/src/plugins/data/common/field_formats/converters/static_lookup.ts index 29c64fd4f40462..419e7c786640bf 100644 --- a/src/plugins/data/common/field_formats/converters/static_lookup.ts +++ b/src/plugins/data/common/field_formats/converters/static_lookup.ts @@ -19,7 +19,7 @@ import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; function convertLookupEntriesToMap(lookupEntries: any[]) { return lookupEntries.reduce( @@ -32,7 +32,7 @@ function convertLookupEntriesToMap(lookupEntries: any[]) { } export class StaticLookupFormat extends FieldFormat { - static id = 'static_lookup'; + static id = FIELD_FORMAT_IDS.STATIC_LOOKUP; static title = 'Static Lookup'; static fieldType = [ KBN_FIELD_TYPES.STRING, diff --git a/src/plugins/data/common/field_formats/converters/string.test.ts b/src/plugins/data/common/field_formats/converters/string.test.ts index bb0fd5cc011b67..b2d96ed5c03080 100644 --- a/src/plugins/data/common/field_formats/converters/string.test.ts +++ b/src/plugins/data/common/field_formats/converters/string.test.ts @@ -21,30 +21,42 @@ import { StringFormat } from './string'; describe('String Format', () => { test('convert a string to lower case', () => { - const string = new StringFormat({ - transform: 'lower', - }); + const string = new StringFormat( + { + transform: 'lower', + }, + jest.fn() + ); expect(string.convert('Kibana')).toBe('kibana'); }); test('convert a string to upper case', () => { - const string = new StringFormat({ - transform: 'upper', - }); + const string = new StringFormat( + { + transform: 'upper', + }, + jest.fn() + ); expect(string.convert('Kibana')).toBe('KIBANA'); }); test('decode a base64 string', () => { - const string = new StringFormat({ - transform: 'base64', - }); + const string = new StringFormat( + { + transform: 'base64', + }, + jest.fn() + ); expect(string.convert('Zm9vYmFy')).toBe('foobar'); }); test('convert a string to title case', () => { - const string = new StringFormat({ - transform: 'title', - }); + const string = new StringFormat( + { + transform: 'title', + }, + jest.fn() + ); expect(string.convert('PLEASE DO NOT SHOUT')).toBe('Please Do Not Shout'); expect(string.convert('Mean, variance and standard_deviation.')).toBe( 'Mean, Variance And Standard_deviation.' @@ -53,24 +65,33 @@ describe('String Format', () => { }); test('convert a string to short case', () => { - const string = new StringFormat({ - transform: 'short', - }); + const string = new StringFormat( + { + transform: 'short', + }, + jest.fn() + ); expect(string.convert('dot.notated.string')).toBe('d.n.string'); }); test('convert a string to unknown transform case', () => { - const string = new StringFormat({ - transform: 'unknown_transform', - }); + const string = new StringFormat( + { + transform: 'unknown_transform', + }, + jest.fn() + ); const value = 'test test test'; expect(string.convert(value)).toBe(value); }); test('decode a URL Param string', () => { - const string = new StringFormat({ - transform: 'urlparam', - }); + const string = new StringFormat( + { + transform: 'urlparam', + }, + jest.fn() + ); expect(string.convert('%EC%95%88%EB%85%95%20%ED%82%A4%EB%B0%94%EB%82%98')).toBe('안녕 키바나'); }); }); diff --git a/src/plugins/data/common/field_formats/converters/string.ts b/src/plugins/data/common/field_formats/converters/string.ts index 82547c0b0dee52..0edd219ca60f94 100644 --- a/src/plugins/data/common/field_formats/converters/string.ts +++ b/src/plugins/data/common/field_formats/converters/string.ts @@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n'; import { asPrettyString } from '../index'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; // @ts-ignore import { shortenDottedString } from '../../../../../legacy/core_plugins/kibana/common/utils/shorten_dotted_string'; @@ -72,7 +72,7 @@ const TRANSFORM_OPTIONS = [ const DEFAULT_TRANSFORM_OPTION = false; export class StringFormat extends FieldFormat { - static id = 'string'; + static id = FIELD_FORMAT_IDS.STRING; static title = 'String'; static fieldType = [ KBN_FIELD_TYPES.NUMBER, diff --git a/src/plugins/data/common/field_formats/converters/truncate.test.ts b/src/plugins/data/common/field_formats/converters/truncate.test.ts index 7de4bdb3dedfe6..472d9673346d7d 100644 --- a/src/plugins/data/common/field_formats/converters/truncate.test.ts +++ b/src/plugins/data/common/field_formats/converters/truncate.test.ts @@ -21,25 +21,25 @@ import { TruncateFormat } from './truncate'; describe('String TruncateFormat', () => { test('truncate large string', () => { - const truncate = new TruncateFormat({ fieldLength: 4 }); + const truncate = new TruncateFormat({ fieldLength: 4 }, jest.fn()); expect(truncate.convert('This is some text')).toBe('This...'); }); test('does not truncate large string when field length is not a string', () => { - const truncate = new TruncateFormat({ fieldLength: 'not number' }); + const truncate = new TruncateFormat({ fieldLength: 'not number' }, jest.fn()); expect(truncate.convert('This is some text')).toBe('This is some text'); }); test('does not truncate large string when field length is null', () => { - const truncate = new TruncateFormat({ fieldLength: null }); + const truncate = new TruncateFormat({ fieldLength: null }, jest.fn()); expect(truncate.convert('This is some text')).toBe('This is some text'); }); test('does not truncate large string when field length larger than the text', () => { - const truncate = new TruncateFormat({ fieldLength: 100000 }); + const truncate = new TruncateFormat({ fieldLength: 100000 }, jest.fn()); expect(truncate.convert('This is some text')).toBe('This is some text'); }); diff --git a/src/plugins/data/common/field_formats/converters/truncate.ts b/src/plugins/data/common/field_formats/converters/truncate.ts index acccf2a20c69a9..dc25d71ec95d73 100644 --- a/src/plugins/data/common/field_formats/converters/truncate.ts +++ b/src/plugins/data/common/field_formats/converters/truncate.ts @@ -20,12 +20,12 @@ import { trunc } from 'lodash'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; const omission = '...'; export class TruncateFormat extends FieldFormat { - static id = 'truncate'; + static id = FIELD_FORMAT_IDS.TRUNCATE; static title = 'Truncated String'; static fieldType = KBN_FIELD_TYPES.STRING; diff --git a/src/plugins/data/common/field_formats/converters/url.ts b/src/plugins/data/common/field_formats/converters/url.ts index 6c00f11a408dc6..bd68dedf38a678 100644 --- a/src/plugins/data/common/field_formats/converters/url.ts +++ b/src/plugins/data/common/field_formats/converters/url.ts @@ -22,7 +22,7 @@ import { escape, memoize } from 'lodash'; import { getHighlightHtml } from '../utils'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert, HtmlContextTypeConvert } from '../types'; +import { TextContextTypeConvert, HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; const templateMatchRE = /{{([\s\S]+?)}}/g; const whitelistUrlSchemes = ['http://', 'https://']; @@ -50,7 +50,7 @@ const URL_TYPES = [ const DEFAULT_URL_TYPE = 'a'; export class UrlFormat extends FieldFormat { - static id = 'url'; + static id = FIELD_FORMAT_IDS.URL; static title = 'Url'; static fieldType = [ KBN_FIELD_TYPES.NUMBER, diff --git a/src/plugins/data/common/field_formats/field_format.test.ts b/src/plugins/data/common/field_formats/field_format.test.ts index d4789f12bdee9d..2229601994496d 100644 --- a/src/plugins/data/common/field_formats/field_format.test.ts +++ b/src/plugins/data/common/field_formats/field_format.test.ts @@ -32,7 +32,7 @@ const getTestFormat = ( textConvert = textConvert; htmlConvert = htmlConvert; - })(_params); + })(_params, jest.fn()); describe('FieldFormat class', () => { describe('params', () => { diff --git a/src/plugins/data/common/field_formats/field_format.ts b/src/plugins/data/common/field_formats/field_format.ts index e99894ca561676..6b5f665c6e20e5 100644 --- a/src/plugins/data/common/field_formats/field_format.ts +++ b/src/plugins/data/common/field_formats/field_format.ts @@ -19,7 +19,12 @@ import { transform, size, cloneDeep, get, defaults } from 'lodash'; import { createCustomFieldFormat } from './converters/custom'; -import { ContentType, FieldFormatConvert, FieldFormatConvertFunction } from './types'; +import { + ContentType, + FIELD_FORMAT_IDS, + FieldFormatConvert, + FieldFormatConvertFunction, +} from './types'; import { htmlContentTypeSetup, textContentTypeSetup, @@ -68,7 +73,16 @@ export abstract class FieldFormat { */ public type: any = this.constructor; - constructor(public _params: any = {}) {} + private readonly _params: any; + protected getConfig: Function | undefined; + + constructor(_params: any = {}, getConfig?: Function) { + this._params = _params; + + if (getConfig) { + this.getConfig = getConfig; + } + } /** * Convert a raw value to a formatted string @@ -170,7 +184,7 @@ export abstract class FieldFormat { }; } - static from(convertFn: FieldFormatConvertFunction): ReturnType { + static from(convertFn: FieldFormatConvertFunction): IFieldFormatType { return createCustomFieldFormat(convertFn); } @@ -183,3 +197,11 @@ export abstract class FieldFormat { } export type IFieldFormat = PublicMethodsOf; +/** + * @string id type is needed for creating custom converters. + */ +export type IFieldFormatId = FIELD_FORMAT_IDS | string; +export type IFieldFormatType = (new (params?: any, getConfig?: Function) => FieldFormat) & { + id: IFieldFormatId; + fieldType: string | string[]; +}; diff --git a/src/plugins/data/common/field_formats/index.ts b/src/plugins/data/common/field_formats/index.ts index 5d04a69e4dc50e..b751b097b5ed2c 100644 --- a/src/plugins/data/common/field_formats/index.ts +++ b/src/plugins/data/common/field_formats/index.ts @@ -18,7 +18,7 @@ */ export { HTML_CONTEXT_TYPE, TEXT_CONTEXT_TYPE } from './content_types'; -export { FieldFormat } from './field_format'; +export { FieldFormat, IFieldFormatType, IFieldFormatId } from './field_format'; export { getHighlightRequest, asPrettyString, getHighlightHtml } from './utils'; export * from './converters'; export * from './constants'; diff --git a/src/plugins/data/common/field_formats/types.ts b/src/plugins/data/common/field_formats/types.ts index 626bab297392b4..fc8e6e20a1a968 100644 --- a/src/plugins/data/common/field_formats/types.ts +++ b/src/plugins/data/common/field_formats/types.ts @@ -42,3 +42,23 @@ export interface FieldFormatConvert { text: TextContextTypeConvert; html: HtmlContextTypeConvert; } + +/** @public **/ +export enum FIELD_FORMAT_IDS { + _SOURCE = '_source', + BOOLEAN = 'boolean', + BYTES = 'bytes', + COLOR = 'color', + CUSTOM = 'custom', + DATE = 'date', + DATE_NANOS = 'date_nanos', + DURATION = 'duration', + IP = 'ip', + NUMBER = 'number', + PERCENT = 'percent', + RELATIVE_DATE = 'relative_date', + STATIC_LOOKUP = 'static_lookup', + STRING = 'string', + TRUNCATE = 'truncate', + URL = 'url', +} diff --git a/src/plugins/data/common/kbn_field_types/types.ts b/src/plugins/data/common/kbn_field_types/types.ts index 21d58bcd0f78c8..11c62e8f86dce3 100644 --- a/src/plugins/data/common/kbn_field_types/types.ts +++ b/src/plugins/data/common/kbn_field_types/types.ts @@ -27,9 +27,10 @@ export interface KbnFieldTypeOptions { /** @public **/ export enum ES_FIELD_TYPES { - _TYPE = '_type', _ID = '_id', + _INDEX = '_index', _SOURCE = '_source', + _TYPE = '_type', STRING = 'string', TEXT = 'text', diff --git a/src/plugins/data/public/field_formats_provider/field_formats.ts b/src/plugins/data/public/field_formats_provider/field_formats.ts new file mode 100644 index 00000000000000..f46994c209dedc --- /dev/null +++ b/src/plugins/data/public/field_formats_provider/field_formats.ts @@ -0,0 +1,226 @@ +/* + * 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 { forOwn, isFunction, memoize } from 'lodash'; +import { UiSettingsClientContract } from 'kibana/public'; +import { + ES_FIELD_TYPES, + KBN_FIELD_TYPES, + FIELD_FORMAT_IDS, + IFieldFormatType, + IFieldFormatId, + FieldFormat, +} from '../../common'; +import { FieldType } from './types'; + +export class FieldFormatRegisty { + private fieldFormats: Map; + private uiSettings!: UiSettingsClientContract; + private defaultMap: Record; + + constructor() { + this.fieldFormats = new Map(); + this.defaultMap = {}; + } + + getConfig = (key: string, override?: any) => this.uiSettings.get(key, override); + + init(uiSettings: UiSettingsClientContract) { + this.uiSettings = uiSettings; + + this.parseDefaultTypeMap(this.uiSettings.get('format:defaultTypeMap')); + + this.uiSettings.getUpdate$().subscribe(({ key, newValue }) => { + if (key === 'format:defaultTypeMap') { + this.parseDefaultTypeMap(newValue); + } + }); + } + + /** + * Get the id of the default type for this field type + * using the format:defaultTypeMap config map + * + * @param {KBN_FIELD_TYPES} fieldType - the field type + * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types + * @return {FieldType} + */ + getDefaultConfig = (fieldType: KBN_FIELD_TYPES, esTypes?: ES_FIELD_TYPES[]): FieldType => { + const type = this.getDefaultTypeName(fieldType, esTypes); + + return ( + (this.defaultMap && this.defaultMap[type]) || { id: FIELD_FORMAT_IDS.STRING, params: {} } + ); + }; + + /** + * Get a derived FieldFormat class by its id. + * + * @param {IFieldFormatId} formatId - the format id + * @return {FieldFormat} + */ + getType = (formatId: IFieldFormatId): IFieldFormatType | undefined => { + return this.fieldFormats.get(formatId); + }; + + /** + * Get the default FieldFormat type (class) for + * a field type, using the format:defaultTypeMap. + * used by the field editor + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types + * @return {FieldFormat} + */ + getDefaultType = ( + fieldType: KBN_FIELD_TYPES, + esTypes: ES_FIELD_TYPES[] + ): IFieldFormatType | undefined => { + const config = this.getDefaultConfig(fieldType, esTypes); + + return this.getType(config.id); + }; + + /** + * Get the name of the default type for ES types like date_nanos + * using the format:defaultTypeMap config map + * + * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types + * @return {ES_FIELD_TYPES} + */ + getTypeNameByEsTypes = (esTypes: ES_FIELD_TYPES[] | undefined): ES_FIELD_TYPES | undefined => { + if (!Array.isArray(esTypes)) { + return; + } + + return esTypes.find(type => this.defaultMap[type] && this.defaultMap[type].es); + }; + + /** + * Get the default FieldFormat type name for + * a field type, using the format:defaultTypeMap. + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {ES_FIELD_TYPES | String} + */ + getDefaultTypeName = ( + fieldType: KBN_FIELD_TYPES, + esTypes?: ES_FIELD_TYPES[] + ): ES_FIELD_TYPES | KBN_FIELD_TYPES => { + const esType = this.getTypeNameByEsTypes(esTypes); + + return esType || fieldType; + }; + + /** + * Get the singleton instance of the FieldFormat type by its id. + * + * @param {IFieldFormatId} formatId + * @return {FIELD_FORMATS_INSTANCES[number]} + */ + getInstance = memoize( + (formatId: IFieldFormatId): FieldFormat => { + const DerivedFieldFormat = this.getType(formatId); + + if (!DerivedFieldFormat) { + throw new Error(`Field Format '${formatId}' not found!`); + } + + return new DerivedFieldFormat({}, this.getConfig); + } + ); + + /** + * Get the default fieldFormat instance for a field format. + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {FieldFormat} + */ + getDefaultInstancePlain(fieldType: KBN_FIELD_TYPES, esTypes?: ES_FIELD_TYPES[]): FieldFormat { + const conf = this.getDefaultConfig(fieldType, esTypes); + + const DerivedFieldFormat = this.getType(conf.id); + + if (!DerivedFieldFormat) { + throw new Error(`Field Format '${conf.id}' not found!`); + } + + return new DerivedFieldFormat(conf.params, this.getConfig); + } + /** + * Returns a cache key built by the given variables for caching in memoized + * Where esType contains fieldType, fieldType is returned + * -> kibana types have a higher priority in that case + * -> would lead to failing tests that match e.g. date format with/without esTypes + * https://lodash.com/docs#memoize + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {String} + */ + getDefaultInstanceCacheResolver(fieldType: KBN_FIELD_TYPES, esTypes: ES_FIELD_TYPES[]): string { + // @ts-ignore + return Array.isArray(esTypes) && esTypes.indexOf(fieldType) === -1 + ? [fieldType, ...esTypes].join('-') + : fieldType; + } + + /** + * Get filtered list of field formats by format type + * + * @param {KBN_FIELD_TYPES} fieldType + * @return {FieldFormat[]} + */ + getByFieldType(fieldType: KBN_FIELD_TYPES): IFieldFormatType[] { + return [...this.fieldFormats.values()].filter( + (format: IFieldFormatType) => format.fieldType.indexOf(fieldType) !== -1 + ); + } + + /** + * Get the default fieldFormat instance for a field format. + * It's a memoized function that builds and reads a cache + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {FieldFormat} + */ + getDefaultInstance = memoize(this.getDefaultInstancePlain, this.getDefaultInstanceCacheResolver); + + parseDefaultTypeMap(value: any) { + this.defaultMap = value; + forOwn(this, fn => { + if (isFunction(fn) && fn.cache) { + // clear all memoize caches + // @ts-ignore + fn.cache = new memoize.Cache(); + } + }); + } + + register = (fieldFormats: IFieldFormatType[]) => { + fieldFormats.forEach(fieldFormat => { + this.fieldFormats.set(fieldFormat.id, fieldFormat); + }); + + return this; + }; +} diff --git a/src/plugins/data/public/field_formats_provider/field_formats_service.ts b/src/plugins/data/public/field_formats_provider/field_formats_service.ts new file mode 100644 index 00000000000000..b144ea7ec25304 --- /dev/null +++ b/src/plugins/data/public/field_formats_provider/field_formats_service.ts @@ -0,0 +1,87 @@ +/* + * 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 { UiSettingsClientContract } from 'src/core/public'; +import { FieldFormatRegisty } from './field_formats'; + +import { + BoolFormat, + BytesFormat, + ColorFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, + SourceFormat, + StaticLookupFormat, + StringFormat, + TruncateFormat, + UrlFormat, +} from '../../common/'; + +/** + * Field Format Service + * @internal + */ +interface FieldFormatsServiceDependencies { + uiSettings: UiSettingsClientContract; +} + +export class FieldFormatsService { + private readonly fieldFormats: FieldFormatRegisty = new FieldFormatRegisty(); + + public setup({ uiSettings }: FieldFormatsServiceDependencies) { + this.fieldFormats.init(uiSettings); + + this.fieldFormats.register([ + BoolFormat, + BytesFormat, + ColorFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, + SourceFormat, + StaticLookupFormat, + StringFormat, + TruncateFormat, + UrlFormat, + ]); + + return this.fieldFormats as FieldFormatsSetup; + } + + public start() { + return this.fieldFormats as FieldFormatsStart; + } + + public stop() { + // nothing to do here yet + } +} + +/** @public */ +export type FieldFormatsSetup = Omit; +export type FieldFormatsStart = Omit; diff --git a/src/plugins/data/public/field_formats_provider/index.ts b/src/plugins/data/public/field_formats_provider/index.ts new file mode 100644 index 00000000000000..442d877c5316a7 --- /dev/null +++ b/src/plugins/data/public/field_formats_provider/index.ts @@ -0,0 +1,21 @@ +/* + * 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 { FieldFormatRegisty } from './field_formats'; // TODO: Try to remove +export { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats_service'; diff --git a/src/legacy/ui/public/registry/field_formats.d.ts b/src/plugins/data/public/field_formats_provider/types.ts similarity index 84% rename from src/legacy/ui/public/registry/field_formats.d.ts rename to src/plugins/data/public/field_formats_provider/types.ts index 79eec7a5a4e742..fc33bf4d38f850 100644 --- a/src/legacy/ui/public/registry/field_formats.d.ts +++ b/src/plugins/data/public/field_formats_provider/types.ts @@ -17,4 +17,10 @@ * under the License. */ -export type FieldFormat = any; +import { IFieldFormatId } from '../../common'; + +export interface FieldType { + id: IFieldFormatId; + params: Record; + es?: boolean; +} diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 4477c6defbc81b..6a2df6a61d1366 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -29,6 +29,8 @@ export { DataPublicPlugin as Plugin }; export * from '../common'; export * from './autocomplete_provider'; +export * from './field_formats_provider'; + export * from './types'; export { IRequestTypesMap, IResponseTypesMap } from './search'; diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 4aae63c24d7fc7..ff5c96c2d89edb 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Plugin } from '.'; +import { FieldFormatRegisty, Plugin, FieldFormatsStart, FieldFormatsSetup } from '.'; import { searchSetupMock } from './search/mocks'; import { queryServiceMock } from './query/mocks'; @@ -29,11 +29,29 @@ const autocompleteMock: any = { clearProviders: jest.fn(), }; +const fieldFormatsMock: PublicMethodsOf = { + getByFieldType: jest.fn(), + getConfig: jest.fn(), + getDefaultConfig: jest.fn(), + getDefaultInstance: jest.fn() as any, + getDefaultInstanceCacheResolver: jest.fn(), + getDefaultInstancePlain: jest.fn(), + getDefaultType: jest.fn(), + getDefaultTypeName: jest.fn(), + getInstance: jest.fn() as any, + getType: jest.fn(), + getTypeNameByEsTypes: jest.fn(), + init: jest.fn(), + register: jest.fn(), + parseDefaultTypeMap: jest.fn(), +}; + const createSetupContract = (): Setup => { const querySetupMock = queryServiceMock.createSetupContract(); const setupContract = { autocomplete: autocompleteMock, search: searchSetupMock, + fieldFormats: fieldFormatsMock as FieldFormatsSetup, query: querySetupMock, }; @@ -46,6 +64,7 @@ const createStartContract = (): Start => { autocomplete: autocompleteMock, getSuggestions: jest.fn(), search: { search: jest.fn() }, + fieldFormats: fieldFormatsMock as FieldFormatsStart, query: queryStartMock, }; return startContract; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 79db34c022b39f..3aa9cd9a0bcb44 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -17,29 +17,34 @@ * under the License. */ -import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public'; +import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { Storage } from '../../kibana_utils/public'; import { DataPublicPluginSetup, DataPublicPluginStart } from './types'; import { AutocompleteProviderRegister } from './autocomplete_provider'; import { getSuggestionsProvider } from './suggestions_provider'; import { SearchService } from './search/search_service'; +import { FieldFormatsService } from './field_formats_provider'; import { QueryService } from './query'; export class DataPublicPlugin implements Plugin { private readonly autocomplete = new AutocompleteProviderRegister(); private readonly searchService: SearchService; + private readonly fieldFormatsService: FieldFormatsService; private readonly queryService: QueryService; constructor(initializerContext: PluginInitializerContext) { this.searchService = new SearchService(initializerContext); this.queryService = new QueryService(); + this.fieldFormatsService = new FieldFormatsService(); } public setup(core: CoreSetup): DataPublicPluginSetup { const storage = new Storage(window.localStorage); + return { autocomplete: this.autocomplete, search: this.searchService.setup(core), + fieldFormats: this.fieldFormatsService.setup(core), query: this.queryService.setup({ uiSettings: core.uiSettings, storage, @@ -52,6 +57,7 @@ export class DataPublicPlugin implements Plugin { + const fieldFormats = new FieldFormatRegisty(); + + fieldFormats.register([ + BoolFormat, + BytesFormat, + ColorFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, + SourceFormat, + StaticLookupFormat, + StringFormat, + TruncateFormat, + UrlFormat, + ]); + + fieldFormats.init(uiSettings); -fieldFormats.register(UrlFormat); -fieldFormats.register(BytesFormat); -fieldFormats.register(DateFormat); -fieldFormats.register(DateNanosFormat); -fieldFormats.register(RelativeDateFormat); -fieldFormats.register(DurationFormat); -fieldFormats.register(IpFormat); -fieldFormats.register(NumberFormat); -fieldFormats.register(PercentFormat); -fieldFormats.register(StringFormat); -fieldFormats.register(SourceFormat); -fieldFormats.register(ColorFormat); -fieldFormats.register(TruncateFormat); -fieldFormats.register(BoolFormat); -fieldFormats.register(StaticLookupFormat); + return fieldFormats; +}; diff --git a/src/test_utils/public/stub_index_pattern.js b/src/test_utils/public/stub_index_pattern.js index a6a0eb386d32ec..b41ebe3e618615 100644 --- a/src/test_utils/public/stub_index_pattern.js +++ b/src/test_utils/public/stub_index_pattern.js @@ -28,9 +28,15 @@ import { formatHitProvider, flattenHitWrapper, } from 'ui/index_patterns'; -import { fieldFormats } from 'ui/registry/field_formats'; +import { + FIELD_FORMAT_IDS, +} from '../../plugins/data/public'; + +import { getFieldFormatsRegistry } from './stub_field_formats'; + +export default function StubIndexPattern(pattern, getConfig, timeField, fields, uiSettings) { + const registeredFieldFormats = getFieldFormatsRegistry(uiSettings); -export default function StubIndexPattern(pattern, getConfig, timeField, fields) { this.id = pattern; this.title = pattern; this.popularizeField = sinon.stub(); @@ -47,7 +53,7 @@ export default function StubIndexPattern(pattern, getConfig, timeField, fields) this.getComputedFields = IndexPattern.prototype.getComputedFields.bind(this); this.flattenHit = flattenHitWrapper(this, this.metaFields); - this.formatHit = formatHitProvider(this, fieldFormats.getDefaultInstance('string')); + this.formatHit = formatHitProvider(this, registeredFieldFormats.getDefaultInstance(FIELD_FORMAT_IDS.STRING)); this.fieldsFetcher = { apiClient: { baseUrl: '' } }; this.formatField = this.formatHit.formatField; @@ -56,7 +62,7 @@ export default function StubIndexPattern(pattern, getConfig, timeField, fields) }; this.stubSetFieldFormat = function (fieldName, id, params) { - const FieldFormat = fieldFormats.getType(id); + const FieldFormat = registeredFieldFormats.getType(id); this.fieldFormatMap[fieldName] = new FieldFormat(params); this._reindexFields(); }; diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app.js b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app.js index b0db26c0c67434..fe004b79ba45c7 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app.js +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app.js @@ -37,7 +37,6 @@ import 'uiExports/visRequestHandlers'; import 'uiExports/visEditorTypes'; import 'uiExports/visualize'; import 'uiExports/savedObjectTypes'; -import 'uiExports/fieldFormats'; import 'uiExports/search'; import { Main } from './components/main'; diff --git a/x-pack/legacy/plugins/canvas/public/app.js b/x-pack/legacy/plugins/canvas/public/app.js index 0ba7385cf7a9ea..9faa92a02a9eff 100644 --- a/x-pack/legacy/plugins/canvas/public/app.js +++ b/x-pack/legacy/plugins/canvas/public/app.js @@ -19,7 +19,6 @@ import 'uiExports/visRequestHandlers'; import 'uiExports/visEditorTypes'; import 'uiExports/savedObjectTypes'; import 'uiExports/spyModes'; -import 'uiExports/fieldFormats'; import 'uiExports/embeddableFactories'; import 'uiExports/interpreter'; diff --git a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js index 4fbba4a5ffd31c..8093c57d2631aa 100644 --- a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js @@ -26,7 +26,6 @@ import 'uiExports/embeddableActions'; import 'uiExports/embeddableFactories'; import 'uiExports/navbarExtensions'; import 'uiExports/docViews'; -import 'uiExports/fieldFormats'; import 'uiExports/search'; import 'uiExports/shareContextMenuExtensions'; import _ from 'lodash'; diff --git a/x-pack/legacy/plugins/graph/public/index.ts b/x-pack/legacy/plugins/graph/public/index.ts index 833134abff0b60..988aa786950950 100644 --- a/x-pack/legacy/plugins/graph/public/index.ts +++ b/x-pack/legacy/plugins/graph/public/index.ts @@ -6,7 +6,6 @@ // legacy imports currently necessary to power Graph // for a cutover all of these have to be resolved -import 'uiExports/fieldFormats'; import 'uiExports/savedObjectTypes'; import 'uiExports/autocompleteProviders'; import 'ui/autoload/all'; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx index affb1accbbef46..dc23df250ebd47 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx @@ -17,7 +17,6 @@ import { EuiProgress } from '@elastic/eui'; import { documentField } from './document_field'; jest.mock('ui/new_platform'); -jest.mock('../../../../../../src/legacy/ui/public/registry/field_formats'); const initialState: IndexPatternPrivateState = { indexPatternRefs: [], diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.test.tsx index 9956c0ec330616..1b49eb6bca7faa 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.test.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.test.tsx @@ -10,63 +10,58 @@ import { EuiLoadingSpinner, EuiPopover } from '@elastic/eui'; import { FieldItem, FieldItemProps } from './field_item'; import { coreMock } from 'src/core/public/mocks'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { npStart } from 'ui/new_platform'; +import { FieldFormatsStart } from '../../../../../../src/plugins/data/public'; +import { IndexPattern } from './types'; jest.mock('ui/new_platform'); -// Formatter must be mocked to return a string, or the rendering will fail -jest.mock('../../../../../../src/legacy/ui/public/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn().mockReturnValue({ - convert: jest.fn().mockReturnValue((s: unknown) => JSON.stringify(s)), - }), - }, -})); - const waitForPromises = () => new Promise(resolve => setTimeout(resolve)); -const indexPattern = { - id: '1', - title: 'my-fake-index-pattern', - timeFieldName: 'timestamp', - fields: [ - { - name: 'timestamp', - type: 'date', - aggregatable: true, - searchable: true, - }, - { - name: 'bytes', - type: 'number', - aggregatable: true, - searchable: true, - }, - { - name: 'memory', - type: 'number', - aggregatable: true, - searchable: true, - }, - { - name: 'unsupported', - type: 'geo', - aggregatable: true, - searchable: true, - }, - { - name: 'source', - type: 'string', - aggregatable: true, - searchable: true, - }, - ], -}; - describe('IndexPattern Field Item', () => { let defaultProps: FieldItemProps; + let indexPattern: IndexPattern; let core: ReturnType; beforeEach(() => { + indexPattern = { + id: '1', + title: 'my-fake-index-pattern', + timeFieldName: 'timestamp', + fields: [ + { + name: 'timestamp', + type: 'date', + aggregatable: true, + searchable: true, + }, + { + name: 'bytes', + type: 'number', + aggregatable: true, + searchable: true, + }, + { + name: 'memory', + type: 'number', + aggregatable: true, + searchable: true, + }, + { + name: 'unsupported', + type: 'geo', + aggregatable: true, + searchable: true, + }, + { + name: 'source', + type: 'string', + aggregatable: true, + searchable: true, + }, + ], + } as IndexPattern; + core = coreMock.createSetup(); core.http.post.mockClear(); defaultProps = { @@ -87,6 +82,12 @@ describe('IndexPattern Field Item', () => { }, exists: true, }; + + npStart.plugins.data.fieldFormats = ({ + getDefaultInstance: jest.fn(() => ({ + convert: jest.fn((s: unknown) => JSON.stringify(s)), + })), + } as unknown) as FieldFormatsStart; }); it('should request field stats every time the button is clicked', async () => { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx index 3536ad80538916..20505107be1220 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx @@ -7,48 +7,49 @@ import React, { useState } from 'react'; import DateMath from '@elastic/datemath'; import { + EuiButtonGroup, EuiFlexGroup, EuiFlexItem, - EuiProgress, - EuiPopover, - EuiLoadingSpinner, + EuiIconTip, EuiKeyboardAccessible, - EuiText, - EuiToolTip, - EuiButtonGroup, + EuiLoadingSpinner, + EuiPopover, EuiPopoverFooter, EuiPopoverTitle, - EuiIconTip, + EuiProgress, + EuiText, + EuiToolTip, } from '@elastic/eui'; +import { npStart } from 'ui/new_platform'; import { EUI_CHARTS_THEME_DARK, EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme'; import { - Chart, Axis, + BarSeries, + Chart, + DataSeriesColorsValues, getAxisId, getSpecId, - BarSeries, + niceTimeFormatter, Position, ScaleType, Settings, - DataSeriesColorsValues, TooltipType, - niceTimeFormatter, } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; import { Query, + KBN_FIELD_TYPES, + ES_FIELD_TYPES, esFilters, esQuery, IIndexPattern, } from '../../../../../../src/plugins/data/public'; -// @ts-ignore -import { fieldFormats } from '../../../../../../src/legacy/ui/public/registry/field_formats'; import { DraggedField } from './indexpattern'; import { DragDrop } from '../drag_drop'; import { DatasourceDataPanelProps, DataType } from '../types'; import { BucketedAggregation, FieldStatsResponse } from '../../common'; import { IndexPattern, IndexPatternField } from './types'; -import { LensFieldIcon, getColorForDataType } from './lens_field_icon'; +import { getColorForDataType, LensFieldIcon } from './lens_field_icon'; import { trackUiEvent } from '../lens_ui_telemetry'; export interface FieldItemProps { @@ -238,6 +239,7 @@ export function FieldItem(props: FieldItemProps) { } function FieldItemPopoverContents(props: State & FieldItemProps) { + const fieldFormats = npStart.plugins.data.fieldFormats; const { histogram, topValues, indexPattern, field, dateRange, core, sampledValues } = props; const IS_DARK_THEME = core.uiSettings.get('theme:darkMode'); @@ -289,7 +291,10 @@ function FieldItemPopoverContents(props: State & FieldItemProps) { formatter = { convert: (data: unknown) => JSON.stringify(data) }; } } else { - formatter = fieldFormats.getDefaultInstance(field.type, field.esTypes); + formatter = fieldFormats.getDefaultInstance( + field.type as KBN_FIELD_TYPES, + field.esTypes as ES_FIELD_TYPES[] + ); } const euiButtonColor = @@ -370,7 +375,7 @@ function FieldItemPopoverContents(props: State & FieldItemProps) { )}{' '} {fieldFormats - .getDefaultInstance('number', ['integer']) + .getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER]) .convert(props.totalDocuments)} {' '} {i18n.translate('xpack.lens.indexPattern.ofDocumentsLabel', { diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx index ba1ac461161b17..9220c3ec75fad6 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx +++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx @@ -9,7 +9,7 @@ import { LensMultiTable } from '../types'; import React from 'react'; import { shallow } from 'enzyme'; import { MetricConfig } from './types'; -import { FieldFormat } from 'ui/registry/field_formats'; +import { FieldFormat } from '../../../../../../src/plugins/data/public'; function sampleArgs() { const data: LensMultiTable = { diff --git a/x-pack/legacy/plugins/maps/public/index.js b/x-pack/legacy/plugins/maps/public/index.js index 49d8646c6a251d..964753f464d95e 100644 --- a/x-pack/legacy/plugins/maps/public/index.js +++ b/x-pack/legacy/plugins/maps/public/index.js @@ -10,7 +10,6 @@ import { wrapInI18nContext } from 'ui/i18n'; import { i18n } from '@kbn/i18n'; // import the uiExports that we want to "use" -import 'uiExports/fieldFormats'; import 'uiExports/inspectorViews'; import 'uiExports/search'; import 'uiExports/embeddableFactories'; diff --git a/x-pack/legacy/plugins/ml/public/app.js b/x-pack/legacy/plugins/ml/public/app.js index b88346035f3067..ead1af5f64e07f 100644 --- a/x-pack/legacy/plugins/ml/public/app.js +++ b/x-pack/legacy/plugins/ml/public/app.js @@ -5,8 +5,6 @@ */ -// import the uiExports that we want to "use" -import 'uiExports/fieldFormats'; import 'uiExports/savedObjectTypes'; import 'ui/autoload/all'; diff --git a/x-pack/legacy/plugins/ml/public/util/chart_utils.test.js b/x-pack/legacy/plugins/ml/public/util/chart_utils.test.js index 6d13f1bc668089..a229113826a2e9 100644 --- a/x-pack/legacy/plugins/ml/public/util/chart_utils.test.js +++ b/x-pack/legacy/plugins/ml/public/util/chart_utils.test.js @@ -6,12 +6,6 @@ import seriesConfig from '../explorer/explorer_charts/__mocks__/mock_series_config_filebeat'; -jest.mock('ui/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn(), - }, -})); - jest.mock('ui/timefilter', () => { const dateMath = require('@elastic/datemath'); let _time = undefined; diff --git a/x-pack/legacy/plugins/ml/public/util/time_buckets.js b/x-pack/legacy/plugins/ml/public/util/time_buckets.js index 6933ee6935e807..98cb677a4851af 100644 --- a/x-pack/legacy/plugins/ml/public/util/time_buckets.js +++ b/x-pack/legacy/plugins/ml/public/util/time_buckets.js @@ -9,10 +9,11 @@ import _ from 'lodash'; import moment from 'moment'; import dateMath from '@elastic/datemath'; import chrome from 'ui/chrome'; -import { fieldFormats } from 'ui/registry/field_formats'; +import { npStart } from 'ui/new_platform'; import { timeBucketsCalcAutoIntervalProvider } from './calc_auto_interval'; import { parseInterval } from '../../common/util/parse_interval'; +import { FIELD_FORMAT_IDS } from '../../../../../../src/plugins/data/public'; const unitsDesc = dateMath.unitsDesc; const largeMax = unitsDesc.indexOf('w'); // Multiple units of week or longer converted to days for ES intervals. @@ -316,7 +317,8 @@ TimeBuckets.prototype.getScaledDateFormat = function () { }; TimeBuckets.prototype.getScaledDateFormatter = function () { - const DateFieldFormat = fieldFormats.getType('date'); + const fieldFormats = npStart.plugins.data.fieldFormats; + const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); return new DateFieldFormat({ pattern: this.getScaledDateFormat() }, getConfig); From 014f095f5cbac36f7b4a9ece712151f9c727ae11 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Wed, 20 Nov 2019 08:53:04 -0500 Subject: [PATCH 07/29] [Docs] - adding defaultRoute setting docs (#50952) * adding defaultRoute setting docs * improving documentation * Apply suggestions from code review Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com> * address PR feedback Co-authored-by: Elastic Machine --- docs/management/advanced-options.asciidoc | 1 + docs/spaces/index.asciidoc | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 38fceeb47d6fd2..977a65f62202d2 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -46,6 +46,7 @@ adapt to the interval between measurements. Keys are http://en.wikipedia.org/wik `dateFormat:tz`:: The timezone that Kibana uses. The default value of `Browser` uses the timezone detected by the browser. `dateNanosFormat`:: The format to use for displaying https://momentjs.com/docs/#/displaying/format/[pretty formatted dates] of {ref}/date_nanos.html[Elasticsearch date_nanos type]. `defaultIndex`:: The index to access if no index is set. The default is `null`. +`defaultRoute`:: The default route when opening Kibana. Use this setting to route users to a specific dashboard, application, or saved object as they enter each space. `fields:popularLimit`:: The top N most popular fields to show. `filterEditor:suggestValues`:: Set this property to `false` to prevent the filter editor from suggesting values for fields. `filters:pinnedByDefault`:: Set this property to `true` to make filters have a global state (be pinned) by default. diff --git a/docs/spaces/index.asciidoc b/docs/spaces/index.asciidoc index fc858eb6d86ef6..69655aac521e7a 100644 --- a/docs/spaces/index.asciidoc +++ b/docs/spaces/index.asciidoc @@ -22,6 +22,7 @@ Kibana supports spaces in several ways. You can: * <> * <> * <> +* <> * <> [float] @@ -108,6 +109,13 @@ interface. {kib} also has beta <> and <> APIs if you want to automate this process. +[float] +[[spaces-default-route]] +=== Configure a Space-level landing page + +You can create a custom experience for users by configuring the {kib} landing page on a per-space basis. +The landing page can route users to a specific dashboard, application, or saved object as they enter each space. +To configure the landing page, use the `defaultRoute` setting in < Advanced settings>>. [float] [[spaces-delete-started]] From 102d28c99ce7109a6800a29f0f7ab822f76b7619 Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Wed, 20 Nov 2019 15:11:43 +0100 Subject: [PATCH 08/29] [SIEM] Fixes events viewer tests (#51032) * fixes events viewer tests * extracts 'header-panel-subtitle' value into a variable * fixes CI failure --- .../components/query_bar_top_row.tsx | 2 ++ .../search_bar/components/search_bar.tsx | 3 ++- .../events_viewer/events_viewer.spec.ts | 12 +++++----- .../components/autocomplete_field/index.tsx | 2 +- .../public/components/query_bar/index.tsx | 3 +++ .../public/components/search_bar/index.tsx | 3 +++ .../siem/public/components/subtitle/index.tsx | 23 ++++++++++++++----- .../components/timeline/query_bar/index.tsx | 1 + 8 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx index cd64b1ecf25492..2730f7665308f4 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx @@ -53,6 +53,7 @@ interface Props { onSubmit: (payload: { dateRange: TimeRange; query?: Query }) => void; onChange: (payload: { dateRange: TimeRange; query?: Query }) => void; onRefresh?: (payload: { dateRange: TimeRange }) => void; + dataTestSubj?: string; disableAutoFocus?: boolean; screenTitle?: string; indexPatterns?: Array; @@ -189,6 +190,7 @@ function QueryBarTopRowUI(props: Props) { onChange={onQueryChange} onSubmit={onInputSubmit} persistedLog={persistedLog} + dataTestSubj={props.dataTestSubj} /> ); diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx index e97c06ace15797..e29908bf537642 100644 --- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx +++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx @@ -64,7 +64,7 @@ export interface SearchBarOwnProps { isLoading?: boolean; customSubmitButton?: React.ReactNode; screenTitle?: string; - + dataTestSubj?: string; // Togglers showQueryBar?: boolean; showQueryInput?: boolean; @@ -415,6 +415,7 @@ class SearchBarUI extends Component { customSubmitButton={ this.props.customSubmitButton ? this.props.customSubmitButton : undefined } + dataTestSubj={this.props.dataTestSubj} /> ); } diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts index 400f82bf811886..57a1f318a7e31a 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts @@ -57,7 +57,7 @@ describe('Events Viewer', () => { .should('eq', 'Customize Columns'); }); - it.skip('closes the fields browser when the user clicks outside of it', () => { + it('closes the fields browser when the user clicks outside of it', () => { openEventsViewerFieldsBrowser(); clickOutsideFieldsBrowser(); @@ -81,7 +81,7 @@ describe('Events Viewer', () => { ); }); - it.skip('removes the message field from the timeline when the user un-checks the field', () => { + it('removes the message field from the timeline when the user un-checks the field', () => { const toggleField = 'message'; cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should('exist'); @@ -99,7 +99,7 @@ describe('Events Viewer', () => { ); }); - it.skip('filters the events by applying filter criteria from the search bar at the top of the page', () => { + it('filters the events by applying filter criteria from the search bar at the top of the page', () => { const filterInput = '4bf34c1c-eaa9-46de-8921-67a4ccc49829'; // this will never match real data cy.get(HEADER_SUBTITLE) @@ -119,7 +119,7 @@ describe('Events Viewer', () => { }); }); - it.skip('adds a field to the events viewer when the user clicks the checkbox', () => { + it('adds a field to the events viewer when the user clicks the checkbox', () => { const filterInput = 'host.geo.c'; const toggleField = 'host.geo.city_name'; @@ -158,7 +158,7 @@ describe('Events Viewer', () => { }); }); - it.skip('launches the inspect query modal when the inspect button is clicked', () => { + it('launches the inspect query modal when the inspect button is clicked', () => { // wait for data to load cy.get(HEADER_SUBTITLE) .invoke('text') @@ -171,7 +171,7 @@ describe('Events Viewer', () => { cy.get(INSPECT_MODAL, { timeout: DEFAULT_TIMEOUT }).should('exist'); }); - it.skip('resets all fields in the events viewer when `Reset Fields` is clicked', () => { + it('resets all fields in the events viewer when `Reset Fields` is clicked', () => { const filterInput = 'host.geo.c'; const toggleField = 'host.geo.city_name'; diff --git a/x-pack/legacy/plugins/siem/public/components/autocomplete_field/index.tsx b/x-pack/legacy/plugins/siem/public/components/autocomplete_field/index.tsx index 408743d2617971..b78f2b0d07d39e 100644 --- a/x-pack/legacy/plugins/siem/public/components/autocomplete_field/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/autocomplete_field/index.tsx @@ -307,7 +307,7 @@ const withUnfocused = (state: AutocompleteFieldState) => ({ isFocused: false, }); -export const FixedEuiFieldSearch: React.SFC & +export const FixedEuiFieldSearch: React.FC & EuiFieldSearchProps & { inputRef?: (element: HTMLInputElement | null) => void; onSearch: (value: string) => void; diff --git a/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx index c7e58532fc7e5b..8b5f3b0f4d4258 100644 --- a/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx @@ -20,6 +20,7 @@ import { SavedQueryTimeFilter } from '../../../../../../../src/legacy/core_plugi import { Storage } from '../../../../../../../src/plugins/kibana_utils/public'; export interface QueryBarComponentProps { + dataTestSubj?: string; dateRangeFrom?: string; dateRangeTo?: string; hideSavedQuery?: boolean; @@ -50,6 +51,7 @@ export const QueryBar = memo( refreshInterval, savedQuery, onSavedQuery, + dataTestSubj, }) => { const [draftQuery, setDraftQuery] = useState(filterQuery); @@ -139,6 +141,7 @@ export const QueryBar = memo( showQueryInput={true} showSaveQuery={true} timeHistory={new TimeHistory(new Storage(localStorage))} + dataTestSubj={dataTestSubj} {...searchBarProps} /> ); diff --git a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx index c16c3a33872d56..33fb2b9239a6a4 100644 --- a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx @@ -71,6 +71,7 @@ interface SiemSearchBarProps { id: InputsModelId; indexPattern: StaticIndexPattern; timelineId?: string; + dataTestSubj?: string; } const SearchBarContainer = styled.div` @@ -95,6 +96,7 @@ const SearchBarComponent = memo { const { timefilter } = npStart.plugins.data.query.timefilter; if (fromStr != null && toStr != null) { @@ -275,6 +277,7 @@ const SearchBarComponent = memo ); diff --git a/x-pack/legacy/plugins/siem/public/components/subtitle/index.tsx b/x-pack/legacy/plugins/siem/public/components/subtitle/index.tsx index 123e14d2391828..1b7e042e90dbf2 100644 --- a/x-pack/legacy/plugins/siem/public/components/subtitle/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/subtitle/index.tsx @@ -31,15 +31,26 @@ Wrapper.displayName = 'Wrapper'; interface SubtitleItemProps { children: string | React.ReactNode; + dataTestSubj?: string; } -const SubtitleItem = React.memo(({ children }) => { - if (typeof children === 'string') { - return

{children}

; - } else { - return
{children}
; +const SubtitleItem = React.memo( + ({ children, dataTestSubj = 'header-panel-subtitle' }) => { + if (typeof children === 'string') { + return ( +

+ {children} +

+ ); + } else { + return ( +
+ {children} +
+ ); + } } -}); +); SubtitleItem.displayName = 'SubtitleItem'; export interface SubtitleProps { diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx index 6d76c277711d7f..f24ee3155c9242 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx @@ -288,6 +288,7 @@ export const QueryBarTimeline = memo( refreshInterval={refreshInterval} savedQuery={savedQuery} onSavedQuery={onSavedQuery} + dataTestSubj={'timelineQueryInput'} /> ); } From ddb3c678dd38b8500e5cae8104b8f9683ee8e347 Mon Sep 17 00:00:00 2001 From: cachedout Date: Wed, 20 Nov 2019 15:16:43 +0000 Subject: [PATCH 09/29] Clarify that these auth settings are for sending data (#48437) * Clarify that these auth settings are for sending data * Apply review feedback --- docs/settings/monitoring-settings.asciidoc | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/settings/monitoring-settings.asciidoc b/docs/settings/monitoring-settings.asciidoc index 68dd9a8b3cefb8..2fc74d2ffee32b 100644 --- a/docs/settings/monitoring-settings.asciidoc +++ b/docs/settings/monitoring-settings.asciidoc @@ -45,14 +45,26 @@ production cluster as well as monitor data sent to a dedicated monitoring cluster. `xpack.monitoring.elasticsearch.username`:: -Specifies the user ID that {kib} uses for authentication when it retrieves data -from the monitoring cluster. If not set, {kib} uses the value of the -`elasticsearch.username` setting. +Specifies the username used by {kib} monitoring to establish a persistent connection +in {kib} to the {es} monitoring cluster and to verify licensing status on the {es} +monitoring cluster. + +Every other request performed by the Stack Monitoring UI to the monitoring {es} +cluster uses the authenticated user's credentials, which must be the same on +both the {es} monitoring cluster and the {es} production cluster. + +If not set, {kib} uses the value of the `elasticsearch.username` setting. `xpack.monitoring.elasticsearch.password`:: -Specifies the password that {kib} uses for authentication when it retrieves data -from the monitoring cluster. If not set, {kib} uses the value of the -`elasticsearch.password` setting. +Specifies the password used by {kib} monitoring to establish a persistent connection +in {kib} to the {es} monitoring cluster and to verify licensing status on the {es} +monitoring cluster. + +Every other request performed by the Stack Monitoring UI to the monitoring {es} +cluster uses the authenticated user's credentials, which must be the same on +both the {es} monitoring cluster and the {es} production cluster. + +If not set, {kib} uses the value of the `elasticsearch.password` setting. `telemetry.enabled`:: Set to `true` (default) to send cluster statistics to Elastic. Reporting your From 063a4f293520108fa96f23296d045901aa9b48f4 Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Wed, 20 Nov 2019 07:36:59 -0800 Subject: [PATCH 10/29] [APM][docs] Updates to documentation for 7.5 (#50988) --- docs/apm/advanced-queries.asciidoc | 2 +- docs/apm/agent-configuration.asciidoc | 29 ++++++++++++++++++++------ docs/apm/errors.asciidoc | 6 +++--- docs/apm/getting-started.asciidoc | 2 +- docs/apm/images/apm-metrics.png | Bin 487314 -> 141711 bytes docs/apm/images/jvm-metrics.png | Bin 0 -> 422737 bytes docs/apm/metrics.asciidoc | 14 ++++++++++--- docs/apm/services.asciidoc | 2 +- docs/apm/spans.asciidoc | 8 +++---- docs/apm/traces.asciidoc | 6 +++--- docs/apm/transactions.asciidoc | 6 ++---- 11 files changed, 49 insertions(+), 26 deletions(-) create mode 100644 docs/apm/images/jvm-metrics.png diff --git a/docs/apm/advanced-queries.asciidoc b/docs/apm/advanced-queries.asciidoc index 815e7317607851..1f064c1cad3fdc 100644 --- a/docs/apm/advanced-queries.asciidoc +++ b/docs/apm/advanced-queries.asciidoc @@ -10,7 +10,7 @@ so it's easy to share a specific query or view with others. In the screenshot below, you can begin to see some of the transaction fields available for filtering on: [role="screenshot"] -image::apm/images/apm-query-bar.png[Example of the Kibana Query bar in APM UI in Kibana] +image::apm/images/apm-query-bar.png[Example of the Kibana Query bar in APM app in Kibana] [float] ==== Example queries diff --git a/docs/apm/agent-configuration.asciidoc b/docs/apm/agent-configuration.asciidoc index 4d2ae5d01688cc..6f147d0e3223ac 100644 --- a/docs/apm/agent-configuration.asciidoc +++ b/docs/apm/agent-configuration.asciidoc @@ -2,18 +2,15 @@ [[agent-configuration]] === APM Agent configuration -beta[] APM Agent configuration allows you to fine-tune your agent configuration directly in Kibana. +APM Agent configuration allows you to fine-tune your agent configuration directly in Kibana. Best of all, changes are automatically propagated to your APM agents so there's no need to redeploy. -To get started, simply choose the service and environment you wish to configure. +To get started, simply choose the services and environments you wish to configure. +The APM app will let you know when your configurations have been applied by your agents. [role="screenshot"] image::apm/images/apm-agent-configuration.png[APM Agent configuration in Kibana] -IMPORTANT: As this feature is in Beta, a limited number of configuration settings are supported. -We recommend you watch your agent logs to confirm that configuration has been applied. -If you have feedback, please reach out in our https://discuss.elastic.co/c/apm[Discuss forum]. - [float] ==== Precedence @@ -34,6 +31,26 @@ Kibana communicates any changed settings to APM Server so that your agents only [float] ==== Supported configurations +[float] +===== `CAPTURE_BODY` + +added[7.5.0] Can be `"off"`, `"errors"`, `"transactions"`, or `"all"`. Defaults to `"off"`. + +For transactions that are HTTP requests, the Agent can optionally capture the request body, e.g., POST variables. +Remember, request bodies often contain sensitive values like passwords, credit card numbers, etc. +If your service handles sensitive data, enable this feature with care. +Turning on body capturing can also significantly increase the overhead the overhead of the Agent, +and the Elasticsearch index size. + +[float] +===== `TRANSACTION_MAX_SPANS` + +added[7.5.0] A number between `0` and `32000`. Defaults to `500`. + +Limit the number of spans that are recorded per transaction. +This is helpful in cases where a transaction creates a very high amount of spans, e.g., thousands of SQL queries. +Setting an upper limit will help prevent the Agent and the APM Server from being overloaded. + [float] ===== `TRANSACTION_SAMPLE_RATE` diff --git a/docs/apm/errors.asciidoc b/docs/apm/errors.asciidoc index e80438975cba09..689fa1fffa89ee 100644 --- a/docs/apm/errors.asciidoc +++ b/docs/apm/errors.asciidoc @@ -10,12 +10,12 @@ This makes it very easy to quickly see which errors are affecting your services, and to take actions to rectify them. [role="screenshot"] -image::apm/images/apm-errors-overview.png[Example view of the errors overview in the APM UI in Kibana] +image::apm/images/apm-errors-overview.png[Example view of the errors overview in the APM app in Kibana] Selecting an error group ID or error message brings you to the *Error group*. [role="screenshot"] -image::apm/images/apm-error-group.png[Example view of the error group page in the APM UI in Kibana] +image::apm/images/apm-error-group.png[Example view of the error group page in the APM app in Kibana] Here, you'll see the error message, culprit, and the number of occurrences over time. @@ -43,4 +43,4 @@ With Watcher, your team can set up reports within minutes. Watches are managed separately in the dedicated Watcher UI available in Advanced Settings. [role="screenshot"] -image::apm/images/apm-errors-watcher-assistant.png[Example view of the Watcher assistant for errors in APM UI in Kibana] \ No newline at end of file +image::apm/images/apm-errors-watcher-assistant.png[Example view of the Watcher assistant for errors in APM app in Kibana] \ No newline at end of file diff --git a/docs/apm/getting-started.asciidoc b/docs/apm/getting-started.asciidoc index 8f1265b73a8f42..4a391f1a496721 100644 --- a/docs/apm/getting-started.asciidoc +++ b/docs/apm/getting-started.asciidoc @@ -10,7 +10,7 @@ image::apm/images/apm-setup.png[Installation instructions on the APM page in Kib Index patterns tell Kibana which Elasticsearch indices you want to explore. -An APM index pattern is necessary for certain features in the APM UI, like the query bar. +An APM index pattern is necessary for certain features in the APM app, like the query bar. To set up the correct index pattern, simply click *Load Kibana objects* at the bottom of the Setup Instructions. diff --git a/docs/apm/images/apm-metrics.png b/docs/apm/images/apm-metrics.png index a75702ad570d09e77fe865a25b50ad9a137257da..6a9789b5a6ecd02e37b109ed262182d89182c0b3 100644 GIT binary patch literal 141711 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 LCFxvA{TKfSez9S+ literal 487314 zcmeFYXIN8Rw>FBRC?cRDBE2XeU3v!*Q94NPNbkLb8bq2(mEJ?|y@VzKM0&5GB!nIy zKgr@^V{d_jBl|5u`<{+^-?L18H96}*)x6+^ zcP!)i!J`cKWl8OWU&g4KD&A-Ce5QLB%E^#bu~G6hyy9+5eNKhP$L*`^ul@baI#t;R zOn0ZJ(5cQ%z-`7*z&q)XQHMeoT zLR6i2Yu}Xoj-wZd>9|9m$m#;7NMdyy1HERJ=<8}ZT@5TSRS z)7x#P$6pz7He%?BmczYnf6b+%NdZY3e#@qI9=!a*jG;|W=}Z?hI(e-H&3WRQtiw69 zGISw1zu(3vslxrVlZGf&_E|z!8TrYMev@V;aw@_KvZ1 z=OZs99oHA{#^!S~zL&|^qckZh`o8eUu?^nZ-;WKxEXx%C`^ zW}k%%RZ9!-$b8`m(EoZB65FfFFDbyU@a#ucb<)~E*jCrG@ZT^U!V1nuj50P}p8MV< zmyz_2kL73jq{ZHz|4z={*{*kSN|0egj*WhYX_^+f zf1lG)taczCBqW&&={@ke!@um5b7)fG?feP}nX1ladY}98;eL&KDEqgi->*%da(~$f zPFt4p!lA*fq<8jOgft>l!2$CmG$bPTiSeQLGlKOeelyloZkYt`XOX=BIy#wtZZXs- zZhrhrdjCx?agz&^;{$_z?$=K!i9@Sfvl4Ur40Nxcu$!W#@Cv)_SB_8PP2b^X3jueE zcglA72XnSJlc?2@slqVr;k`lVzOb>o9u9iUSl=|f+JDAoTgda7XfQwSGtZ}X9h{%S z61==f#nsAlvaRt;{9Ngy&(gfaloTzP*Bl8Q#T{v<-0uEjSi?MaE>N)Q`#qa;`xzzV zJcPX>Skm_8K<5yg7-tRe?kd%%OT(Y`(Rx#x2V>=}`%fPd5z$=eli`9kuflP%B(C+5 z&UYY05jaBX9ooGQrbG<9>2X*`16AVjt8fI`A5X8`YSX$!cPBW=g^uWDAm3|JPu)Av z+J}R8+}hu&;<2_rsCuRmr1Xhk<`xjoSBh8YPE-)0-P;-802i>hwTUo<#ko!P75=SQvV zJy!zn&qs7zKZsw2j;rEMQq_O>kPCT58TmeLl*L*=1efEz!kC3Msb1Lb+qBV@4euk0 zxo;BE81BzDCW?a(+`9a@iJpb!o9QM$ObbgeOVFX7{#yU*=KR6*w_{VZ3&U``ZX=sP z$44)o;U25S!@Ybjeh9A9FO_BOy?b7?*C}t9lOG%0zrMq1!a$$)I!^U{(M$UmRCMWI zRMZ8R2!F_$KcW6Av1gRZknR!r?yaYS8a zUATL^d&;De&xdIS{aEqd$E)r&!3J+DUZP*p(i<~L(i5w?vv@uYkf)M)lOm(5JS%UL zZ;k#;yMD++n?4U0NNN zog_4SV`j6;qhRYPN@Ht#qN!-2RAHsypqpTD61ob-z!8=L~>HL^3#}5nX>b73NASK z4V?wy54?oEgqr8e)%J<2!zO3lzicW_L>3e(`hIvGasPP-?MDey^w)XIqLf;OTznfa=iHUj|w9n${lZXqLs5 zNwD#jzG4fRvMlv1y=8X~WsZ7+f={2?7YRTFbOr3}=j<=+IUIWChpQc`S{*)AAJ&u1 zme-0poK7!vNK9S(Vk|L*MBPLNVWwetVJ%VaJ)e5WqdcOtGrlTAl$(?((>aB6hmD3A zkQB&p&Z6*!@EMCBg&x^ovTZ+Ne|WrbY8*G1tq7?gtRQ~R{h=#@m3&HU>)d*NY%^Co zN<#diHZ4g%b6%@KboXL+1*QPgha39{`R<9^idFcGi@y*<`hvY6&sTWf3t6rtrx`u0 z+&4n_)_eOOoa`rh3;LX%&0LtDOwvqB zc&m8Z54}XDP0F0Nr>hMErvrbs4+UmOm1RX_(FTbGm4ET>@aQ0xwtstve*SG{RmP0) zw&6B1+cCRl6gS&R_&U8Q-ONNs$6Uu-$F~vaghGr>&ac|i8L0!b}Tb2dkGdM`t7o! z)dLR)d<8weLETvnKEvlHpifP5ewq>A$8yZ# zq~58fo$skkCGN8O`_QJqX1OlWUCl@S0(^8Ww-h(6yp_4l-(-Jq%tEC8y&yfqR)pVa zYsp4r!fWEh;t`J;ucxKoYS;dj*HsE^aBfgSBCIXyM)47Y&Wnx5cn`GkLFRWY%lmy& zsgqkpT0T5wFL`?WU3l4cKRmrCT}jxv|6Q&-%xO6WG>WKBFk}D#u+s=T4y1Qjt!cm+Es39rZIu%l<)s86TP09D>?( zD~^=oJfWPk!r3$X>us>GmfN#o@7GDRGF|2=w=+-pg)m7l)ZQLu4k3`@}@!7Re> zp_ztp0K*I6ZDitmX!lS{N(41+Zd=ra2Zp{>nm>$?m`n1lxSEgop7s9Nwb{5?Yfo)7pkB$Y z#m#j2TPZVhy1gW+|JI<>DMHXJy%HX3^Q zE)IWb32s?Cbw_J12(}oXauo*b>>llkUD9oLgoJ$~M!WB~WQxa1Ud$L?Bwsfkd|QjV zD5Oy#K7My(aA7u13m?fF!Sflop2XCiG_4$71%zCBWILG}pAyW5cO)qor~I6|_8CNh zug|VAP6vpGKRE)d4jg-Y5vPTcc|b3o*M~1Q&8CF5X~3@GE}G zAVzulJm(!W;x0kE_JNZ`N%p!xrc*u3uL3A06pOcUCHG{+hIyyQrS941dwRi9Tt2p*QaRzI5cV`hUE&u?)3E<^) za<$^(78Vxfddt%SY*Dd4XGK(Pye#Z>-q|=< zIJ#l$kl+#G;}QF(!2jpc|5W*Z71jNpqTGVK|F5F|*QNg|D#rDv3;$P_{xe?xoW%~9 z!~-#|{~mma2O45F2H5$avU#VXf&IPxXL4|Ga80paum1CkJ;t4tbX2^sm3s4oRpz_eJNvH;&)$gK9#8x7UFQ*L)hFEi znX2p@iH{%Ii$2Q|w*qee^mR+=(B&a=!-A|^k<0jf|^G7>QkKW+?%davVDKn%5|9?vVcA88GDSDz(*urk+o>o#lc9F;AsffQ_Zpc_zMohJe{{sB{3J3B4 zoxbc?-nY`vM3u^BE7$uY&2Ifm%lyZd-;&6-Ww}^GS9B}Wr~2iqGnK?CqXYlFnLiRr zx-;CL<>KCVTg}wjt}m7srF+g!OdB0X46R6HOcU&DzVcnwf$h7uj%*akvc!pk40L}6 z^KtlQnny<{LJ!?|{`KY(xJQugA+^FjoAYvgOe?nDerXS7(N3OdADK|xcEjKsMK%1n zmRZaKVn3UYVw_s-&*8=g)ZG2o!?YMdDunvdEkkSnvdLCM$c$E2jjV!x1z*yi7Qv|S z?AzBt2Ga%JybK|F=4j9(ZuH!R!N<5Nmr$|$%HRL3nFN1WEPFsfX0NS&0Qb`M%H#2x z?Ce=t4U{2RVI%(_lN#exUiGzMzT?919Uc+0}?R$k35(hnqnU%kWMve>^t9BcybGaE( zY6tz>p`(jo4dj)urqW~w#XpD1GaRnVl77~{ch%$?N4=FJ&-jyK+$lYZ0NG#Nxbox& zM=9cDu*UVE_v5#y@9}~Z;G?71UprfyU75K-JMaJD#PBOLqE?eVaVdEzGe$5#sAs{T6zVraK-E$! zw;d|tFFCkWw9E38pY7tyjV5Qgs2y_Uo=}T>8faC_GW^i3>Aj20xULx}LM{CyXKVNC z)d?8RtiC;X6LE~({=5D8P1c`A1|kW-6}MJ&ogj7qoA$Fz&W3@tDK3I({tf{`Y85}% z?_AEXY=8aD^SvwlixA&Va&o?5x1GCcXPKy94skjAo#OQP6eN7gW5J4r!!0K?@k;uh z3Jb8=e0RkTcM-dF$)Rr~%;qc*urw3LQS^L`I0Wk@s*R|@! zLrO|{Z?661luNr1H!lNjYFVv8rd{7<^AG#w&TH}+^}%IQm_Z+_Osdx%nhra2dL=rm`-;>R*3WX4aT`{>!kBJxM#p-&Ms=#7v47gs2jXVGRkC` z2W;0B_9Y2c!T@N)?DX*yZ?kF98er#p;~SvA&siexz^@z`ge>Sdbc|cWUy(EUcqTL z7%_^RLpD3}^*@Znn?*}a0wi<4bbq|-rZ571E`WD)tREhD6jT;T6o450+Ze*YNAGW>Y%KsGTH=c`u zs}-pRzQdRoP%8lSn0Sq%xjaB@+REgTu5T=xe^wbO=pm(bxH!LcWQ6Ten1yS6RbuTw3cJbfJPyk5%};tc%T=9$R2w~mA`%C} zD+dogt`4Mqcu%a*{IrS0d=kecfq?BiO5Ega^E?>M7qA>;(44!~MJ5Yv5xKbA1(RB# znynoO9>cvl!QegA(b*eA9{eb_-sa;9>JE#dikm`#<)$}ei!~~e-M+^lR5Ha_q9yq? zr_11|^!88Jfx0Tq)QT`4KHA;?-{<)LI z9u}5u<|-9j<%b<{;j(LV!^pTS7uH)U)Si2b^t`9W@fj_iDg7uc3#~adA+Sj9?yiRn z_%zx$r8H#z>E=T$X|lwMN6G<=uMKE~7kQ7EnuRvtpo#iswogSilA_qRpzWsGfX1sR zno7(|m1bi>)3L2Q2*F?b<*!`I{a|T2Skv$)XxY+Y+MIhG{Sqe=dzohBDLT4Rr|gQ~ ze7i!~pmi=E!rH9|_uAwd@ax1o8Ojh%vgTj0VahAREP$>;{ZFYM6@*mbMKZ&=Rh1nj z>4ab@@#vsT2o0H$bo^z|Kh5P{hMJ z;Z+KWxgxuD**#lE*e&Uv+0$^&GWJtI>yV%kc1fFt)Qlf?a6+y+o&hl{T;5Chf|s7& zU7sf*WJ*a@C?wzIFuVw&IoY1nUK?rC`l{s$ z^c&2|@^{a@*qLb>h|;c;rN?CIAag%N&l--6eFXE=X(=1E0CUYp5|vE9laUhcQ43BL z)S7?WBaploMMg$um3brA_avnYeX%mQuU9U@%E~i_8XZ~46vvpOA^vJ*){n=&4`=h8 zx`aF+jW;Nu@Gepcz^@(95af!H1R>kZ5Jo=;Oza1L1zCz!43= z_ChW6`l3*^<8~}BJ~Q%g6N^!)zQTV_4S)M`_mKI5%Ad^HRw{bJ+w1pWwdp#B&u)67 zol^>W3_SKZ-G(z`k*~nWE2kXfLxDE;Yp2;}rSDHUUkbYhpIq%w3HpF`yEUi0R`%`9qcflUzNh)x3+isu)A-TtOxa4hOGtpR|k}FB=#G55+Y{ z{XC@|E)1Ke{O}$;W4CTwiM@c__fWj}tJtVLh2zn#fz|7b3qt*w?cZ+dO#N8!SZfF~ zS&>f|j?0cdIn?AP5(ssiFbj>OVrEmK*9G+IoL>Dr(%zhIO&YTBgS>{s6gm=X55#1- zEDl*Oo~4Re-sH2Q$H^9sXOA5~fw ze?w|3ZCNx@e$;DB@Foth?)OQFX6H1^Z*QOMV4z0Qp>gXQceK1YgNZJ4Z?eXy&b^H5 zxt4>KkpcS+_vM)m314RGvRfR4_BNCfXOCITZ^wMAmy0XxE19x$C>jv%9?051(5zpkRyCgR_ig?O z!)(kMa}7Ku&0m1?g7y&!+|iPD4dMbtg@cAws)<+ENh9@RgdU1-9K$cGFKK<1{VO_d zM^OAmjR6|PIbWach*drl6nI2E0zYcJOY6^R47_UPk}bw~I2!1qh(sYc2GU5MqWliJ*f<%*O<; zB`7|XsiRnJ#>xVXi}a)2BqttA)BG?F(07bHUdYg5C`hien>RSpy(@q`ES6fqG`q(Z zbG6amlNa9?njZ7e4t8tnOZcf|e16;Y(gHiy6l3(An&gHn4LY1! zYI6>Kufsrnu^^y_z$~B@VOQCtrdMxmj?DHgi{ zu#Q{6i1^i+8D!)$Q1GhmNYESM2LYfLP=F!{Bv_DNX|ku%?JJv2#!bhUZj1i-L;xan zsim-8!Mo8a;CvTDds|S!RBA;<5~F66a@|~J;BjHhU8D+0pM1Tvq)a_8=W_UhppcN3 zTX{WTuevsM@hbN&dM>Lb)E6aaZE~vJQdaU%ARyp5uVd`x*@PN`n_wNn7;x44_Tnh~ z#wj(lkpCU^%ojuBkB2WFUJ;xI5yR}Hj{abZxWzCg+voM9$=6e76&gvMJFWtkD79&p>2@f)u1=lNI-pz591%L0# z`~69sQQ#YE;&3(j70oU_`EJ(!N0Mi$^Q=IIB%Zj6^+g~HgShsW?#>=D2V8%ORZ8x> z2KF1@d_`}Qg8D7j55C3N_(lqzPG{ySwIX~dkvP(JIUU7){>=o^4kB47RmaGm`|Lky zxoK{OCRZ86Wg+LQ-5MT}?+3%RM}qJ1YZMKY{sT83WD3{FD1`9HY|pUxkF|qC@$2Ex zHLa%A90E0wVEgZIQ|V6S7?BwqJ#sy^ccMzTd00F+RguW0J;$Y5Lg_0B)AZb(Z!*h09)Ht!eWd;?^@Am}Co5M||j+*-6rFdAGae7hV~y&JAy%|0IQc3!*W+ z^1Iy}{Bx`85^yiFRHNxlBG=7)X26!4id?-dep`TmJ?v%q9LyFI&#wE{GX-51WVvfg z@Qg206fI3I?DGXqyDbycG$JN0#o5&O9WMT9^tCbL%BQQ0to;gjOTLNO;VIt)r%+pL z`5oHl=0Lk?ww!=(%Bt#1W62QuB=Hg-eNiZr`Z#sU=Kzx8(XvmGcB)htS2YxGtfo<2s?~+$-nClM*Yubp}&ajk{ zR%sQ(25qSo4$+hTlMGD0b0AEu%-IOZqkaUjgyW^W-n@(8K1NN&QdU%Qcpt8wI4Iak z1%2)OAjud;L<@e#5jiBI$(r_{Z+5jo@;b4>imU3@@SmWosOMs)zfUAnG`<8S^MEXN znuAjA+j7@C+&MjO0Zz_gG3euyv)`F0w+W*-$!qr#8sY;2JmzQMN%?MC4uiZxQbOSd z$1$Dn&sfYe&so)%&O~(^BqUx#=QJp^hzo7jwuvRr$17~Dn|JHA|F9|+n5c|{VPD#Q zEJ-r!uNMjKIEIRZrS!Lh`k6ug4p0w>?I%54-+=4-x0WMUy;?q+pdZq{g~eNiWQS5* z2Uq6=YZF|MYG~<{SA7opJb^X2A9~Zbj0V<`R(V*p+Epf|=_9N$n+l7(Q;%$VJUQ~e z<4f$q+l&*h4_f>zZ(mZ#LNU}LMPaLb83TZyhv)7B*8JOv-D=2g#7$XEpqF?UIP|zO zA#sR8#Be7$PSL{=Nj}+Dk$BZ1#Z97j?X-jEeH=Lp>F?NGtQ@X3$psyS#PKWYuN;)9 zRVcEY52UM?5;?)@W;2V-+zS_?@!(T(k^~}c5Da4EM2Jv>cnkB{a5@RgLd7u` z{=nnW`-{$v?ZireHhYMA#;Zc83cKM%bM40gQ#kiu@t ztQ@#q#}r8^8_8DEH3E&cxv1?dAzMo3=l3aLJ4EL zBh_d#PYs_F{1p-E+>QSyg1f)0K@N26e}}0Q62(-OdAAx)8ho(Tt6B*#x+rx=EwD)) zuTDmQVB9GJ)?!Q93u+D06RQ=H6Whe6!HUsY`#0~EVvdc09DlfvQt$mK1L?aGWM8_` zLzv&eq-6R}2rJe{$Y`rFj!z79FRxTQF=rof8I$%2?3H7c|z!Ov<+$e45;+_wg5&1caA4ri}* zEYt{rwyGb~M5(rj@@-?>op0{>ckrKv40`#4+0Qq%TjX%zv$Y_|2sUD)SotVmUZPo6 zpIYB?mq5QcXiJl`=%t>`tYLz-bU-vw08GoqVs>X7guZE_hQHS1+SfzxS|o)@nv4zv@i+o zuJHbL3Ha5Qe2Ohv!F^%fHu`C!)Lky!oJK=WNp<+*f|Y18S-I=wTpD^-v;5&gg_4_9 zk`PD*o@Jt0ey|M`a9QW&_Zw87R>MS4k0Ho3rbi&ad)9UVZUiJz6(&g;Nz!3N1D~^3 zwvpBD#m_fydapc_w3ISWm#mo1F2W}T0=L??R;$w*Qd#@r9E=GCP*k3&SgSP*kX3DT zmakU=<~|iXmz~ z<(<~+vqPQ~Yyfh?gN3cL8cda|068;|*Yt3hL6d9$*^k1YlD2CwEc9E0J)AT8#CJ3l z1-~aExiPv}qZOrMcW8QzH5_9<5#zZ9*EBAn%l&(``Ks9yBRXvX6v?c=lyLw{J!m-$ z5#Ztid*cNn2t`@9cTCN1TE%Do=!Q(Y6`k7?C5M&>TE*O4S(9HJ@6bEwHyr(VNF$;q zalPu+a=pFEocBI*3*z7W2uq1P_?7#f=tsKn<&9{v&Zv&`2EQGs;s}0q?YkN^ynoaD zC93kYC?T!B|0kFwjy8$S&cLzFx3VR>2@Nqy6P~)1T|K%y+d?_z0}vnb)w&K>3latU zIRtyO4Z%Tse@A>FBmPNK#Bk^X;%8=tc>aN|Bp?SpEU)a|+-jG4yF>Z&c|Ey$zU$ie zlR6(7aZm;7#2Kte&IfF?5N)czXGmZoP_j?Z zAk?!h8iyxd)+t*4q@f-5U4+c%=in>*kn>3ZFM}^zMIht03E#PaCNifU!Odm#V-1!g zr*~!HJvN_JOFuxHFI?M3i%&M4GJ7Cb_v~M(v7O`Dsiex+vfUV(b>`~rYouY_u8AX| z$345t^r)4tgp6kMNi?7Sz*5b|IhKx>*L*yUIa zB_kze)HZS{uJ@oVTpBIY%_X5~0CqBwV}84NwzSypej+izvR={U>t#}k)KJv=l%F%g zs%o#y=(GavyEY7S#DDezs>1r zHiF_Nf*P!!r0lvcgPdR6tc1Lf42_(}V40DY{+*J3*+#*(}&I#G6fFgVl+B-UI)OJOZ zO`d~yq)xXN(ySYLu~~O4x#QI4=78NJovfY^bnI%5z)>0&`|WRT{xCy}W-B{i^}0l7 z0H1+QEx0Sgn{C`v)d)UB!`zcJJ7vV`LTl;`HiB8Mlt?769F8R`?7GQX4cs+cJDFFO zya@pT>4Wg1tCFVc zcZh8(DmrN%NqYg=>n`!#R+;?#}6OdTbOBH2(=neac8#8~Ba zkDO%t;mjlU%Pk@b!RG8Jd`_UlmvGSBi+a;StzXjyfu= zFV*~y)k*dyv#MK`i?N1bmdK{w@6Xz1fo!t%fG!XNj(6NLt)jMPEq-kT;{S^1_?4*K zs}4$#s8vl<=N47jHE`AMnU*4+cmpTkYBf3a5b&=k`8dQWN^0*RQ#vzU?q6?Uv|~z{ zNBFG0?q2?0SLylU*&TwF7OuYHaf4hR&9MjYIoQag|IO}-`+27dB%WB}`WGH~{dlF> zqS%Q2Y)${~>L6U=!*WrObcWkd+GN9g#_I+x;9WS zFff?B#O{f{wSL*NoQAaV7HwB1l@4>0eXcfB;Ut69;2Y6eDRjKO&x!(moH^2=rY8D_>77!OiY) zO75xBo}0*BwlQU4D$4yM`5Ln`4g6e4Su|^c(TCJtRH(m$Z@c&Zz_(Y}`cz*AAGf4> zBuaYP-_N%4OVZ09Ns@Ew(Oz>W(yMiU%5J18Fw73Mc`yeMO zo5b9G8W+L;P8+N!R}9#hat*;(#S>s&oLTP1%aK~aWwM?>)fm-c+p+C3big8s{$7{3 z9oGR%LYY!pUuwREI*;h>Ikz|8N&DGC2-d;KgNwEHz#y>v_7`Hw)4R9fQ~Ea-RtaK< zml01hwAlJeYDMEyb&mC{7SFMCAT5`Hxpq&=sHY>ziMabl)e((Qzhh~DA%_h-r+NZ@ zO2ck1>^C@3V}TM-&p3Ijo&nCSbaExQ5Ib%Por6so9_ulS2~TB0{eOyRG*!ix;~7@J z)jh3v%H_*XOGQh#ZOgd(du}ob5o6JI!+4iqHSV#r&%EQV)rIqEOP*`jffO-x<;cq+ znsCd8wenfrz%Y`x=~3e$d-`G}rq<%#gQYIRTbSS9NNP6HZu$ff*RS*&98`|1k$%cy zpAH9R3(=@)r+60T0UN*kG&1QZGTbl=q&%RrN1yyvWhUj!{2? zeXFm-i^T5sfl@12E0wEU2wF|+Ld+@z*pBNo6|8I4Y$2w`m!?~Gzz^02`t)m!st3Ml z^3e!h%XtHa4d$6A$pA8|@pmE>Qk~J5T4Q3L)Zbsa|C483E>(!8zS0?`b057m^uGMJ zpH)v9=9Yek&SdO=PQ>)ttOlw9KF6Cckk`~h+-3L_gKB~^|`_%2Yz~F}bNzcvQ zwX+LKx@LtppT=%YaUNrm3UH&9Y_A{~-#=2Eb4|XeNI3f+X!M6~hgw0BCzos%l5AKh zw0qTc3Pyl3HORiT78XJ>yI!5n?%nC~{(LpAf;wOIP_8iFx1plemo4Yab2q?4LzLHX zmW0|xvj_{1cv?_51=IGF)4Ny`enG9Oy<%*p_It5j^$h$wDF=I3IH_FCh3ThJooJB2 zl@evn#OMZz8D7fwJl(Z=K|~xnK*u%=^x8Iy@Lfx1jNUCRwvK}Qa)VmUD4OuN2l)gF zQQNu`JQ_7UG!m}wm?Xr9w3p6U)I+q`Qm;>Xj3EyowyFFgB7N0$spzT?zWGAfoe4@a z_Pu^?4s6Q`ohoJtZ@ZDJ>#qW54ESyu#->S|x)Ggg_AbEBc`PJB=BjS_aP(u` zw(xwt1E+_r;ihOC=l`Kt5d!5BMvcz5)UR5T;gHqBvnmh0pl+j~n@>_JXvmEe&F(D1 zs8S1+ad!5~+i%(28?__ssec0z&sRb{^AxVeQmX{hB^}BGDZGWX$s3p?&`<*+VU8Y~ zfB%uo+za!jowFn7wJoxqT8ppSSr^q5Umv18M__BT4iWIaYyhqH zIHX;Hh1pU#?5VH}bVXM6b=+ntnIF3X$Y*-oasZ@~3K3DtaWw}NN&84*m+*hdF^Em< zM%ATDJLY!9G4{`OaUDqB6CV)}iAr_*c^~#}nD_@#XRd;=19dZ9k<_D9ujjDi}6X_@zyKL}WV-z@*id>O(efAmt z8(_pVVH|!Mu$t|g_x7Bp2CA`0gB6vC=Rt!ESARa$Sn~)|iz~G*V}6eLU0VZ`E{kXX zXuuaQwA4ptJ~T%t@KD6OU0RAuRA)vFErn)mDrpMD73s0*nuUm?31AsH$16S2^HuxA zlD2zi%!q2e$69Qi1$Ey1v`0Uc^9=!?g=UV00?o_qOGzE;n?N?msB#i)o!z>hSTzF7 zSvBllo!OA+0oF4P&nHJOu#hEV7k?pR#3Yw;OFo>^sS1N3reVVujx6?Z9w2?+157klc=)?ODi?cEyECX8J+R zPG%zZ{p3SQY?vuo$uU?71E%J2BNVSH_Oc)Wgq8nTnku9zWU zSkTI+p33jAniS{^{tqVKpy^jF-i^biR&sa!RViR&{b;6w$}@Edy&Dih;8eb%$eLWO zwIF^V4%#Z*nTVC6wce*7d(BwG1vwP3b2mpD%{BmY?fEU50Lh=CCbpEHGs=`|dT2=l z|19!9*$q5${&XQ5*r#vbAJFhk@6G!jN>p1C1KJc=wb{{!ZeJp>dK3?5W>xJxXZkVu zekTaYjmqdBq#cii(U}Nrj&oT2-b+suO<$U5SbP-AVoO^*r#&2O7#a!er}4xl5DWU< zQ18Od{Kgu1taf`m+wgqr=SsmwS083Rtwu&xCKW_h)Xv{F<|`tzVWn%q#;z3dqh~EQ zSL~H-#}Miq<4TM<>^E}fV5rx5?A+V z=w=&Oc+rUYM7S(DiQ&d{-oomTE>cFHoi&ZdxS#{~B{fE0w}oD)Pkb4=s)Lmpbw*LQ znD_Rcy)FT24`TLsXIp(M@00?|PqPt(b6cq+NRD+kikWA?>-s^%y<&L!f7<|;b9ZU& zY6{D~KUyng1$OJpq;s?{QgkICYc$83gk0>^60xCjx)6&#*!~ArrI><_ zxo;(l*(IV-Nx5t^&|PtDyK3=7Cx%9@++1tbnB#i~oS=Z1j072Dj%QZ{wP3J=o_w2x z`1ZlUTEM^#z@v76v_C0Mx3VpLks|T(td{-qh+w|3n{+DwW9NmZuH*}>o-khauvNP% z>n0$Y&t43h!I@Vn72>+^3q*(A^?bqgcfeiwAK?DAi2NJmDy$bP9Ed{}{6-qqMXUSk zBpIi1YhvZaMd5v5QZ_BQ!ub_mxxgL|)WSfNC~(`kSi8Zq#wK)|M+3%~`^2)E)9xA_`G@jaHiSI=?{;s_D^vv!G>ZgJw9^O0ci()c|hjSw8Z$ zJ?%|W4^#0#Ih1hGiulchntdSJTN?r5q-6z_S{=E3Rr z01|OvTQN_m)OJykY_SDvs%^5?e@tbD+F*V0rsev^1lp7R(5u4m0YE#V#b^8#JVb4+Dro{*ysSyA?TA+Rd799!?r3d+~GwRv_ zXIz%fN!J|JLxlT-5eQJ5s>IbYrDyW}3a{Q>HSq2r4ecJP*+ zXp;9)zIs^9Vb)N{XuZ95slsmk6Yd90;}g9?2_P-8grg=_a?q!nfOQcU(m{G26z3P4 z#-A!1VK*&r0`^aSg;&laLdcQph!kOfJ3rs2gKr=8~@+5{GfD3Vyz^(@=O zC;VsG|I(>2{G*!bMp5#S4OQ4EOXK#;@x6xa1RCX#OB0e4b9XJrVzp!3ogX3_de*sR zC_%oKIq2uijp_5Nvyd})VAa5$yM8EMq`p?G9$xF~Idtgs_B`8FqTfyfM=@!+wb*XI zh@6L9l0Q~7V}nn@wc%Vy#Y1Y2s~^P>!l+XGL=BsBQ|o^@SBqCnN8zPtin6jBJ&PNG zBzn{S)`s|v1{3q|C26GXtrFB&?%+|<_?ZrFZq+KsjG?eei8>nYK*RFntvVvXhL|}f z9TXp6Z#Qb*F_B`bRHQ}i^7?dZ$o29JAFIhMGUxADud6#}dXA~a@3ozf|5>ibS0gou zg}4LL4x+1wDb#A~Iqm#j-O1Qihn~!gOAm*nqEI zGlu_X$&lgk47EHVqjg!2iobVav0jS-nM0|o6yqk)$;yhq!?!A{+B4OH^@LL(!MEOq ze;S*$oc+{jgnrA5)p}Vaz@dY|Icbfo5A7B;f(qyO@?gu|l-n*84A;jEYmlun3ISR{ z)6YdcOD{g;jkJ$Ve`r9AZCWBOr#^%6;;2FYL>%iFy8NMm^DN|a|CpYX-aIzY1gl_P5ckV4S2foJ_TH_2_kr>u8i(P zdQdT!l@45Zx8&$)_Qf$Lm0de!_|>1?JGYnxH4lW&@=s=_KC|B~Tr6$72tP7hbhaD7{;8*jm*EPmq01+==X)JAExr#)s^YiE<|t}gYDt#?g@2wB3sjM zu&n3t+k1pGOQjp7D9sWBI$k57GMPUIHpcMO+3V=xvHvY(jEJIkOvDDX3D_J=U$i7g zg7=~1!49Q>`)59f@zI7|2`x5UL0hlZ^X=6*3>syM$>X;!3-YVkbMtoZl|=}r@j23I z8+(M<^K=|UOPniCm+L#7Zk|gT3qh|-Z~G2Kt8591QTt5qxpd+|=SQ|H2Y^YlwaANK zeHSBg68_k9bVix8TE7=9L zi>TBP&K?i2=|hE4A%oLxnp1m13Sye;M#5{GBBh|t$4tLdH89ur)I*Mj&RFv@M8Q8w zZGYb|&>KjZwLSv~spBT@ey-g;WwrL(*!!s43Tz>KZZ|4auEf@=jFsJR8Kg~mK@I$y ztUv3aN8o&P=f5YongtnkI1O3f`-po*6H;s`177iCBVD}DAn)rVGC);-{VvHp0{tyu zE3&ZQCp$J9v9i0{V1SKdy&ExxvEupy2v2e4k;+?3d2`|b&zOM{t$mL_BtKJC^JoK& zeKuAb?eLs;29gK%7N&Z8$7P#LHp9)4iL|!^yQ$z&<}`*r4P;w^rVw%xgUL- zNMv|zdt8|qbmV?PM*teu%b0TUQJnEY5A=1CQU*#=m*eZU9V#*DBdssA_KAtRGJKn8 z22>}VlP?l8Hvy3ESNm)7s+C~+`K43(cUw(ym}0U84E~a5+I+hS zDk2%-^<5L^v?Oz*tu3Nbxcm0FZ`k#cBsJ`->gHX=!bd<$@S7Uv7CgHF=k7XJo;ksr z9%5ekn;i;HhB!2qYCp_!(X14y>xS%okMu4eD2;c0_6*7Cv4XZPBLndfa%KX6wYx zt@hZ^nUk3ytY&+XRm*uJ4h?B9^DzsVIyZPw@@;@dm^tQn$&2YsTkjKJejrl_0kaiD zyDkk-*hpG&19_euZQz|lVl7N@@P`|!KZ7jon~LA9-krtG#RV`Du^;G{He?TUN>vJP zUgclm{B|4q&^9H-_5L%@^(o|DO9Yg* zR`Kws#dnKEpa?o%I^wmrtjB1LVdz4R+E_J3%!l;4*j58oP?f@Gmhg>^z8>l4>6Our zdAP;rXtP_s&Ksk~j9Yx*f~m90H+CuU^5>9e>lZu@rGt7NBkD4vytD}gfu1hQ&g_@j zeOAwP8JT8g4!KNgs5zmPgY}2R#*;rzUYYAB>b4-a8;^ZgD>}G8vE;A9IUzC=YV!WQ z!q8rsBA$`qa?P76xyS<-u*Ejq3-VakT?asL+cwbGz1s-}+BicA)6(~dO5Kc|>gM+# zON5Fwh`U>tkq=qbet0EE#y0_YYrub><$1LMJ(^X{EZ+%5p;RgW18_m+C?b21Qr6<51th#{7FZ9h2@@Z=Z$aq9x}gvkqoLAt#@u3Jm;YuAM577 z7VRa~@Tv?&3#(fxY#pe%j6`qXBso8im2o};nrHC<3@kb$!p3a4GOF0Q=*HqNNIxw< zW+*wo_8Po+vncRTaLOO{^Sk4`Ca55sl+v?b|j)3Oyz{*RkKd+&#nA4bQap++Nac; zp8WjaEu{nW;)daJJy49N(eU_|H1Q^O%ljTq<1~XzpxFXlR8M-;lI9H^?f^2 zJm?Cp^%-r$pd*bx&r8Vno7r-GnoHC0;gU8$>tlC-et5_f$tp3j78(=nk|yk)M&x;g z-7wpk3|T@C^G7`sYg63zfNuxLmuXpvX#1!}PFCE8Q%vp)53Ng^L-FYplD9iZkH*%I zEu+2%ry3yDIOdmlfY1E#$>Kx7>#QbMf zop$=8wO$QeqS#HmZLX+KTcU_emq|wM>51NLp=r$~v1ycTz)bZ}kz=8K!B7Z&TC(_{ z=gX_bH}r#lk~SRhxK_(`+)=n`4!)JYlAZDOiWKk6CZ2hPjIIs!vv4U{SQaI`#dZ zEYEG;O`(~Kn^H!bpGl*sJk$za)qnAL+_jt`Vv>S~9>(GP0G1ToU3jTQx7~O7LoI5! zaCIuXFqSoiP52zEMiLmuT(chRTFvbn=)I~}kY;f^J9Vz+##7@gUqdgvT=ObJoG1L? zh{1;FGKa9$M<5&fxkdJkMXX-8&9h`L595=8?M0DEHt43grny#g`J{HH{p&z!co}dM zLJtErpv4<^$NuJEJvylRQI5sY}?ee`{a5ZM2^I6cUFJSyntez2zPgaI1E-dH(d#*#r&kPvjw&E7Px zI+{*#t73k-7VCPW_`{b&{mPVL+czd^^h}x#OB#{GR(i8MbqG%VB5){wW!I>H!l*xN z0&gSEoK-O@YfCCI2KF0?Akj^}j^LxOBm;sJ_o0w`+ov!pV%&4m6^VhOkp0P5+gr*aqxg!(Lq}kg|%qw2{8U^4# z7%{My+Ai*T1!{9$%fnN=<+@`ue4eSsqkG!Lu2ts>5ZBA?7oqV`<=lO0#jVNe0lPyB zTFewtg3z1GV!&9AXJ#Zy%wD%`H}d!Tj$VR0*1Z4~7^&zvfi`3G#1$h_-;&Z*=Bfw+7owR8)qa7Lry8K2R}G8|&e zrr^-Ad`d$$0|f44ZKh&I)uV%_zr+C8pImRc{#6t=x^rVMXj&i;APe4P-33}Ni@P)4 zcP2^V4{g9N$5s*t3<&v0Gk{GM1V9ooA9-D=R6P0^9Q&cYT|XgeYeE4=`j~Ab9?1OM zKI>9-Z0$M)OmI$pWQP{kPUm#rIVvit@7<;VHdwTx{M6I9Gq-#{4??4-FvS`4&LHy z%B}=lFEIS;tY{ki2U6VjlPa()IkhLZgKUi^=KQC%oo;6XNE($-1x{YK1)El*b@7#3 zU@AVBG|lB@+zFpPD^*6@jmSX)XpD*;$Lp4ui_Pl)u3f19vI~;c2cWI9mXUJjOI_O% z9*k@=;0V;V`g6cRj7*4(j=V&NS&qv#+Ue}L9Z-i@wF_x>cp)Vrn>2}B=$xm?F(2Ef z_Att^O&`HtU0pk@;voCYnHQ7>1jGS{5sts(5Q@SQs|DVI=Nx^6* zci(r!BJw~ydnp}3aWn86=O6FEzd0+?YVXbs%3n}AQJ9fDP}xgMjO-xJ{ft>spoDnx zdyne1{$=kzez0jC<)5QeZC?#eGBAU`g#V_2bYMjazf^cui9!z(caW`qjL)u_rRwyR z6KqBD{! zf!ds1PF9&zxNpmjDBeSZ>#@rIoS_@&(fAZTiK(y5&ajArmSU|~X^qNX6s*0ogpBgs z{xf!6XNLapb$ET{(Ie6`%DBS;1YkSc+b2RRzE6v;RXhLp780=s1{Q;V$68nv(VrT< z+4}xv{4+4=TX_Ov%xjTX|MjT13fPgt2TQy7pd(mRFpP}%7H$is;H&pezvn^jNh<)( z$X+aSlg^AJS*5%Qa7GVuAva43-XJJ`?@_(xznl?Zj{h%nM&x$$KR(6)9O~&%XWWSS zm+cG$hUkjhw0;P8rQ8S8IGxhJXPp#p)&4Q}lIItFficd{dWh0P^&V2XlJITQbKqD` zwBE)CsddJnhl@+)(EXls0NzA|7XOQ=Ax`UfWKm4qAx1dI7~BNb^-+-^{SE=~*OSW$ zr|+<&U0*x--+XIecV*swk@&nw1;!J5aUkFi9e-{DtfzuLxD$n1x~P z|3qjp>E&0W5bKJ$Hx))B@+WX=eMAckJxmcRcXxBfsqBHZ80@EJ_RCqG0rYU3F9lXb zVGx-4kHxpYKU>@A3N)cOTSt{p% z8t3qrGA=(D870Tv-#64J=%Cjm>26hWd1!6GqqB5t>sh>^Mu+)kW^S8YB)rToi=ubgrRzyI2 zW7mV4H@uKav4DNf0v;FfityI&KTZcjVQoyI=^p6l!zaM~in9L)^H-0>0}t^}15^Z_ z$EjLnXW23I^PvC!s|?-&-eTn^@Z)y0!M}swb$??I02C!7$Zi5ZDE^a~P`Q2e^=$wB z`u|S;?|S$Dn%@5-8&84EUS-2%tkF$wj}(7Z382Q(-&YZcYO?B;_QfFgq_%|$O0m?h zh`D8)c||j-_l7o-^rqeM1xoCl<5lY_jz&>W19BY;qUrepdrh0a29jbL@0a)=N!lAn z#AC}X%I(UN^0{kYXxDVPOk$XXPMQ>TPlu=T&@1-nv4mWXGxU@^qj8yfMPH%EJ`(h= z4E0~x{NKBOkz_#ZH}B*2!8ahxYEf4obRMWLwwe#(Po!-ec{EJZ)VMTrj(Iyu>)pV~ z=d!h{*v@GpcawfyW3j4bI@f*gWTS%BxZRLS#jy-fWs3_U+lbFHT=87O4s~DVc3Ym{ zY$is!JK}ewa2Qh>2sU)daK5Ctr^ z<~^PX;MF}2USJW?;QHob|AG0>&RN^z zfp@o9!-zTGI`4Z20{&7+oJ^Irw)<4xz|@#gXvI*IYnGi5c~>1BReZBc}^ z2kx2Qw=hUtZ0|_gGQX+CBX7+nl`T*Avh99k#BjnufCF+^^IFH3tC%utg%9XR|HP*; zOBGlcE}k&zNv;y*KU#tJ+4KPb>QFLXkXiZznm0MB1<|6%Wo!ayWo0S3Jw3bN9NXr) zssqnjkA8e+t)m72S?5sjDzmZD%scyqloZBh8?2iVKooJ?4!>B_(_N%s6Bz{uoo6_5S_LspZnk%~<|Ve5Awh?C%5spJYD+M0%0b^d;PhL3(ER zagcMA%t7)c!d>%p8@Iqk#;(9aX_wl)9Q(R~@k%6N5F-qaT*wJ|FDU>pfhnC)#$9|s{eXPMyVP;xtz4iEHeK%| znlFG_7&ph$rczgBA{ht}J{?!q+!?$DZ8lZzAKm`0dF_ODmg#Z(PKKSfcB&OyoQ(@0 z1mbbDfzz4Bs;5h@nxFBI@%4+WEOygeRX><0xlTK=$^+0a#c4;()2OJZ=FYk+4)qnJ z@J0M>-ab`$Sa>+DyN#f8S9~$okamX14SMa`NK!g8(+alHy2|Zo0L`ajRTK*X$L}w6 z#Ei~~)@)DID010MQoHRh#XXe>KG~u)TYeXIcD$X?vvf+3A@U7PIbZ+VJ2IJ4GC}tt z?`d380ct>PMgi3BGyg;8XLH#SnQhai4Zqp?F!Q4C*>+V|RFvjlIR~z!hAiZ=JRa6vdVH~tnX!=y|HI{ zf_@)psBahOGZ?K87e9FHq8f3dGUmc(J&+kM_kd+cVSD|8+@gKtsycFqrwRZ~{2ay%3~sLZ$6c+9E` z^42qo>xT8ErKhLol^jbnG-T}V)7ZD~aLY=0Ts{`Jkv;S-e0sP~Yer&nuFL1L7^q$A zu0qz4s6fVbv0wR~7)oV3g_{r~DS?m_A6c;}RqdvkT6;XazQ!L(3vY63Bz}b9fw%Ol-xTny@w3df(&qktj80z2hg2joyerCe3nflRl&}i%$K9qg8XGTaHrp<6Q41K1mUl zrvj@(bI>raGrabVF}=<;&h=F1LPViz0kv(VYY+VoVbd*7uO@{wQZ8*q#p5lGSHs0K z`5r|`w_KI>A%Ts_x_x$^Z`^x}=cPTg>lJD}L<1XD>eRN=lWHl5VAgJb#36N?6TcrU ze8xX)-6y(3<#X3@p*KkE+cHzREi{P^pbj{kj_oZiYv6n_>2Xiuux$ohQ6G_Faen$Y z6G@DvdMC>UoGsRK=Z~QzhXq0=!=WAa04^%Y))Noj7f^Q>`8Gqf`1ROiY)eo?`wy8x zqqg3e;u&U(ywfe{bYnr|K#pByrn}`Aqw4u5pd-Z;S+THt#jm}I4jPSmW_iyGPrJ3f zUP-c|w2FffWl9)f;9A$=WN~(nO-ip+WDsAo?pRwc0$WiQb}9CCshQPV=$T=HL~5Ir z!?|kP1$$97e8}rmO%o;cV|$4-d%dHUz{3e{Oz?m!Vf)r_-r?H$V^Xdje-v zOcP*s3GIx%xVQiu+l>emLY^_$7mG;B7tvZWiXN8E=GO#aSUcL}PwVZk{V6xlG;!&e za$4fFIXrk9d&_uQBn`zWkSsf}%v#gk&Zg5Gjw3+DG6sjn5 z-ObAK8!`!4NUB)s%;^~HnX(b~nL4R}Z#{YL^cXaaIwo5ks0vciALJV~kkAo7v;dR5 zeyWD=LH1PV6}#0JezVEXhs5mGr%hj>PgQ)dX1m-t9G^|6s@VF3gI~FJ3=k-FCNO}- zRP{%zI%^I4HBhPf{m}Jtqn~Km-(A(FHq7S6`zD>w1r4jGSkuEr4GG-S8ZDsBhc)Yu zVu$+{kJ~dY2HLRwy$1-q!E|u-06X|Rz1jKkZr9#$PEQsCrN?VkGgqsIa%DcfALj+$ zDn65}>BI(e`SCi2Yg!GY{xI8N1`2$r3vPw5fhv{mWJ7(4D~V3OhR(hv)rgj1gBE=f zUC3Qq&GFkNGll2Hr<=ma(sSERldkruGKM07JP+f%;O?!{pVve{P`rCbiiSl7Qv22? zd~rUJuS~)~$YIj&YXB}7wc|Bc^#sF1fjGE0TEs}cJ>w(I^5pV;6W?czpJIHD8$0L*+G zew$*uD%EXsH7qp(C$Pq-9a~GJNeblMd9o5OIBh*^SMYqT&=!#A_UWE_qh?t}6dGsJ zqow6_=P?U4KoW=q+QeN@$v8xv!{aBycs{FJB?fcPsZ?i>#aqMPPU(y3ER2c?j8vNC zCQ;Cf@nS}%lx5)lEU736114sA6xSx7=5an691Ky7{rYvo9*EI-3>|CZpI@H7#B=G+ z=PF?c*Qf6>5lU1-&XAqWCm=31r2% z3*UW`#%2rzP(7k2=BZMsm(#W(hW)OZP}AJ$p!+_n6e&u^E{pG$sdM%2)KI4!rNxBf zbFF$g$qCa2IG98m%t)SZG++~@UmkyMJo(wD)@np>RIJRC@~|sTW~kX%E23-5@IH8& z12ZQs7X^_MsULDb&o&i*fpXbhlP9d4b(#9iaIeObD_vK8M5EvpS5wKw+q*<5VNRiz zOmDOi#ry_)8frdn!}%|Y;`9Ard8|4KCX(%=cO?sVD)?BW;xQLa>RwT4c=eCxZ5gVK zd`QRKPsIr;iE8<#e)xG@uh=Z(VPBezY8--4GHyvnie=5KIP`2qxir%4N&2-5em_z~ z{BDJjio?dp+%)|Bo}vktxa3_Foc8xyDi^$Q8_{t;+nLMG`rZyHFS|qBa4T+#>|tLR zdKlss$wWpO1YN*==v7BFja&{kkHbVGMXpy${YFS^hF``wcTBDh=bR~ z*t3pE$|kr}09}LQx&ekUfAg4{uC4cWDns`~jyd)e)B@hQH~6H+S(AS1c$p1KQfW@13dAk;HH~i?Tecy5svf>R zP!GmNoO{uR@Mfgs8E-rAYRi%)~7Y4W9Q^SQnF>TqsFUDxU$oBrDC zpS6lmJfqF=4{M(oiq4UyR8**LTwUH&&KF-|MvIYhMoH(T|qaWcId{$Xv>gzZ(yc^lQXpo%qsr5E5QRYgx#pfY`ia^h#w z4)i%o@I-YfO)bX-*X6h%-ndVlBZgWnl_&DEisDBYmZQjULJ}KNg>?L34)y8-far{nc_V>{wv?hSuKjFtH@iG&HmI|g0@b~eZf#Lm;+$# zA+?*sK40~bZila%Y!4L~X>{s6E@PVvpA4v&*&lBS4wSTLou0Tm=|xUAO;`0+tOcbn z`iqJmI5$)?=YqRNioKRP?WjUM$8YyOW>gzmowT^rMDRDmZm&LK)m8n(bkB%v{=j^^ zKnNceR(51Px)XA+At+*7DBGJJMryF>plx?IvDzFJSZPjrKUB?Yo(QA{Z(E1^jPXrz z>-9vD@S+u4J1m|auJ4@^Z!W~nWyJRhlhV`32^nuW-|?h_31~cy4pk?CVyZn@tQYkSh%i$n(;*^^*z$c;D`*Vq2GA=_81^eNM*Q_I<2Qf}tdM zAx6@*{=HJ#SXz*!PxZCI0UruQ{4m07Cu`~XT~L(v$0f1PlmwJB26iPIv4{%S+O=x7 zBKZvr0O?>hovBf~(D%APSCiY0gQ@U)m@w)KQ|Gttck@(|V5^Y~!&prBQDkpJlkuSK z{ki8OU$fmx@=N5vxFttc)`InxUw4m%FQUWK>Q}rV3}tuD0P*dKmbf2{$kQ-lzIKnz zaZb{^PL*dn*#_l%4de$I_^^n$`PNDGz0kEHJ3wzlZ#V5OlIQ7c5n4Ax`-Zt@g-O%F z=B4j6N;XDvU~yAHOU*Xfx>M4cl6-1!AE6 z>VUCeZ=Y~+B<4U}>8$(6$z{Ac(0pnOPw)3iU`0u?oA&0604dkav*Y+=&h&j(9S+l; z7$9R=MJ;y5MO}D#yhgYRtO!la5rKMl^ex<+e(;Ss%m>G7{Ji9K19kZ;FvO^B#$e5C z4qBtaC~T>y+KIvau4BW90iP{}DX3{n)}DoNAC#NU8>$E_DAHRWr{mM=4Ilu1knbOz zI@G#J#Q4b%hFac?HP#AWFVSn%QIcKg*l^XTT<6Eri&aav8A7pR=DA-!@f?y~b4a4NK4Xjf7q zh=d;&iYx+02#J7D_&m|M)nExwX~MtXtW~q*A(O^eHDQ-+5o+1*I-g_CZh0i&6&w-d zNdY8(2d;chdZnPS{Lk7KtL4BMqfJeZBX(`g(&@yOhH~lKVQPo*1e;k=Dj;>uwaslk zUb%O4$(NjRI>=_$xU?LXb?W*Wu#mN74X+w_DjHQGvD{S-L3>3<6^Zd+YKwI_`o z=|HcYpJC&2m&k|j2%laDlGA1vPJ)t3=Cs|cgaU_I$pDmTPW~=O3a90xJg;L!AW-9o z?rAfcO=ti~H7xt*IBe1}Cr=p6DLc$Y*t0EswmCC4v))xqVCc-)U1mILA0o$FxsYdA zh;CFux2Ykorx4x{$URe7I|z-%?zBkb=MqKqqz^?^7Eq}xa$z1m1le#|G;Ihyx*t5l zo>h_~vuH{-4`1$?Fc>gfdChA_IkZ;FKm~oZ#^%Zy|*jk=n=d;@%N$uOZjYd>xE8B`Ih7%ZN`dg z>YZ0Cn$==K_M{V2#U6KvqzD345s4$)EVmn6wuRi5n}pQBYHj-v27t=jNP(jZ`E{?r&*NA&f<#by54c=RXPOQ_ap@=9rs=XB^OvJ9OR-~P)xVt#Xy6}}g+uAGq&_pXABYSPDUmF|2(q5S5J_UWLx)ujy+JEL2rXrNBQ= zyr?Q0M{l#XIj)+j%Gp?{%5f#Uze}XPT_YP*P$78muE-r4=!V61dVY3d>}EM&!Wg^h z`UPTtJ}}6;XiViwy7H=OtPJn^u%S`rNI<~?hnRcSvQ)Lqv+{V>x?cn5VNCPSPdvD! zKw@yCk7wxahx$O{sjxNc6_CJrNhr#y(Gzu86BVd5H!)e~u)5ajalBb0*1mfmq(%p| zU)0k?PT`e%B4w2bRHm5I?_NqX2<%r@$$|B~OQnPn{1*vulad9`b2hi{`8%(7Iw+8* zDH41?HY}F0MGf2TROt1j(?kd!<-1`=3Bf(VMdztDF2%a*o2e-?R4%@@oNuj`C_YdLk)=vhv&FI6#Oh*C}H(kqu^)@vV%OA<8{lUHBY5 zSCwDHy%rqx@yUmJ?);RxNh7z^9o}=?THlaSR=;~c#HA~>DyZ@s9kZNVSf2gL;Ss_+ zjv2Fe{jk(SHSV03edQ21SfG|RA{QqVR=nAe*@}oa137P4)+2Ksfz%#*(;UPzO}T47 zLOH+0#nh|XYPDM&bY9G{pKJHwZT+ovp^VG`h#!O;(rk$IPZ2h3EiDk}`reD)w$`$# zjY61{6(Hr`T!Tf_CO`V`-lozvNfdpiA7z_ezB9DUgdM;_=M9*`o=V>rgpr_0`+-g!bjv-tHuOe1Sy48W$m5- z8g9Ll$WtP1|Dj==^BVg#N8px;x}<4Jw6ZiFXUa;%!wr1E#OXmyd6*kAa z6x(mw@ClLeiN!NtDr_f%=2YlUXD(-c(3)-VG((EcN45mZoj2Vz0cndWposWjZ*27b z@DZvUsE!ngl>x`OpLc2YjiOd<)gytk<3cWFq0@v)9Y64QJs-5MGYx?T#kH(OC(7Gi`arcCN9^X$?KVK*zl|h>wh_K zbT6KMtVa+w^=Z^hH4{I>H=4Fi zf*@!`eu*O`Iw221&W)^X{ke$UpT%vQW{p5)4Qce_iB~c=e`VC8Qs~ldEcD_urEwy= zbh=b*Zo7G~b?qN}&=zfGcortBx<5P0%3FH&reDJ?#Q`#$jor;3xSqiDngUNa6--JC zq+si!7iZ$AqH5RdH26Wwu^cr8#nay0>rFnCi9>Rf%y`FWQ6?sr|d(P}(`-NEUF zzN=Y?vU1@<_9G>rLQ={_7DqXAo_U6Aqb9Z%=Qhd5Ld%Fn2-;$ENICzqAKToRB$-iP zd%vjKK`9e~i|~m<cb3hobJu180a)jLe{D+JZ!ADZY`zenRPy8J3B8Ce_q=8B~3B8CFS)LHM^$kIZ zYDnQ!gm7`Z@3v3Qahy+mQ7Fl7nXU`Uumz@Pyz(WgUNfLf&-MZWZ)G#nu2^zl|Kek7 znU0X%7P?t1TWaa8OK(0XsTwNut7Pzy?Nfa-#=fa+e0NlfOO5SJ{E?)wNd;O(y_!?c z(t{D81-A69F>v8xwGdEmZjtJW&h6s#Ng1}4P8nvNR0x1@P3FyDx~E(APwtv-43?!! zuPW0_h2MYl$V8QRCfmmZt`}-Pv?Ec2Iz1$(E*vQuJbObt@52A~fq5u{+4lq$wFoP0RCvS1sG3%;_p*3?IyCx{zpl{IZ}#&MC$+ zU}@VqHFmn9dfkfvTj*)Ji|hE|tEQ%-Qhh?urAyOvqXn5cO53~1yFLGQ6RIDB*O^7N z9?nWlk5YcY=lu;vwYSUdvvza|XMSdV!Ox{EMRe^h^cNWl;6@0o>aEBWZd+NvQ6qScYNg zQBU1bD7?USJmHI?k;mOY$P{)ieUNV<;B(>EcnICH-#EdVYJ;;-Q>!M|m{FNt7UE6= zhn_v)@KaxkY>Q*O?6mCBS{13VNMT4O+Q;9M169$m5y9fh=SG^<|5HR2@F(H>tE4HQopJpEzsO4w0N>Yu~L~rS7km z^mZ%kZ2~$nrhue=6%&|GbE;92-7^W&iZv8b^kydJ z5JXqCy-utz&K*_8bWxtK$SJc)`^8GCpJxGPZ4PoQPObCQN#Aa|C6S{UCvgAq-b}i> zn5~R|#E6Cvu#uwQ)UmHNF}K;oUKI)tUGx~3);^Iw27kMlBAh4^Ik=l`QGSQN;@WBR zz4WWJS;+GwKUKi#_1;1UO$3pz1b;mCW0uYtk0Y6CDYE#C3{U5~gzId8F(oUIoBf$S zb2++y&wo0Zv)Z(l$2wff2(*kJ5*STEFEg%G7Vg|gSuW!@YqWqX?)ly~;YtX^S(7V> zrlCfN6FR|%aEQIjASV!y%ega}`Q^t-yAG|L;Ju%bbEmJIdYmjqq94!%uSagp_-x1J zcByF?NWnYOrZUB)77n?`lk*aQ@{n|{ECF?l-31__w?ra9jnqqU zF>d&&&dh+WQ>1aU%YMaT;RkaHR)r(_H*j*~GWvi}vbH=oa1EeL!woRITn zXFRiYSh3ol))d|)z@sD0J`L1*3wiDDrh3$GwuSC^_$O>(IAoua)rQY)ra}-xglv+J zm~~BXG9g65;KsyhAuCm!bT)@@f_U{2A@51E^<`Mu3jX zOcR#gFd=#9aOjZHT)5QNT>&rboD~Jg!)L1zK*G>zFn@e@;1f>UbtX&~VeHmlMn9gh z`?G>_Zy*vr%qGgqEbMx)8%ZZk`6n^+^Ng4dZp&pE*w_k*m%^Ze^o-5E@gOOdvbz-@Yp&};41RJJ{saH ztuHz@Q4o>ucT)b#NYw&mnWO=l15@p71E9Yt0nT7j{qoMJBf1uh0_@G2tLI&Q!@7)%<@qF-;^#kD%#WSYaKO+4+97Xo_zeY8aGO|SoY z74?X9TSi&Uu}1YvdO{Aqr*})kKW=%<@|4s#K*H>Odh)y?^X4gBFEN6W0*$kPca~l|*^94$ z#sjj*ix;@$=wnG%+1hc}r-}i$0ox@?GU0TVoiCwQI+Ch?j5ui;qB}Oohn$SyksMo- zYK}l`tknB8!nS)j3;Pd7ofoN}4>qlJ8A!Iy-`IB!zC$8aWyB@cl|2y~HLuDM9{kbk zx)mBOENVddPNx*|)MIIbw*!bjN`!~H8SGrgSrDp1h7RXYf|UIRGV%UVFty2q(;DXh zfs9~)F{u=XcoW2a6^JFIE_FKUalUPeiB@0%PX2;dZ)TbW9gPvJCf&n5B>+bTSX7_g zc?sk1wQNiD2YGjh3oVKqmU?R#GLuP%Q1L*z;!; z()&hS)yR)^`!32oj%REbiBi(Q{Vu1EE2zM4)ov_9zzj0W3Y&+!CO#v5X${^9_o-mP zh9?6**HCyj);FPlY5@eUthKMzatfEmR+|vLVz0ttQi^2wrelFHOT9C6qBHHADZEMLGXCYsrMe>FX|Yc@GLPHgVjbo z&#ka!sFuVhPo`|k$4$iy#C<2o45n$%Qunekwh3`O=|a15UW@Yx=(@bn2h z-N=Y$r1;fgG8ww13Esmr>7QsawN2O#wP>*zJC`AqN#V=Ybvc#__{2zautcf^k1};E zSSbmy8h25kC5%gRA+1}f)C+i@&P?`9XZ^7~aj=>JqSS|%LGQ`2$I_lto+0={y;!DH zj+Fn?Xio8k?K%}xuHVUkMEzk9hDC+!JG-P*u1R!?EN(-$ty)b0NKe*zlWBU%!s{Xp zgWcofh@R)wS7xZz>q>Y9>##paH;f+0|08w%V`?<7!)I6Ch&)m7tG(`|3j3{dw>qcw zcsm@$7m!9Gcv)LSdZbF8zf-NQ4)l&X%<&2@gibs{;UZCP?D1oLKV=yU3+w)3K3XT9 z;6daVNp@dk^&;0EUAu3HVjkXH7%ta0j4NX9g#A6;jn|yyu&}p|`8>`9qoJ^6D!6=p4 zkZ*TiZtlXpsa~8I*5DEsX4v(nMy!6xta)su#;%6K zCScN6_3hc%%-kK1$gpeNW9PXx4Czl_BZ7ua?b@#~m2No71GKdt#0uM1`pz+`U&H|r zrN@U!o%zzl4`W%!4Ic~uk}qNw4lLI`Uj1oNz9)~apdv?s?9qaAOAa6F-f%2AKI%Nso^$0WQ@h>pgK^1IiW;W; zCnSZhbinsdfN;>mto@9BlVp1}4e9qN%&Z1M_dwNH{|U<9Q|w(vnf#zg|0u2Wf53s- z!TL3LfT8iIBZ;TZxNRE$v&a13Pya$J zfb;o`_0-G?pZXtsJXadvFO0N&V@$xmCa(gosng@BedWsVV~6};XA$TVj>~ubuOd|B z6Eu04jZEmEeeap}Y$1#Bw!;k@^6SN#FX|M}T%0{HE8ReVkN17>ZztRM0H7=o;HOzV z0^BdhvzBX7q`!Kxiu9idA@5LEW$b#fGf&d~ez;=7$TuUA;~8nWP1F$lCG7e!_@C<$ z8H;fhZ#@1RZ~miTE4@2%5#!=DFB^R#VYH(N;GpuNLFURbYXEQ?42g{%=u?~l2S22b zKAEyZUUv)p`*X)B0OK*mBo#2^$bXpcZ{;Ji_-OQ7L?MdWG7q315P7{SKY2d(Q6@zE zww1h9e3!8+7{XJ09~6#Hj`^Ef0>IauBwh`K7GPZervm{DH2D^=>;4n|>N`b%$y99) zB&-wY9nb$gz1RIsi1NxOnFCwg+)=bXI18vJM9{|^3_2mW0X{_o2F*X)0v zv;N;b|Nmo$ck;5|_42~Me7=GFg_kZ4*3Wd=XV0Fc=iuG$Pp6T4n7|Onc!Hj~E^!a! zOkhBKz2xtI;jdEAV^dr71F*e&Nl^XF?n{fzd?(xZgVmck<^X2$AWkxC*vlADlwjoe z=JZ>U;@5{qDS`3}0sxxI>gmju}t&nT=UR|Hz_4T_KH!+Q; zPW29aEQ0P39&b;GL(~fL&uEUw(ZldPZt)2Jb~gDg4ejFt5E-XQYKc*iO^(fG@<7QZ z@q;IcQ>)F>8$u~Cbjsr z9wSy&YTdVl{thzxK!+kANBTbW@wffVlS5<2zaEt-oY8hKwVyeU5F9E2d>Jy3Ya%Wd zCi+PiUCS+?FQ+Ks6+m`mGgBrvy*{QVCMK3^llGcDLk|y65dU*hhTV4_hey92dW?3T zHRAT8hLKEyzpnBQ_{Nzo%dTg;`f}p>-zZT{VvQbaw@gl;O;@NCp_8|XfP}Vma`S+6y~`#^-tN5pb5TU?iXGF{V%=SQY;` z0+IY3=lmX>@1^V$V)CsJ!nTXn2Yo^FAT|;}sqz0zDt=UmoC`h!Vrwg@8|xYl=G=*a*O9(W<;zxIk4PJG z441c}g}mM|>GCN0z>w%{B=0ip?tWYOB?xzq?uH9%==bfwu0@|xxs|FE`}HGIMD7F8 zc^*oK=YN?Q3jGR^JBVWCfIawx;=i8L~fa3?l%IxO-RUnOhr&%z1 zmoVrFC1Tb=9i;G135RZ9{9^u60f8|oyZ&P_d&!y2Ir^pb*{XsLmZ@4 zMm{{*`KEl~28L};E+gIhlr9XFe>2!-M*R_o%pbKau6RVYz)t0J-eS3;lPLz`g#Q%$ z)aczddO}`WR>?F?r`j+Rbf-$=A{I14m*3@;z$tztOUuJwvl|V~Ks@@_1Vmp=1c_ILE*?7J-r}*C;TTZrPnh ziI;!P*Kf4hwgLDrA@B$Gh``EXHSuwzOfQy$Y2d5mHhfEd2by z0ZJvN?3W=4U?tu#%q}WBO;5eu{EXXn3b?|WUC#aT12hq_sxkg|9^X@L)?x(*p;uV{ z%zQ8>x~<%Fn9{H!xeU4L-YP(D|F=O{+8wP7SOpCiLSPk4n8!POZw46wk?-epHpFPs z{Pcy=4TKHrPy%52D~6woE<~^FX-xnudkbViw8&%Jr9R?oLSUuP9`LUw%9o>eF zLBz-YE|AP-qcz~A4yebUl@-DCsE-|P6H1|nld`5Pi-!~ao&KMU76mO}DEkUtv}T^C z0}^iLLv0UEUeRivE0A{?A;XK=U4N=8FLsErH)=8#PB{f+loj5d__YT+v~G>)USaN3WsVhvY2)6XHs*2)BYQ8 zJ}Y|lS^{^YD0+bTvl-4xy9%*ch0g`d<~%jaEF1pZYcq{^2qTa-N!m?zIW}G@ipxoAqbaS3}zv?p-_A75S&rQ&p7^Tj{mnG zzBy0zn_sy<4Z06fSfuloZ07-rkuSoWW>2Qmc05-;VOah(nusVr{?Gw zE_bIgiHag8rwi{q5I+9-2bOe#!jj_}?fTJHJTiqV7-C-(zXBml@dq$NuacoZbpfO+ z3w~P!R|@_@OopA`bB704uA=$T7hURrnYgzIVF301L=GZ#z& zy~lmI%u5xQCAO>i%@N+6yz!Uym^?;f1GZJ71~9o-sb06tGIXt+%zwWCvKFA>kI#S(-|8V&H@WIjHinP2Gq_Ur5Jqq%HD6j4DXCPj=y zL4>T)3izNUe!ssaU)09F9;~tKgrW#lGJlu=xol@echz6k;SaPZj7Be(hsgH#)*p|7 z_HEi4=b8)v+GavJe?q@y;!@wT$Y0$#E1@SNQtvoW=}BXL`jX} zlt)85H$IH$YUKSfEF{BeCSW&U#OrZnRm5Cw+(irAjyTvB6c8X&wbs{BX4qD=3ky4Y zxi(Z{ZLRo;UBb`5Ph*0W+lCt83RPDB1LpLWb@u!zz4rGZ;Ry5dX+Td| zwgzh~T3CjitnIH6GVFIb{Y}dE2^|>W!s^L;3q>H&TPWZ#TC3Dlu5p$p?1$zJHaVqo ziLS*yV+P+L_z3z#VwGo_&CoT3s0`BGsdNlT3?1(tZlC9S6u%$e@x6ci zgU4L^+SlIaTI*crT8mLh1GKQt37#x`=36t7lHRLf)EW^AuZy)Qi)7b-Ab;tS_Gmbr zdp%X5D7cJp3yE&g8|JFy-D%w>q?Ojqn5Qc&ksa}K-r=<4zt7m??R zg@60BIOlAVaA>#Nft!U1>C7fl5^mlXrUr$UVM??~Jv*LgB%1HFzg!JU5C(1P7^l7O z&ZAkpAX~!!K=cZ+KZpaw65*Py&APAOseTyJ0R?_*V^zwMfy9R7_lP*3-%urr!ARgM zldxSv9Ys4ucFs0EZr1!XN+<)4RmUXO>e&+3RjJb@mdm{a(g?W%-3mpwEn>>W-b>$J zbxJ{>JQ2}e^#tK=&wBo9%ICH(Z*jwbVrYcZ`tcLP@aLblsr#``Q}&=3GbA zk4As(_=yXF>To^k{L#{~AW%u|Z#h}sIAVOdPzvleLa1|KT)ph0>4SCVPr_#ox)|r} zcZcGPuNAw86ejZ#?=d$bL;r&H+15v^f~QO8c?`gOOv;sWan)389>PA zJQu+HmzGE?H-2tcg^=@tx{YQ$OT5Sf(_vxo~m}#{IPqeEX=7ZLC`B^i4eP;_eVC5^rv|YOjx(X`( z)i5W#xiBW6OADt9oKQIkBIUma)JOM^hpTUa#%*k_hwDx41=gbMdNm9=pB-8vvbUUt zzywWsa%;Slo8UIsQa?SmE;}}R%tVY(Ou2$_jDP=J!26r1d-7xNNl%=1!QHcee<$;4 zbY5IBF!aU&KA2Z${TTbTR4|drg$JDr2YFiQDJlgj4_!6TwZg&9>NsmWfs-!WMA?8doVL8yHz6xfV=%jk2tH-xr%%U`%{0>|1(XJ#o|N!^*u#XH zyUwD+Wg4r0Pc4I4CztwPvNx4iT@G}HI(a(c;w3p39x^}#bmnrh>*)vXquhKF1?ZT81 znSt^N0>lr{Y+(XU=9z3j=2+&iUz*)hEvKF7HHZ9&HxUiw#Dj65R3`lR{6)8G{Bcbm zl8z40kvvvfad93P1EP5K=RHOla@b#t2~_PD?iDMyy*`67|6o~T%<0Vb)CJ4OTj0gu zIp*sdk-3iOAGuUi_8iCv*A*TZI1~t>f@Qlj zgmpX-vg(@UmQ}9Aa1njibiZpP`$fw7&JPS#`-gOm44kHd$VO=#G9KfbzX|~Dz1TrF zHalYW>OjR*N$D>aucs^{y}(n< z$-RPkQ0Yyzz$k6G?>6EMYNq$R`gf{FF^$mX+BD~=_BW@4MT^UoGi6x8DJw3YXV;*t zbwd}Gw?~39VJN7SrZq%fD|YVGi-EYluWH>V<+pzYF?V5KSY|V|bmCEaPsmJ%>752< z{763y5+f2cE}h6n9`8;k2kC-wxfJvX?7A>Y5eA--L{so5k@05R+7yNqvB z7R#iX$IzQ0=XZ;8qTC7rit7CO74jd)2tm#JTspD?|8Kux(3Q72OhP}xzstXsAfySh zt|w*zeaAp?VCxH?HSNJEV0>Gn*rJ47H#Dq*n5BZrBXjx_oh-v#9p=Arbw&(Yt-eJ1 z441U#s7^xPTqBAPau{P!t~m3krEC5Un+Bao>NVsaA*_pX#E%G=>Ei7aExU!XgYAtuT&g-FqfCe zn<3rUeyO8yNk3>;<%2KCVuyKoi#rIIt9CUEWnhKSCfYr|#OW}{VxgWJW%KQm&-tx# zP{aEzlsZlE%SAPBXAFc=yYH-)!LnPLCcP_qaw05IPci<*yL13_23MM%o$>fzya>km z*CdLFgzEfdc*c!~n7h?qEe<)=o3ovbk#c zY4+*wH-3J>6I?aGwE22hgjwoiG99B%gj}q;~B#< z3raEf)fzaPGf}T4&)8Kl%I05t4E4&XI)hf=)7&4z8dNrk$Y}+n;!I>0}p$GRU`ew9jx!q4Wm)`W#U{rM4iu$joE=?00m$B9mt_`fiY58 zoYj)i{M%_F7{?RoBLZ+Tg5_@K;g$YE8FcrvQ7t38UV_1 zYgb0l2+N6@N877l>h!3YC%RKqCQ-;Weq;z^Omr}xjp_4WrZ0sEfxs*I>t^x{$K)9H znf;@Ddg=qLBxxjpe0dnKG3SVML-?wX%x{5@g)z_Kul)tur+}xQ=2B!JZ^bcO$ZWde z){(0YZvh|odCv@^{mKwW=J@$bThVIyS^{N7KHxJ|0^{AR`pW7r=g9T)zjw9Su&xT{ z?B74#!no4IqD3NCh(~F_q>camW~!4dsyY1F&If1|wbf|3BEq0-=q3ag506k(RJ3Bg z-gPrWNI5wS1AZg=*#?hdgxxdB+OJ}~eR*J%R#i;@Mwr*Vs9=w95sBEEj}<&M&AqryP*DH+V@Jn`38m8u;X$5}xO3Dl_bHxQ)Hb|pXD*hv%)qjNH!Cie=v zMDFrwy>GxRNyO7=B6>3)b-1?)#`5MB{~ObeT>)F1aMkM1D*^IHJ%qn7=2*w!(%HYi zNX6U=(qL$S6OagGgLeEc0#0uzcMIrLI6b1Csd>3nTQ9ob+rNYz@nsoYHp-Jn8R=Ww|PD^6u)lvUK_vjU*d0uf8C=y z0Bnpw4(Pvt-uI=a$Ebz>wVkRvploOu80v*WxiTG>`V_erjoLmGaT>2=&SjwY>MI0f zlf_@tP=1=sdU}XB++U{KLxH9~N9K=I#U>7c2}}BCoIDQn*9g-o*V&UE%*FcJDWt3i zR9P&*(TmjQwF(0bYh_GLvwFD$C{C*SyuM>+@|+fTsDrnv`m3yt2Jb(3)yC_LxhQ`) zK_4*a&v`&UKo8z)26S^2`xol@$%Ng}QP?I`GMnFv~E4*&takr_=U9YxUZ3py!>~8==Im0Uuj%CPoSh^e9oYSf0`TFMO=Jt(!su!O;nLhca z9XS4|I(tQ>w|_aN#V1U*zJIQe(l!aipE?Xhniv7#c@P0nrsCj(iQMr){?Tkis{WJj zReXlV>aCWIn`60is~CB$$3p6k_FF%{p477H&VL-s_rQF>V)N&$K?N@mo=P96_}16gmsFCsHQH&=cIwjuOwiZHUC=NNF8m!v&Em9Dt6mvUNi|=9gSoLUv@u7-C>aye{*E>` zq&I$Te^`>a^6~~)gn-5Q%NN>*Z?56ry_^(KJ%D35ZSm{Vg+0_aH(xoe-(hu6kFc zK?mDm4k1HIa7-9N`t)cLgq`J&52qFQU6&$`b?@G|K?(ZrNxZ+s%7Xp!WlDSlm>1p( zI>8EWL%+|{gZ{%k)8M9c8`kS0ya>?;LpoP)GchQl)sK$(VUOh#gpA1V@jJ{#NKv#u zvnu(^)gEF6PG@@BhKIE7{5k(EUs?;O(HN<>ZDNUq5N0j{lkF;>4es4*ZQUBP?Vsu<4II-4f6--_%@HxLP za{#l-w^IAdiV(ndB+o2&zO^2!q@wVGsMHQ%14`YBqUCYywWYnu!7y~w&d zY3LiR7ZFPR20Bt|mTw4}t*KqA@2$;sTpMU4e*3ZLQ3J+E|FO)%(`BOfLaq|2d#|3X zj9;m_K1=dx{Zh28m1Z%G6$2_Q?N;ckv|LRfjIndx*Q%Jh!JfS(DL(@H^^!=+um|ovb!gMRUQp`}4hx+ni1#j(dCa`lO@z`Uhn*ok^35 zce1hZ1F2~{?f%TVNF%Vkro}_=-0S9(P=6sYedB@Bby>=3WN^Ju9FF`+Tjgob}vcy{Vot9N$cN+I{OJhL;!xH3Z5Z0e?-1DC;W%6{_ zlnvOG)a!H!RMij9Xg699ONWh02D?cyMbtOx3}o7+DiWMe83QL}4o*YV({fiY&@nZKEdH8~txzcM}TSJ3Kz1P)hq| z6vkyDk6^3k3Kck}GNgP7df~(l3Y^e3z~3gm)f03oqeBPy`4!!n9n|;cipC+V>tl21 zT#z0GL!l#>;Wgr*$KHw_sw!{oL2VEMhT@qFCRRr5{?NIC?86e~-Zmza?fm{0z!!YF zUtQmbTw&UAAfn5?h0NO_sb2LhdTG0-@_8X&3fgPXlVC)C&_d8_53SB`_;vT{t#39O zI(dzCbi(RReLD_p)1Em8+B{xNe2xnthu|1ycy^~e3S9PN8^{@y?rezVG;VtiFKNNj z58vOrHWuyr+xMU(#hl0Qrn2Hql-+z(2{d`s-F#OxEZ<{5H01fY+|*fbWa0_e%RZBi zLj}ovwQcS(;FLL6Q$*GD)Dm^hqHg7Pz=-+-cGD4S_6@s@W`<9*QPpyeI6w9g>5m5*jBP1?xK+ zWgjIa6V{4>Z3mEZu}zptR?AcH@0W6ja|e^FUZ?wQpMcjOaR_5b|GFD;yu06$3%Aoj z4pVeQ^rYK3MQGwsO9e&^mxzMnFl-Vhv#4zoIodL27QNV}E=w45B_&AQ@Y%_6{cMJI zyp#7w|Wb_tyay*{uC@^R1wU!vSo7271cB))kapR%2Z;+6fqyHGH?$`C)0|aoy3jV73za0YXQL^yKNlHFr%D z2-V^BX{dc`oz|+UZ$a;FiWYD_A`G8m>6*yt6CDJS@iuHaB%{oGW{9fbN{>3zyz?I> zCGzgJSCB$aw2r@h;cmCcD(VLfJarCG;Z>p#5!pzJi=e2c~_r?JVDJ|!)T#%viOI;l)2A8(oTjxLQ&x0q7zM|N$4 zH`l6^V!8QV{IKT7-0(2d8ryCIv!8vvFf{SXv0ZDGynn<8)5EXf*U27ie3CFEqe|01 z8Em65Jb3l8ZQ*jKK##*zsnr22`^4pZ(`9j=<$PD}{lnhiMq+3q(_m0_Cb0-=A+LBq z6OKs>SPSbF-f35NPFb(n!%6Gzl_MQ>VHFzBO0MZcm~_cw!#x@PjO;17ukNCr$oQ>O zS@o6;jxR{}S&e2yIxdcJK%-j{H1?F%^Z;e8)7F$@IdF*r8dq+|aZ_$erydqbq~8^4 zD(JZKBWB7JWm7Ak2$?vhsz{QUZm_u)QSD?Nhge=HvcV-{@(p<2_BDgb_YxE}5BSl;N+DU;bTzG8)C0^x92ifHcHiS$C^wKiQWuy4C`(2X#pHl&Jg8hq71U^UWQ z>T8<)(Rz8Go7jthmC3&}y8LgGyX&-#*w=*DV4S(u~jQy&;8S1cRI6jzQn&-F5 zs#PlAC*HYPqF_v-Ans41s3l71Hu2?6y&*UALM~mVT-bp9?}4DNHR zF@=8Mi;^4jL(XsRl`Wj(BCwJp!Tp92Kg*C(Uq*LsA+J{cXke}+sWLBhm z1}1guQVv1dY}?QDp1JQug`w64dc@79yJ7vGTs>ft^iIBkcEnMtiBon@st98x_) zrQgR)xx1rGg$||_(jK+)Y**3na2anQHpC(i+S?szeh9ACjFQvR7I}h;PAN;seqTzd zsN9L(TYJ{8_97iILXa7Mw8A1=%`M2Q;hel-j&(|s4JL=Y%d z!_^~w=*iu^pMM=I{KdFm_5jb7+9)Pfr2+V4NEcnol~(^dZCp}lInyt;Wcri2u{F8A z7j|PHc1{g7{M!swt6w$c@Ifmh>6fZ|c5X}A^t1iy`$K3`d$&FJwM{bRURaL9>KI|1 z(=M8HufvwnL-Sd-+7Z>kkU$BlX^nK9pEVAo=(b$yqB~-HS$QXEk~{@QwYEH*+_4W1 zD-E4jC8h<}n37Dxiu(T{%Xk0&k{{zwm4FD^Z$rG3Fu&igu5JV#EYv>*bw|ieS_aJ< z!XH0HCYXANBz0cE{lfH{C7OD9Wj7Ek|}lu;(4bUVm=C=h>=jo zMI&_qd5es7>AGU1H1j+cEp2zD>M{(OdVd-VHIn?Zc?GZSi7q11iaf!W$DaSLRZJ-fY+>c?~das#4UuI9J)@hjU2Ib?P%DAo!$^ zS5{`UiXCHwj=w4g9XY)UDbN*cR#n$ytUuh(-C7gvDoJgSfehS?X;rW6ENTzrouKs8 zb5krptP1QMB-I;zeg#cwIR0cd`#xQ1rnnW$|HGe3XiB*&7|6+9r-E0$bUMea=790` zw}Uu=39Z1Edo^C=5FJrhn^zXMw~yjoCQI!k7xmI9U{m{C)P7i{FYSjv*s|DbGP6%& z1EWcWt#oxfe%=H^73I#PQe4p;BSl`o2$JL?+&S9*}fe9*DY>s~X9Td{;7!RIrVITP9cAv?POGQk@0%Iifi{lh5FOb>MN< z*wF=M3;kto4Fk)pVA0mQu9b2K+<|B9>T;Li=mqMzr{_s{EF%iW-S|4b`!y{$Tb%Ep zwM7t^s9%e8K`ljLsJkmaX|v3K*SNt%$z7MuDbW1;@s=;s~r znqz)7K!g)|u$sHT=XFF+{H-Tlf7l4V17gxMZQ~Q zTT!&{%RL<^Ii6=`ST%WfPg7J-zawUOkEZgI#PsHohk$$#_HVa=@-fDLeP%A-^(DlV zG=k2ISsEfAOQ?McHZ*b=W4oC3buj9kds=d0_xo8{2|6Q>NgwZdR>qK<~q_OROx#emk+W*jQ48=K6O9%l7;jUX!`>*(;l6x zCzE015P7Z(uXt0(dR~v@IjdWpdDy(6)3S8FR`56OM*pT!q%h}3VZ~eEz)VZN&@FZG z6B_;)TALJ4Wnho>Xr)xjgY04 z-Lc+d)v8QtIY0Oc)ZNKQ?&9eA6%qc}#Z$?pisSXRpz!)O^*{-+ow{Azu`*FR`gjDF zG<%5n`(OfJ?r88`5f$>B^^X8VUkvI+SG>V30se`cgmrIqq;AHQVO@l%4f}E%-lR7* zV8)^`@uGE2RfM4~qCEc*f%^H(2AeusI36*n#&bI6<%8i?<;iFYulo-n4dcR9qVx(P ziuxC~f=Ps?K#J6U{CWi+Y_!m;Oec&zDYdP3YTKTEU2Bvcl2YWZVs~Wum{b%w((loK zVPkQv6Cx_Q&)>6bhbkNVHsN{DHnXE2*l@Mn<^&2xB;JeJn2_MA8p)Z8YmZAeFRSb< ziPBC|lmpXqR<90Z%q?#US3~{h>@#1Kna|ulfD6u`7g@*uvL_O><=ZgQVQ8RWR~G$948La%3|O5?a-S zQ%f3*XVo=zWpQ$Cj2b!~eEB+$())w%z!4_q?n=YV0x&V?8X}o`l8jBj-p{>9N=eV# z5Q^C4NexF)rxJ}zqXeNf>_Qj0=>V=k?>I2%0|GK3JRkRy)vuZdz!KVkx~t2H$_hCP!YDv8YThTV?O;2fRe7 z%g1)IIzNi7;YAMuPq5`z6%%U1{G!>lS=4pxs@mfBd`hh*yC-zLUFv`2(uOfA(;*(4 z)Fl2$SHSO0b7k)|Q>G&+YD17ZY2d8xWG4=S7Gj)I3IkRmM_UfvnTeX=bk!DEt_ID^+*lWnS$$w~c#>1*vp&>xL^k9&41B z_YVRo$v2eq*zB(5zbA?7r^X)`@g4ss3E@?B_m^aEC8nQpLRsiRsrggOQ!P^n&FM+< z8P9#Mx6Fq}_DE6+#h28aV7gMl=KNN+l$N-Ho1C7%_wMbl!sGUva`uQ&%luT5XjXTr z6zUHP4EHB(hVM;!lni_5WQrszN?jYSu&GZqxA+=i*c1fq{xQfufK6w4sh~^BFRFGk z@zXuQ?n=paDKcvGg0vtu&Wy9A1?z>xOxTY+-P#_lM&>{HNi+FRHgA<=0`OdQ^C-M_ z6-D;8xHJoGLk(55cgj0?ESPHDwhR4hB^{1j5AckOlaJq3&*WDK{vgS%*JF#;)A}~1 zAMUVLS)x-z&#~CzzRF0SZd0oYLE6tJ7)=X%Hk*qX_#yQ;B1Vu4ZF;>F-iM62YVacU ze)!IZ8j-?!6N4P5plu{FAn0A5-{?T8OScfCT4`39X&nqT@Q{u~;jlPkhK~5{{%&g& zYqVRis2R5`#B9rlspHjCi`k9a%w&Tr`Bc8?1F3jTvXJflsf@&RF;(8w2kZZ2YY@xdF*%02z!eyLzJJIWTPPun_@-0j{mt%&+uJu#oF=E1Z z^%LN&feD)qqAfPP<+W}5Q`GJW?kYC!uPx|6thpai3S1KVewGZ2*H>rLRhqSD29(m% z($-_C9=>rI)x_R+UIO+t8kqBr0LA0I`6NlDU07#5_JE0oRKP%JYJT&6jYg{vJVC%Y zJi9kz^pRSM9fL>`EWPb_^7z>;%)v4Y7s7j#QbaG?g9C-gR};CP{-<3+>1;CSYN+jz zPzpy;iM)JDk$RW#2!5c`tAzuKtks44o5ejB^vLXn#;ej&8@D(lefEB|^6McQnM*ML z$&~C0jcu_cBQ8tt9%yvc5~;2~%}`$M6nyu`5JTwe`r}>NP*#mUYeK}9ZvPxjj!>F@ zctw}Uv$%WAb<+qW&x0r!v=7?iIr+q%=1SXmwOYoN4XUKw> z=a6i1XXzhzRWRLQrkz)B$5R+Z7D%*1@C7JsX>|phAyV>n-!sBed@pMNjkQGz%pjbC zJ>T$OlDkq7j)vM(w7qv1kD)s-@39dNFV9qMz0*_t$N`!pQd^rHw3?TCZ-?Uk{qEh2 zvhYaL6)*POx799kt2|nM$mCrQH?m;P-+ZPiaU4tpu>hk{6ZJ#-UD?x7NGVca;5iNV zrK2!JwA)9m>rJM&)SmJdh4(dGI7ScZ&%f+m?14_yxUPKFgiB0+df_(L7L)$8;ib~I zT?Ik29M$}Lg!&$KH4m!^0*`1ORG5#;iyWGk>kj(YCPo{}O_MvA!EM|7@^@ab=+}K_ zOW<~>9#foyxev#>{%C$v47_Ix#fc=5Mp9@KQ&$uJHpS1_8eXGV)mvMtf|*-~PCdAY z%p@~nM{V6?q)#fbwjUDEs+{Cangc~^3Zv!k1Q402Qo%As76s0?-rnop4W9I}cYMr; z`w8n$n90^Tg_%ISy;`AI7M-1<{UC{!i`NrFK;~ye)q~%p0Ajt7S9{pjdp*6gwYI%m z{yYKYxI%d`Y^Zql5*L-@_moDp(D`LmbzL)>#A;#M)Jv{d8w+%N4b(4OSDTH&rQ+?nJJ!{vEOOYH1j zm-#rJZ+Ig8;X!#%(L+JNwIYS_%WenbHqLYX(H}0fOSK%UgwC}knB*7hV~7U}bvOiT zZ=K?L&fxb@&~q5@&Ge1$Z%4}F+~&m3620Sjn8K|IKtJ^syCy{c{hiv8kv^~Sa!-Ux zWkqpq9+z55(Lqu0bW>n?coUhR3yY3j<1Bgltv{S!sv3swBle4_wL-ji0FW3RKBcc~ovaYHYJ}R6#;( z(h~0MBV59z}e$aWF*LY((r{7{MPWs3#xOw^f!RV|XEir|FheiRbU21J@2aA6B zP!Xvmm26a7n5g$LBoqW%eis#lt(3=L+GY-0`Upy&7=QK-BRzFdzmoYl(>&@mTu=AP zabk-I0|ez$r0{;xZIj0UmDO@Ze42mmi}ZvBNf9UES;PvN)r@H;*OYyj${hvc3Bopj zvH5}GTJ{YlU4O9i4(TI!xX}tPHb!af&BfWYpSy!4>OBCnxlY7VM((MR(dnWO<{=u~ zj)S|6TZpJUv}X3q1zUJ~?pxdHP!_-<^7P%%w-zm<4<{Y_Ojs)~y)VQMe7L?>8r1N+ z^}iv1uHG)$w!C>+gNE2WnBGMYe6~vrCjV#_Bysjb;%0Z z#&JOQK+4`onKoX`p`Ok#g8EG}hNP>=*2~Wc@Ze>8(5Dyrsg1(>n327=Ezdfd~9GqaQnwDc&Y!z0a&SU3uOb7G9bl z8_g2(;lo|v1#d|m@2KUh+zoUVJMl^>;;v5&x*GU8*w~weRlBUrUw>&_cEZ&;4Rlg% zW$E3SbB^OhTKL!cT1ZOazyX_v*cv;I3pnbmt;oL(A_7*xmK5HhO_nfpPdzc_u^eKs z8ga7a>&sHqogg|cubeK_ML0(A)|Um0k|RgMV!8qQwLPar2YATjd^Dn-zv_&U#Qb}%;$ zmf$v!a%4_R?0wjrxuN4f0CO$;x(eK(80yShbz4dpinD6{4T%InT+E*m4C!1fFTn^U z1CNDY@$Lnw+BXgOdT1yVZ@^{frnlKZo?p$-rfXCBARp9f8mc;w#u5AJL;Hf_nsooA z9F1HM)Vt^v+7_)06+HxMcs#Rp9S5^fWX!@YP>Vq$bMOSV4}gQe9oz#vEl?K{HIT2x zSH5=ap#UV;#ky)0)>cG93~Y8ITIyM5RjZ}IH*9D!HBC@J*pWE);eiT4&ugfGCD?~l0r>yfi)U?KAO^;D?35Ez1 z=uLNMa#@S}PCXH+zTX(=k&j90JB3MR4R~VFdx}~p<#AU{PRm_?JHftPsz$%R50cT} zuJiH}*p8p4@~Aa0>&rR%kXit?-P7h|e;JMu!TRBTxbL-M%4l(TgVL5*(E8=pO8+QZ z@wRi*+om8QM%7hkk=t_9P1U+n&uNL5FVFCf+gnUAbyM8B=IRgv z#ba)W4LEupqDevTHGh{meWsb>WxJIzcR~1?AM$}&Souqd=``0OZjAdQ)^kD0Kq}1X zBA8CaBgKuo^0V8Cm~!xGDP0&j4>@bLUye_3PwBR^=*9cs1dnJY2T$XWW)GUH$8Z|W zWRTc|oWF$oZ68fSdZkhgQA!OJj5vHO&=M4MkATmtc%4gumov;mp?O}vZC%KjxqHas zxhdIRs@IX5vC>u$nc(bEOvy}{k1rM;)$%|dL<&-Oj0_9fxcTL+Oj(X<`;3*alqbz1 z$jg(Bg0S}F=d@b3V^WE)Jnz5@ukW8<&%(*P8)d`FnEOi$hiZhH+_p+D$WmN;!P`Xnrvh@<}4B6%#P2nqB{6m%Z8?x-OY|s6eCcYk?#I19xaoETlZuFLOA6B6$+n*O;G`cGGm()-6(|M2SL~K z@WD&hVWo=UW8A~K^!0c%reWG8vJh-G_{t8+SUL8m^9~?k&OgC;E2B zb|!5?cQPLPSL8-Ahj-)=aCg02$9vq#etU(8%WI@anXu^{@_Ldv<&mE2 zu*Z9?DawliLtj29u8mORyIvAq zzjwyDp@(q-ewH&GcS}QpY{K&J@dLvfk@BZ9CJ}6Kf|Z{360&KrTu*cpDEu~f_{z?3 zrtW}Ap!~Wj@NGangh2M5^ylCJN7BQ3Y}8b&h*RVi0wI81T-T+(B zAh^@I>jPcSIH$@6$wn&)OMR(qA;h{i;LaX`9O{oijr`dLI;-j8bpM$!kG+>x;{0bq z54~TZ$6|1$MV|+xc`zGf@n_LKM`Q|)#Y~tuk%;F|hci<(1HS6=rVJFNpG0yRweow7 zS?1&10ks|&Ns!mrWjM$YvXcqGieL^k9kKkns|*g-TcdUG8YU1-ENUcmy+p={9GgbD zCVBxZ6zmRQJ@QK3swkdut!}8+3NQRu@(q7F-JgyeV&xV_agc>yIG=ih;}%&fZ;C`LN3ATpvGVb^D%&NWS6E zQ<=$sHEOSvF-i1zs||rWz-4D@W&m0gBGZ*qJ>!%%Wjc%oJMjfwDUa!HDRn51t>=^n z2uEjXp#(E;NDA;+c;+9*nC9JP)2|cPDm4!`4H+?)231;ZQhItG>mXu-tCJl`NIkg1 zgI*f`;&JQw)B+V)%Kp1AQWnC-0fi;38n@+X|}vS#TFJa+>;_+3i{h7Uh^e=S9GSzSQSCd6xkUA>XR0ne;kHP|4nZTI0kO zsPR(dL94~cR=Y7K=?GU{Z@E~r|6XWsW;)2;Q(z#qjDjo4YgXeKi>b~$$m+CXI)%%? zC)iulplemU{uLgn>k|1O7`?^ZF~iHjJwgz8TRiFIK-#cFVxn~xknGUIx0fw~?&U3i zjx^0{+Be=bcK8Q-N4eWkcPeeY?aFjhEcFHLS#TgQikrGg>&oosH8k_`WTSD^&o5ao zo9InO;}JEF>nTL^9&tZ#F6C&keR_@Kez!)&I?152|IIINS`wV2`o|?sc!Wo5(qn8b z@3jb^^Kd0wmj%iMa7ct>Y=v3QTQAz*SLR;ow+!8ep%RlCMzK6ezyndv%;HR=+Ji~JUf?Leb6*Ka561nx03SI-j!maPJPZgZ&_*9_`AwGcrnH|1njxAMl5z+Ez{ebZ0s z`{-a^rsCD!v}Ud_b{oBJc_s^cdSdNa3}ZnNz6A zjs)3)T)}P)oH8!kz6B0Whk>_2R!$F=UFH@guhd=ofs#1WLn2$_6imK#YX1lpJ%Nngx1U*X$#psjqqPYwNDu^V z7zUBraP0kuKPv(1I_Ql^+aU)^%_)pPft#xgHn+JHipu=6BCZC${BPS(uxoaoUuP@ zaGOf=t5(-h9b@Z}7%9tDA88#3IPfer?!U^YlJ&7{#A6)DBLm2V2RzoQ!)Ljp`hR9$ zH1=peQegu@h%YuvO;<^U8Nrk1K_5KO{p#3v_7c_CcrW5{EMF4}2K=53oX|}gkXh}a z_4!xVsxsq4FN-#7LG+zoZ8!%uTy}hdy_2?PA;-2lk?#*Gj7N*Kraz}P1%!h#TY(m| zgZf_G!AzrGr)+{7P_zD_u9lFWQqq0$K;jeKB)V-rG zcpNs4*p}X28BXg;f89p$AX7HFW2Zk~xuS0RQh&adhzT9ve)belrGi!zdehC?g0pF% zAzB!PO{EICC?a;$6l-yH+#Tp$spl@|06FWmYB!2bBj^(u;B3uF~rF0|~STHbdCtRl=(D;EvGuC?tYxV8B1~;jj z`FMEN-5|qz!J@|zo(DU!K8MlYW~22JXAJ2}eGklBgaa=u&2=V{SdCeTiX`bVMf@+H zBqoE2Io~_RK_R%^w?U#$B1Gj>2tCDkLyioZNH6y6{hh80Kl&{OzJU~)(Xe`Jx@IpD zMCT|MtAU%Qjw;3$)k`_dM#EvR2kycD)Ob^dT*D-Z%@{?}6asUA$#^>l2$2h9enUl6 zIF}`SUeKMJbaHlWQf}8>?hEq*E_A9PwBh{m{K81CsTm zmy}8la#g}7y-vp2D1iJWTdy{!w(a*epf{{eRm~#ofZTD!mWJTor0G9B4K7#H(t~Ie z{<+GY^{H~5VD@z)yFk#oN3iwA0yQ_ScKJ%N^^u!qjSIA<=}oz1w~m|R+R{+)?Vsv(zS&_7iw?CPo9MfDUv4O2yuFY) zY$bOorP%sUH!pTQ^=gz+B~A6A8K6OJX_PyLf@HJ4L0mEUnGzNJ8yF^NWcs0QH7pwA zdDEwJyt}Q>8Y$#z-=r;d4y&8yXTw_x=rRvVI8JEu$P6QaNnGv`|6aPtm1dZkcHOk= zmk?ZQ>O1NGVhQDK4BP)GmhurDrX7l`-s(Xthuef?Z>IR3eb43|TbQtWxwJdBum~n< z)Hqcs-oWzdn+UyybuWic!Dk%d+)8krxEW|=Xtb0Y-I>3Ad;kx99-noKAM@ZgjRD9V-%p5oZ=kQctNlyV!V*|v_%`=S3M(wd>L0bNxGM{(c(Ra*gFhL11 zkP3WSw=XFL6-K~70o)2 z*W*lq6=mQIlY3QWeEs^ou(fxitsFIK)Hbxv>3xjV?US7cmEvJn%}I->EPn;D+)dNb zOM6%L{&!xGG6&<{-17`$0*#5u1ug*W` zJUdb26$-~D0SpoJ3goFJ)N@#*ubF<^QOw(6TnDXpcw|B@T^tn-8kI2fL!zKS>j)J3gn^OYAof(hr(JSNk74fR>0ZA(T!E zD7G3^=qa^($nP=p?r{Q-GGNQ-&`SehZo&PW^VHYpMZih3z8Q789&yHyI|5 z)ll%s{x1%kzO%I8DHz;=a)A8K{lntW=XvnP_qwcPBV`dz%e=87Xo_4b8e)nl#Z>xl znMs`-t&s1PE=4KZJX%Blp4jp#k+Bo06uZhseoTFRNcn{YX&LRoxROWz-Pm9Jj!!8y zpf3D&pNzOF*k+vBCroYvoS6L3dmx~_U`W=iAqDX&)VghELqlY7uV}E;VV+Iuvt0w$ z9w<<^2Z9b3hs}OwLN^qwp;a1EH}#eD6k&TYTd~;M*?e{@m@qsw*oxcrSNOQkZbkU% zRv`VPG0ZSm;LZ2J(hV=Mzdj}<=W1}2Zh7~WS}HiY+mKEs9H{^;p$nYx%ZzO)w-UYL zhYaONCV0%+O@%=43ljO~}Mx~JG} z-a#21y^#wlH*USd3`(d&wPnYDFesQlkb1D%lOG+Er}Ir(Ll2B&HWkL1_YCW@CbT4@ zCf2{N#UzQ@hx_0&{IL4drvcRvY2cKT$$WjQG>@Lo`;!zEqeNjGwnthFd45Rk3hQWk z5}xpv*c-C7P3Fy|izUzJ3&uCJPNLHR=0eLaKh^@$D_oRTi*G-Lw7qchkdMUl69%Qz zmVILP&k2ORY<}{W?lTe<0A6W-JnZ&NFcbbQC^}v5)Exkl_G^TzvxRiT%UNGK%T_4U zWhPkGu2HbC?+{TYd5K6#UUUEA05O!Kk&k9es1mu`){%gC{&rn|-QW=|Xl>TOgP5A7 zA=bAwz{UJzni*J2&(`ex%o*^&m=(mS;8^ z(;&mWH&`sdR)0}-ls?!$?e6^>{34&lPwwQ0r4}1SfTmnB3k4%7N zwEP6L*PDrciH&nX7=<}ZgZX+@_ZN5qfE4u2?b9vEmVObGrsBxKfBVb|#V9c*5Pv=S zABgdpkMWO>3MGb5UsMhRxK@oOnXQT}+saX{$f7y}x^#{s~D2)VY{8&?M6 zB{m7EWa86jl`?^6Y1MAT^PYVc>=!;A2>NXPS-J6#PbuB$vk1?6=v|>R&EiyNevk47 z`WNgTrO%z+yMNBT1qUd^F!M4C5Z>N%1iyO$%6+=!iQve%7C-q*9j-*}zW}D_oz0KA zD}Q|CPgG!yGeeA6I5fm>FDLwOb>#o=GlS)aq!I^Oxc?{E5|av}$9a9`-nK{rTzESIYfBs#6wr z_vALanhJ1%?l>ZFYC%c{hxPFhc&OOOosZOvR{Gu@XQKfn_`lnfy(9c7=6^%SQ$P_L z!6>obm&$`%K<(KBFRLz{cG)Wg=Bt>-<;+<-cR?xo*N-k&JMf%+>r*sHXLCte z54XXKvO+jZADH7oYm1$w_C45#)}fHPr==>V&Cs7-2KZ(_c@eZ63eg3jeS!d=1%|89^cduNPsq+>)H*>2V)l0x`F9q|^nlLXa=2I(wlc&Rt?v~x<}&?% zsC(ZYC)rD$?B{AuZh?f*>6dl2dX5Q<%~X z=bjV3{R-b&*Is*{v-ZBuKV0~}!1K&;-=lxyHyrJL$PYuT5GpYP0#U3wpg&|8787$7 z5P8Uyc&xa=y0l)FXMt%jKxL<}ZGI9n{(WyKV^1zAEk57Xni~|@mpJ^-9~mXViCGtOs^)c==Ia+&zGGM%)|r z0|0X^^TC`Oh2uIQ0|J0l>|V0_T1G5-zGI?*qvq0ZA+7U-N=t#}*!oJ%%v?@xLC7^S z&7X7UfOp`mzU-b{Nr$7M)B>NKC!Zv<&s%h#Qd*RPM}q7$kN#6zi(G{}J>2V%|0S#@ zr{~LOGP&yy(`?nN`0oHs51B^>n;OvvP1i-k0l8Vn(V^EEu01_5g`m^pYA27j#~efH z6FDk~a3mV9GdB4(R6974QFv^`b|yDGL?WO;$2XNd&Q{;va0YBG zj@hil_g*HuWE`g1io;e*1twy{#C`YLV>z<|(HC@;(xvqQmt>#@Jd|20L#NlVM_%?t*U3p0W=f#Z=|Cn7I~7CebE5F1?PVpjM4E#b~kFB}3! zO3Z7dx8z$K>4|&dE7Xm9jTT_5(a$2x{O0bt`p`X|q!v^@2CW?i&ZpG%mAdmo569G4t+ zLEY-NrGbILTq-d)k_0gXUf9sh>fG~kqFVk@5HW2$k7XE`bcxS(gmM^JMYl&H!uLP} zrKU4kRByB#{+w+;mO*WW)pa}Zh9{2^2~w!vuAqe41}NgVq_(=ESXB2mAre6A3E2A7 zrLd2-p_lqI5y$R<9q)~|2D=l%Rq2P8){JMp1aRZa#NA+*3K|;z=Nq9ccn70LDrF6vCDMTLVlI&FH z|Cw-(r{%Fw1+YaV|J#OJQAOE3i{ZR5K#e-u0rl9fV`nr_9;vd3)|uyC|GF-mZaZT_ z8vJf}86foR4N6;wbZdSZm01jjsqJmCQ_vrOBh+iRXVDymA9Rj;j#+XTv~Y>W7b7_V zLZ*>QY8%~b^#s6^$QbxM_BJ>Szvr&jZv&hX^F&R0^TF{NY!#1Gb?cdg}uSnPY_Gf|J z%*;b0Q{hm~e0)*_7JG)&Iy<&#HL3m}vYLk-IJZ05dPJdpC9BJ0+jwN+E`NS`wtQ-2 z=Xm+k6maZV^fph@%0+eTBYL9N<`76)QMVzY_X4HUk^xa|c^b*z$(+ZH5BNR>!HT-G z{(u5~%e@{Hjk1SzGQa&0=^;RuI?UHbeQRD2V2|p#1MiQ8gEE=L_@#rMpKNvfvZc<# zu<}8H!=aC@y=@~&JDUqUZk^AUWz2;auc8YRZo5A1;Wu&Lu%B{Az+qqADCk=0SL&h~ z53VNdU!^_th#7F(C~;rmwDg!vgk>ZPAIATB*>l|4^Jdd^xJPn&v-x-|#f!7FZeZrH zf-_@R9eM=@smpWQfO^B~wZgWKQj>O|PbZ;usZLwRWJxxVgW;L&8r~uZe#54^SI2}G z>=JapIuHs8pLM54pJdWlPED#r=(=yz3+)KoDIqSus!I;n47QcK%O2z zv2)!0I4HPYkD7gV`APpie&WXQvB@|riQiz{Ao+wGfw`ex{qB0?F;2sU)ztKO|0Uh- znxq|DvXwcs8Jks)4eX?n$8HJUkgV5;#0PT*6M`T|W9|m!l_@^$_U)o+_O`0%^&Js&%T52#-W@Kwm&A@+dr#+iWDx^Kg#dA_|$7Q!ZTwwyP?-H?6B_!YNI)DRH{VG}G)$94D&U}gjY5R6${xnC!q4$8$-dfQ zaV|`5?fdEs{cN(=wHO#8kG?RrGGW8*Mc`I5#(dao)qimTl(t$6FMimX#Whv5TN*K; zv!>GpV{iLt?m>4%q|n^EE0PlC>n2tvY&XHvzuxD6K5E!QZV_{AkpP!jPvD+@ zOa#9NVi6(*4cOD|-;SuS;BsY}a@&eWsCe|yvFt=#o`N;lG@}SqT@N;)3#kZbsxZh?be*?@ifHjdYKKbck-h6vx z)6Q>W9#5A_=m9g_M8H!Rv#a4^Xf7;bmzSQ0Ct#KLUd?WW^f4Vcp|PtNbe_5<9~xAm zW4uZ>tku?*cE|qkCw_1XBJ#q&{*528ucbgDs>`7M=jMzQbCw~r-V5oa!0?+Bzs;`{ zQeijkwfQc~qt8aLZs8V-M+UnuJ|4sr9fedSS~c{1lJY{IX-K+LGMPST|6Qn{MA&nQ z-?E%-r8duvm8SK z0G?J<-^9jqtn1?84~Ito+D41*+OA24_`HT+@l;HGx45@GDp2_Q5u})Cn@*-G>!;DU zayl%DDsTH%YaqnOYa{7vW%73`_h6}GVL!)Udy(y1ZiNvE5PY~UW%Kr}7LQ7&JBv_{ zI$i${`>)k!bQ%0@3vca0u;IF2OoLs6!^a``xk(FES>H|FTW7fu6WZW+oZA+E6hJP{ z)G%eOl0~VmFodmHk3F%1ql(M-1|_rzfx&{%9VXr1sY^H-dv(F>G;LFQpA)O1R zYtX0J4Ias4yeF8+Mvil@FggbdbJ&JbNg6JONzOaAL8_v)jz-=0U1?A8*&t zlXa;}aTn+{M2$PD5p6Gp45Th2WBt(YRcZoGFU{!Iuid%d{P^nUYwCrQAC(Hm$%bAO z>z4Uy;zPK5KgxWI^Ui2%-jkq~XB^Z^wy;a6M{uV~<2P`z%Uv>!^UfxdjH`_V=AaWj z6L1J{go~94$E9Rl(T)3@ee7C6pX%29Sp9=u&(o5oNmt$DL4$Gn#QR|{xu>W;y6TQ5 zr4N6+lE0TsXSN7Y49Aqv>oMaD9a!r_cK~qIC(5k@0?u{aiP3714cw0y)xj%po#2>v zPHxxSSXbP*t|;OM;up}zyUGtzwtSMp|JGeYJ~O%iVJk>to`?LX5svMIjPNCUZ|!`N z3K!%e(hc|CM7(wuCi<||>{bf&>LEJMj>nK8VlDmbx!qKvnC)=muLoOp<{j|dH8)*={Z0V*Y#P|AdR`bf#2E!iS`sNP;4YXr< zvUjea8knA>c{5PZdC3(0c}a`%uG=6ZNRYch64QRq@0hr1;R>b3t&I)U~DeeJN58))^(e= zUH2ASFY)ri^dQSDyNBDN8Il1l0Esn>j5T0dty#(4p==G>l#z@R)WJe)DIZ99B|#VQ zURNA<#8*F@SZXp0`epBnb;7}lXX~cFXj8~kMyGN`X?~<@00Jq1;z1@)vkr1Ha-eh6 zKbXSucjYbQ=H<87Gn#WB#4CXs2dKu6$)ZvTa~ZC!4lpLl>$XP(z!C4Nv;Z%$;l${m zc&^KO*WI=Gkc!`%x%ImGH0pD_QW55T#gWvZBa;gavBccu5dd4<4o1`FbdA`;OwYH={Pgx}3L zS)`C8SRYDnT{j378vm^S5wJDoKMLE(op&qbdGhbg5E&#)2!y?61ykd3J5Tt^_-~&t zLT5`M0ipdSpuGa}a7}qG&zz|r#SV)~%IsADL|TF&ZPIh3PIu=ci8bK!SkGCw*BVYQ z9|8zM-3mYnDBSM>s14B~I~e0QM0wP0vg3ozQ$b`}?V#vkoYc$--Me9 zaR}9T*!f}xhk)vyB(i`YwEvP?2DHie8Q0*2*CQK_Mj4RhOhuumt&^UEIgV=`Yz;DH z=8?;8VVeG`nZZ*(XiVfySNcBs-eP?AMd%Ip`{GFT@rGl(UC=%6Y&H;PJIg8dCHM;{ z)_k}Ts2CR<&>3>qH(BQ=h7T9*NfV^qLko{WwrcoI)ZZ0gv35L4kqC~0OZn0On*f*u zt-v5TNV~HE!;5A7P#C*Giwh%@YC!}b(jA=}dfNg3CE-MzlNB8mmWPe@UK3vs<$&BT zLM2zVQyxEzK+|XjKvxX zl7RM%=-XUDW0R9_h|UzfDA_^z>RLMx9j*1`_@m$V>595Eg2m!auhU#TH&Ci^3yF@u zD?gM*SU{RY!#=9%La4@FMFMCq==cl(-lLO}&X5ZueqiVuNZrpdRsao$dP2ZZ_yTT? zdw=t)-S&htsH1%dQdg=!s6%cKDf#r=2d&s{&JL8OV!$9v(`e@%@gmf)hOUUsFK;f( zy}Uf#k`~r@L6{sUbj8%Y>PEa5qJtK-{ z^NMC|iFZOwQh$_EEXEIW^ab;!<2xem?c`0v$$|k)bTSeTJ~v|GGd<<+%>yGT$aCo$0y>hnEO2=ZA{J3H5Bk*!Vc9_>NihA zLM>*G7_a|)&kJ=3uRT6;Xp3M7*U99Zp?}Op-gXqGvo&ttm0=Ox-7+)f6(+kqVI5sz zHX$qEU=tJu%3D_#NAqjyx<2bmWVn@?15Pc8v?5yMpkVqVa2?Z*bB^{A7yA@80fKQ~ zfJlDr5CHOMLFI4WQ&(_t|3O7Z1jEq}EC-0Fqst(iRS;l%6GS{T!DPgg?l*9$|7tdd zeDXdT`?iz3Y8}6$$ROun!XrkBdx|zWw8j7}b}wB1OMhQG=_HWN&sG(wEfJ!+FX$)L zF77_{-KC*?*d5zS0E_L@ny zz$^$`ooSJc<*4WYV~R8YE)WUREaiBlb?|NS&5b}yY*4eL#6?zf-mvmyorTD!b6g}3 zjBRJVmxXV4((ikqpm@HCrGJxB$5)*IL^pp9pMi z;4P}~>btY(@``=B2=YEKFp^p-i0^&CEe5K9+uhMui8%P$9er*D&V)VzeeD0Fl}Z_S zWkFd9Xug@q6fGT{r#4%ltxYvn^Qk_PlU@E>^5E}0r2-d7mi1QG)f%MN`$;k{K>4nP zHDs1GbMB!5U@)<&J1v5Vihl*(Ocrc{Ar1BxwVi%FkbC?ZP&eIe^l+T3t+G#7FG@=q z17!_V12g?5(rC5$&2s&%`KLX`)9x25-|hdP)q4+hrW5wu%gW1?;GXTfc*ie*U?E^cCvg=5vEyf+bMGW~1pvNS@dtRvZ2AAr*#y;w65k z>3Qw8C7B@E-QGGOulpf(KXTd4KRr@_Fv7fl)+84@TML?%ji8Ryo0^6Z$V)*B<}$Ue&i(wDBlJ4VhvD_aAQ>iF7iEZ7?S zdNmH5&|`BEm2O-gLnL_@z=$yGI-T3F zNaK82`7N3cvR@3A1%mZI+Bfm>@h`JvzQcO0b^=5Aqe~ccE=lo zmeBoIrSzrIH_p`k@!D)v%)^;`mAYK)2d5%B9<_ORUPQn-Vh2)}rHh=1=p?52za%2S zJKOB~8yzqm-vd2{=vr5Mxt0&?PkUd)y%lpoj^=>82;n$odd_gA z;sd)XAZISCb7EI5PaCo!=C$kcdni5ap7?QHN5*VJ?$9^MYH(hzpRGdNAW|lTtTnq`yZlzWj%@P zf3o3Xo@+Q^g#ud*xWMIe@KHeLci~7+glsHPW~2B%zbJbH9Q|$VbIvPG%v;LfQKMwq zyBkO@9FR?=MZfbshu}=`2Y-D1i^1?S78FDP{l9)~`R$$o$IbxeT#>=RL-7DJDzvH7 zC)E!7eLU+1uwE;8?>t#x&Sr2#@|j8Q<^B7J!~bj44N@q*;P3u3V(@=g=l+jg+ulA< zk{6~1Q`yMXo09+kIu9Wib!1ltFf#y%Pt1Rp-v)NQlzMSzbtX)Z_g%|Vn<~>6=t%OG z8x-%qe47e6XVUN904DwBBSsm&6O-=vU(=2M9z%-^?Lem(keB>#9xoE%1adH=ji2uT zp^}P|lk68YI9}#nIp>HOP*V+o;xadgzXYXJ= zj68+zIck_OpN)mYyn%hWaMkz*79KEO*gt8hN(hDeD(#1piVYXnJ|}7KLRP}SPLJ1{ zF~B}Y#`_|zhM59Lg1MaA`1Q}kB9wzzp!4;>VIVF~qeL2Pe^KsowWY#(Eqf9oJ$a{m z{oKPVK@H7MD`7@5098WkfxV(9hU%85xd!E`v0m+{Qq9wr0R1|uDS;$MB^qL_o3*Gu zzBU#J(O6$I{zsdYLr;4D_tu8r-~KCUJPGhhqU-#wg} zttI)1i3}nszaddYFW7K#|4y8d@$j+f5> zDGs0G5@&iFr3mMvR+9)ZhirNK9aL%_Cm+HqpL` zP3biL$2{zD_PjOk)M}sLJ$Wd0u}bo?&(x#XDdXoW0mti1d1;wh)md)U#?@K-%C0hM zYQid;12yK->jTc7|ASeLCg8%1M4KHge{jm>gCLyC9^F1xkWR0m_F0f21=@`cU@hp!eV1@_>kB@A z&^}!EtI(G>$Jrqxd|#o|e>u>)=I|QBy`PUHXCAHOu?W5=HfuCTij@2En+-%{2z|G2 z`s-R|hjZIKzxV@3t9mRaC%4`gM~9W3^v#fmg%N8z1T4G zK%9bi^pG3U>(bJxmGRj$dEBidFf1{W!16fFTu(`p5iE&Lo84YwDA9H0$+0xB93N#Q z2HU+h-r*z?|7s92yks#&h?3=&viV+*yA) zYu}rE-bKzegg;(vl>3t5CnE$WAa2v$zPQ9_;QPAK_Ym=Y- zVqbdMR~y`TY56VG?n69A@B&Y6Or8s=N^kqTe=nO|P!I(?THN~XKEDV^Q8A31WvEd?rymFBOh4Zl2AlL^%UMrwI=bij=M7l7x^g_` z)iEtk@^SPi3WqfclGXLrJYJmyTsoDIWmNb_bp@zj*fsdMVECp+O65*WM5Kzeu5N*$ zu`!LE+9C;>?TwRHs?;XGcD9s6iRTTJ{UT*?K>97@0U*Myx4<5GDT@1%Z<%IS**qmn zr)|<@m~KOlJN5GDn8=T^Hw9LF5bA|}FOv;|N`7HpmlSyR3ywvMsnC86^=8`OYS`)D z4?w!de_2Z`%HAAwb93|b@^XdI@~#LTu>3lw{)Yy-=7ST%pgC=BbM>5In8$nW{)zwD zhzSQ4@))p}HmzJ(A14 zZ&Pe9y#0-avc!28u7`c?|BU*_Ka~{Zccz1<8j{1tnRuRd9Q*(=^2z3(^>NrtLsN>9 z!pTUjejmKRCHA+1{#<>f3Dzjyli50%+ok>DOT$KRrcMteP>SILSP0}aT>WMp;fzE? zMER*58#jDz6P(_WI%ZPPzWVzRDaDX?q}fnShW6x+$oKN4Fo7kTl+sQoPhtR1QoMcp z91^V*&1a@nF1@x^$A_LO>nFp&P z>&DlK6+JgDGGu=WIj({05`{qpr+2Lw#+jTCcg^^9pRPO;Bj5hwY-reUacw|!lE_vI zLQ4>6dF5niJxsM*BSJ0lGnn;Hiv zXV}hTes1(Qx?kHqfZ9!d-H7R|SbTPHfcTFs#ID~|{(`7{QVW3sQ=qOGl46_p>LqHa zc*s@cqu%6x=l@HMkmiu#iH3#|SosK+SuD#-&Xf*3{FQg(E#=9hZs2L0+t(V>3mh!% z#$2ksElR~(SvCEwLQ`z@^+RvnUS4-B*sXJu_4H)RVi7m+e}!tZ_}sb;D7vxr+!c^( zcmD|sk>7=Bo=7!pkLTCyx&H@T^krno@GU+Q$g>328SYQ+DwMNcyPZ@sJEUb*T7K7* zlz=P{WhcU(fg2;^rq9oE<`I;a(Pia2($mtE1e{lBh=>*$Y+4ei(E6?b=h?jT#G#-R zbrt@3DQQxmFgIbEz2VI_Q6@~6_r#Uwo45QZtXFcI+y3BEPfMGzHond#qo7b;dpK{Q zss)xRx2eBFohcPk(4jb8W@lAO=H9t8{d1L{7X8JkdHm=hfi;2(wZ9FyZ>6as3 zmKlkzx19xA87FU~{q=HSgX?fzvD1XxtCrPzPCgNoJAZKHCq=buNW_z9zwWcQ4QmJQ z6Q|Gj>S}!8&gq06uU&i;9&svyh#GD_{j;xa2Hd%9oLt*GbY`UW`qlKPPViOB({NYo z&n5_QxWzHB{vn+ouC{%bj@~Hc%4PS3O&T+!Vv|2?z^)yumY%DMNHbroC*~|Fz^s!2 zO}pz6;P2O3NCls}c?VbSi_G@CQ_ZGF8BLBWgj`AN>#7XQqiTg|ww}YquD>H65aeI9u|##reO%KyQVKHqES(iQ&5P?Hcyx&u6|5$ z!}RINtC;t7d~H1UDrmPrWF_|4De@UAmh&UX8#BfN{!uKX(Ct()FmVPOt? zu&(D>n8X2(G|4X?K0J_8a@lxm`m@p*#u{3|Cc@|^b*~OHsSYbxkwk5M_5N zFS~@y4n6<(sUbXR@>3xtS#-yqJ4)m~8By}l1n)EnV!Z|=k83h$kykp zM0OkzwHY>riPzvf_KJCDui5`x;SVWDw5}Y%76ynp%p|`^8ergkzry7oD+bi zpO~ww-!rvgX;oDzhs@||uR~x40XK>bdVxcpDcswNTH&ZM+(t7MC#0#5} zBJf{k&j3fpU>1b*d+C|Liz}^H+Yg;_WMUjxw+Jc1i;J<_IyxddJ3kom(RN?-5xaaK z^5lj4y(dmi=c?(wuYi`8QS$hktDKyV5_;gJYBccWl_4+cPbUF$ux6-#7S-V`#)S7N zJ3F$vT7b!LJX1biwb!8ftyl*#rUz!J<3A|dCxFPRQKL9(_QWie(3z6<5>T3w;?dNc z)+K@X=y7n)mGgi!eN@>_ta<)_+;b2UM!L*Rp7%{8uUamq(u1U+xLD~LxzIhp(+~~T z);`LArlnGFVkuu!Z@qes5270fVN6-k5zs-dT-snMaLHVu*M5ASZe8Z&QU`1Nb4yXz{&csF%`S@L z9eUU4=!W8`?S(!GU9V-8w(f4L-jySSr{a94Ym=sk;deaOxj8~3FkWugQ?X*v%hUfV zfUREIb9+NsAsoq3XoOEMh;W?mmtzaf^4vG9Guk3?_HrCqQejF5trzx0e^1BRDp;a5 z1=Tb>h8--oJKFD2jTfw6mDebL8EdkCbhzIJ>K}7)7MUG$;qYX=1&q|zhW!G;Io5T( z1-or0VoK5FQV|ZP&O23GqZU+?BrD5cX^l@Nh{?0ftX`gTz<6HB$Sfl*?Ex5AVFoea zDgsYfjIt5^kz?}oj12` z6ZjFdwYP`Sd#zja_1Y{r?EKNMf+a!bCblPWbW{+Bo$!KiDGCpD0jJ*!%*V^t$ziQt zdz`StE?zHj^8L2p#O-JlAmMSR(U^CC5G`d-PP{;N-{!OZ2Wd{?gCuS^ zL2g@g!$IVuuCl3g8T@=3M`PnmSb;>a7eG+7IoBUrtM>l1Zm8c?goaqhTe_&v%5*+J ze}N1+I$!@rMT}>^NK2pEwC^2KS?7!mQd{Vdl>_s&i)f=Dd=d-E=QphdG(xd<-<~nB zuxw_m#_JtNKTa0uGSgC4rsnmSx~)-Rl~}^u-&vYl7)76aQ1*j{D|=T0+rm4!;fFyG<0wk(H1yeK;npbBM%-Yc8{zsI!$Tr?(Gwbx zQe@@T({L0p4nb6m*VxTV1S9|33iHOO0OoU0y#G%=9i;-AippRb^vzI#j+Ts^T!1ng zA2ZrJrW5Ud2f`v%j?fYe*1;k zV%HzWvBD-nwL8;tK?D4-tKlPs4fD0vaVO2^X23dP>6Q=VEW{6Vi)VFQ|3HtM%nCUh zjtceKxQ8ECMEO}2;?y|8>8$Ix8+0Z03sZ_P40CgG@(zD`9jrw+gk^bcL-zAu?iu=W z7IN<0{|E-dhKhSc_8+rW@ASLDmw5@bZG42be?xy)bX%BuQC|-H$ba2=?s@*TgM90W z8PXrZGb;`Iqh=S7V`sO>UIPBU09!q(VBsU>?M$W5M&T|h+*>4ENBz-O;a+UCU0G3B2XRMqe{lvt{&@$qTEMK?TOANW6_FHUp0!dwJAZiwZUbea)kSnE zNlKqn&)~yGrE{(d^Y$KaLl4PSGe4u$4*v#9?S@iTw*Z3+a;d=AUyZ)AgKE0BadB$0 z3cU_VihnIvBucKs>h1!Qm#Om3@OR}Z06g6_nMjkw$$%1>@F5(H0o#mSQy?#Y$D?3! zTDGIZ%Ww}8htjDr-^Qptj`Mj_I-I-p7 z@zo|4XX^(2rbn?nhr}kKD|*3AAcJYd24w?v#jW#B(GE@XUP^Vfs(^#3l;lj50Zcky z`ZP1|lg!9H=P))wl$X=mNP8ZE zF=)Fh+x6BBkz>}!VV$)r)fg9F`gKpxXP5^g7Q zPqeyCfz{pkmRBtedxd%(_=*SpBhQ*9h}W(qekBtfU+Z1=I+#iRj_^FjGyxiJKi7Fz zB4Ha0+KT-K9{>GBi12?9FTJ~Ws*5h03;1U$8mQVvuLDv7@}dv!Yk}~r<*BAcuX+5hjHf zfvG<%VhhRfSFiF_1@rT2pEt&bL35+g$+)iN&$}ZkRzkfFhrL3MYm)|6t#a*pm$B&I6>I*`V};DeRpYKbfZ?l|6%@aI;*MN8 z`{Bjh(Pd?2Gt!D>s~u2j+W)?GiMnrE6r1+FkV^%qpJL<9_D>H>-{-5Alx0Z<+?H+N z?EVZLf`EDB*zv6l%C!%5&-iA_E}AY6k(g%+7ds|?~f5lOCVZP0c_uPu9%zHwgT4h@q;+F;?WN}9sBo+>PUw&6MBFTx`SPperKjim+#?_)KDrQ=3t=yq(kT0`>I{%LKWytn2T=3-Q@BdMYr>M0l3A%N*h7D79x-3icQ@^j6m*6L5m@awc{h`^@L># z*PXi>MRrCh;s*I!H3qHM;CDRsw<2i+phfe;`C9axg$;fDTiXrC!n;}4<5RWUBwRuB zLJxfFyBmd!L2fA=H>9;O3|xt}d!OWH)QI(iV36xZO%eDs-vI7?S{ujhT)zORMd%DC zIwqb|!gkh%BdZUTN2oY`LK%d*IzB_hT=mB_&~QTCotlrIjn?V=%PqBF9tNCj4Qubm zouL(p#yz6j9{^gr8!7+cA*RZ)A_>gh)qEN2xX= zd^)~Xhn~&^*Tjv*AFZ0R1*X5PW|D?4RJ{oY!{ZCO+SVc)JAD{|0LrOnbvSL=Epq&4 z9}4hF(SnFr@e4jbK?ZlL<}T!)pbz!k+h8%Eu>*sNAs;?Cn1Pr3-#+{UaOD|9k9XNf z{f_sc$DwkpRn4x}J+}y!!?Th+N8RF$$uYFu+rDwQ_S0xonMb-$;Z*$Wn$(& zG_)AsuI1Llz$G^1#u$lpE&v>IqJm>1oJHt?j`z2|;;==1O{0Q12i613bH!{@k3{X%9*I@eN^Q~lACd*! z?%XJU7O0ZX}w-CUY88wskYgULYv!?)jSH+NF1m+D0@oE zw_u!e!&j)D=<428QBes?Or%|0T)fiHRP6(5nn88G9i%n1yGb!+crtjOTf0}CV*GK;{UY5Mw{QC$=_Wl%D_x1Z zK#Dp?WrZFpMq%)qm5QkKJmF0wCZo)zHykXMYySi8(bk4-TO$j) zDk~QmAOcqRi1o>&-Nx$_Aq|JiMEm)jv4_=HNu0`G!>udlwysenN|^#7w7?w~dQ&;9 zS4b^XDpQII+`)3fIXwiw%D0_>ib*Qby}pmSH4*=~dM)3%B$Arjx+1Q{MTd#@mO8mH zk{5jLAWac9W&FAJR6g{TmXqD0~(mp0(o*q zsA4`3D6I7on0AR9(Dt^M>K%>_Ct}x6sUN`_j+vu%cv2gefLm$fMbv5y2D+6nG=uFtGyOZew zg3W1ij5D>>TDEtGNv}%h2)f-szdTx2;@knC=IHl8%yWT#gy3Av6M%iT)^uB#2U8-2 z`&8j9D&sb8oUNCCk@H@?i|h(fP9vMFswbXV*fj4d@$I9ItjWH!#pb1vsR(8O&CE834p+9lLXg#x z?qXaLk+8fVGGt2M6fDH(wf7@AzakVF1`m3*;e$-PF823$QCI9RAJ5CIL zsV@>Isff@YbyO1u6?vb8-;5v=F(-(Ar_h2@NYZLmL^Z~^ph$z%e%OY<9r=>zRPV1wSa6`a^0X(b4BKn@Wb5Zfw=aq$jq;G!ke9N8dsf?Doi+|-6{4$184v%Uwmt)+{;p>Yh{$1vA)UR+`kWk1^B+gH z%m3m604;HkeWx(v9A?hD-eMjnua|>pIS-NpfK_2*1*oov zF#P8?`Oz10?>j#${0GdYV@~|J&wVtr%(cVviT(VtCX5R0UcSf9>VSJD8Rus*Y;WE< zvUI~iM$v*ASlgjdo&xK<=k9N{POsSC!jJ|d1;_@v1u{Rm2)>9HgQ67p%!=T~xE6o@ z*GRz!Z{Z7l#~UjyCxLA5r!PUmn0Y)bL|m*443Pjy0tm563=PwHN2Q1E%Bs{F7B_BiqAZ&$Ki86^RbX; zD-AYV14$yA#OE3%|Fb_nJTxS$qmyW8XebTfRtFB@JXq-w-iNM1DYmjYP6{Ya&VOzX z1M>DP+1VFAMFC4*M0fQ^014*(FG}z)l-vIi2}Vb&Nvo)o8Jd{LxVgn8TlHi3MBMx= z+H-?TA-kiy?QHX!ffg7HSsg0{9&DsgpZ+e^07ZanZzI764LNZ=08XA#^iTik3)as| zc<6yuWGH<-z-p#8{hg%;E=J_#lZ&y-`s+X7DW} z8M}xy-d}>ngkH6L`_`JCm-k?8&5o9nvq_QH%op5jpzBz~Sp!Be!!vC-AX(7G&0yuF zC-Fl%?|V)o%<|xA&9Z+3am0GTc=5jm@1CRozW6rfRg2&LwRRK8c88CI)ZEUhlGzxK za`l{36geF!kIfgeFmc-Un3bA3Nle2g`muERcpkf5qnQ_@YPCEfx=M_KPRo&B(|ncO z^B#gyEd8$V`s{}v>lqN;;kOexxw+w8TFx3{kh7{$=i*EBzTp)t7L|It!=Km zx#t_E+#H&G`8bEA2&0$lbH6$FAy)VUU*~c~!fx7ICs-BC^)?<-t?5#(%y2a~J#~hOPWSm`<|ZEVMgn5i!6yzR_>80j$6QRcW3T+J`%{NJDm8el zCao+XWAbX;W)!RA(!Rxr+L}>x3`G~GnFD+O@1IjI2@k6b4}2f5h-zOA{(zT z3?f^pTKSSn4XB6M@p~=VvbGmTQUbRurovQ)))?r%kg>iUdoGcTBQpMkk|Op(;jp1! z3;hRNNax3Itwxh$9S<@4>oQjjy2CFX?z!X_M-76K5bva054I!x70%-jx0EWVL{@*l zU99l24wC~(wE`3tbAKaUu2t4a6|-=Vokgq8>LUT=aALwxjsN3H(`P>qC4caYD@5gM zTl-Da4Z&S?x#y_bI{y^Jk#u-0I0|hSKU|Kk2^OFTPAMW+JD#L8%)9v*i|ZE3z*w0! z-8^fqeP)pWQr7}nlbZ=h1^E^9vsCy7msOmWZ$1_=FQqYlVd4+#oX)f~dx02AqwOaf!ZGmjFfeK8WOmOG9lE)_}cUu%2MO(ADw6j}F^ z(=@N3ut$fgI#6Lx?xJv)t;6yD7KKxk#pWVBOVMtNpyR`e*0HC0$q~N6)8D__nM_IL zwM?Y+jVE>LyQ`rNWxByh!qqZ@_Vo~XKg+RfiG3%#iPCqO#kPm-RYjBj`qhRk3Im?5 zoBZVB2KB^0;If~u`Y4~o6IqXA&MOluQkmdxc07&9SPFaPt^63i_)KOM_s{n!wwG?6 zfZx&YJ;%fYAkVk$|4LMDo}Afg=Bvcwd0$25&{`{WTh?;=-y2#he9klp~pp`H=S}y*ne(^Kyy1MxwY<7ElgO zMU{48U}b7|yZ2Sq_G4u0qy3((4Kj8RzZzN`FTrecZNku6-;)Zxq7HXE-0feg(Tm~# zrja#Rt;e0D8?Gifb2&hjFBSH~ZJUe0Pikmv!_qz>t!JOzxOs%bu$O3ah&z@JY1=_jlQEge_KHSQN$SKn64VCttr`ZmXBtJX~1siQ>c@7VS|-NbK{a z7QP!T?DZT)%-rBo{n*|PY;je%p<%+_F=35jEmg?UX{_f-Z*z1u@>&Cx{fOG(D9!+R zWaRZy>YWD&GmA(xA!l$T{}vuSWEKY>NKI44h+E8Uy^|@AF;%zHo{%}bDHGeGGN%}9 zAkf(a&S~*^PW}9A^he7)TNd*2`P}epNs%$wRYr8CBiYL3rMy!Lg)$XmRgglJWtCw? z?#AJ6{*lbmJn1(~G-TD510MFvin*!g1Y@i^c6rZD7wRo6Eb=L>g0eMp2~_GbZ3qH` z<8u0dUGE=BC>i@|L9t>az^A3Dt8YozEjwlb)dwRN-E)8)Txi19W6CA(6F0kkp81HO=AqOgJlVq_N^w zqgBdb3^0ap%ZB>8xis6ReAh$LJXXyrw;q%Iyn3k1avNR=Kf(Hu;d6FvNdsJV3f@Ok z1+g9nHiiDdq~TRKQJT5j5A*b=d)o>ONr-O`{n-pCxvkz+;|yn1dt6QFpuD>iZmHm{ z2U?JlCW+&XDs>bX8-nuXFDH!h*RhF3kJsXr3|2%BU2BG3r%KQ}4*arLwZAG>pEZZU+o7qX{%w5%&R^5CmsO8j;km1e__O3lp|O3gYHc5NiY>lm|$ zAN&r7O0)zEtBo2P4~;eJ;BLibN598V5gjRR!fqbL6^#45R{0brjW}4@qOw(c?sU7_ zxZY+0lr~KqRZ2ayYCOXS332DTEB82D$6gl&$Nnijta>a_8m-HxWLM)!P3P=HM^WLh^|OBY~M~#89`UXBxFH18?0XbJ)tYw3E;Hg(KgqD$%MN{)Ryru$&r59I(S_`t#(jI{D`1Ov6?ojQFnyWyZ{R)O?Gl=yI3-)Y1+u z;j|{fTo1343oxz|vQ~^%N|g9N=JQCpk_}Jy837)*Y+mBHmoiUvZScr_wIzGV+?jT= zcWb4+EmhnAm)3f0Hyc3P_~IAq9NPS-Y1k?PO7e<`a7%I{6*#jLH@Gyn`;13S89m|Y zhvmy}k*4};J$MlRF5 z#siJyLP1!b563~m-7VIoI`cuh!;wC-Q367wQyX$uKJJC*Y=3wYznPHi_3d?H7uy9F zq&d=3(P5#m9yj)D@8Q`l*{?5cTG?CA(swE}+sz5?gwiH!=57$;RTHTtzNotHxDRgC z7Rx9D$OHjq+1_hFy}|qDUI0elR`M1W&Bv3>i9=VX`&{W;?D8FoX%Vq6V4SBiWP6CE zf=eHT^DViRsVKPnJbO+$&WYw#i@d$T3EtTY%_(K>_5VZHTSqnh#&6>Wh=3qSDN>?{ zv`TjT(9f8ZgbB@90e#$(WIhUXH?Dk*VxbEpLJ)L0MNf+_tpN!{xxjKI+(hU04lR` z3!c|w7a?Nrge@m(Ckgt#jH~#X3@1Lf0ip9)D>gpn-U>XRr29Le`zl0-2u&OSg*bN| zD~pV;HYSQ?KElK9?@RdqL6{Y8JHD4qVS(xf=5tuwT*%KSGUqn}jsOMRbL zBU>?Rfq?9=Ox$3#I(eNPUf13F68N4?6E~9z^mNS{NB5DOBlR+%!lMx#&!Onx0tV!; z4NvBIUkd`A|FAH{LPHz<$*J%Bm3|ijRxqr?d{8$CH%leQ2rpNKat^AvF{?QU<+j(; zxptK^R*Kf`OhMOD(QeOFKN-9l0g>=?zv6ka$tz7j4a;?HFGZqF=US7^8Yia28^#^o zSvQN$+o1fbr)9>=e?0a5q1&ahl5@Q&Z=f}h73w34O-~rvS&i(4Qor2hc$~i5c%t~h zx}@z?@lUk-GW`bYpix)P(x2-&U`6aU!NcaQor4{*OT@qk&1D3Pr1=h|NyI&}iEgxW zUPhwib8*Ifgun!q#wtJrZd#x|c32mPlovX_w4-lp*Ob^b-LS&`%%o|m)Nj>0cz z9G{jKH%c$1Jrb|43*VON6<{P|yK2T{<^GFQg1o)v%4f&>u{%Aqs$2}Pq8-;W`%N+J z+Fj$`61^JKHw}%GRCH&4Je)!gLsAA(8IsT6pC|TTeMz(!CUEc;HeR|-FbegFa2(P{ zu)AY4$X>&1Rx@LuPVvw(xL6S%JVrq{;YWc|!qZ}NWkpO9Ef4Czu4Uy2l=Yry&9nRi zoW>FNGjjT||6K})0oE>{x`}$_AB<2$UNRM!oqDz6%mp;q2KSd!*>p&q;rI(196}E& z(Laj67$SYjMG-tPA%v(+)D#qVqU_5q84;R}n<7s${&^8d54}?G=nNsIZT*|xv3JC? z=)<6QcJ)VB*J`8}k!b5n^OyxHvpP$SvhL?6wMWNl-rxhl8n*KQ1N#%D4B97R@-?SX7+_b_F8F#wgGZN!UuTLv9Yyb(cnn(VEkJ zI&l~}n{!~UrJ<*}+K^JdU7}=`CMfYH*=bwE2-s!@KnI8cm#YCePDfJDD|YYVaV~@g zL-E~%_4ZYN-Z-@QKkhTT<~>N>YkddKI~~w+r~=jZ>J|c|F2J?HZjc0CdWy226v zcAn|Kop)St0x7eYD6gZ7`Qp0cwxCTB=9WleQn^wUx0G~EJ4NFI$hQQe`1Q9af^W#1 z-+I!7qrVsN#oB>@$bW1`6}GVCRSBPm7OUL+vR`flTs5xfT(`%k8#9)@-$l!V?%idY zlNs?xHrnhUPy_1qbAgbvNBiDu)FWlMbT zG6@;oP&+Mjh@{ZfPiaG9i^^0f;&(_?2JFDrDQ37AlXR@_`$JgqFF2>OQIEYLw1HDG0HdYpfspNr{ zpTago{liF|Vx|j`WKUvETYi5&raY(|U|O^2%wgb~wG{{Gq&;?uyv)0~NK+CLn#;^}qWK zKvXo+2aq5Md4j8bGQY5t`9E-+OX%M3N|W;JgHH<#?a6T9wJF(Gyv4yk&2ZqcX4Sb! z)!?q0>UPe=W_)_6Oc(j?v9cIV0Ke|?7CyCq(BDgvJ%cQO>`FpQ|M62I6#z&zfEQB0 zN}UNVIW}V9V6*;|In(+fTeSovHI$wzT6Od5OnwNoa;qwCy4=U>72ZMAyQMS}%MD`x zH~BB&*X0m{Nkb*R_>20c^ws)*dx0iTVH)5RAz~-G)bBbf6UG&k*4mHmvT;Rpr>tJs zme+}?I!tF|Q*Y(YFmp_t6u!_9zc^pL!A8DHEN?Yds)jDO_yu*{c}pgHR-0JlHhzXj z+zAc_X$6;87lKBI+KH*x_^K_xMhV|ZjhgJs7r{(5fHH=l<6f3vAv}EC=TI*iVYG}o!HngZZ^T8m>Q98&ZDPV zqAfTDlToy`J^U0o%z8pCb@@}Li#~d#$G)NHmql)Jnw6U-h)<%$7v_8WGsLd2$}@Q~ zDQm!5dT0@{WdpzW(Lph^Ofj>gRq6XPGe$rES56d)U^g%#tp0qC13jKFz$`S>h1uH} zruxlwWBI81=8@!t|Ax`X4iGnLy!49zbeW#t%U@GnT~>3)$-HH$;o8g)f9#{L`TrU# zSGM-Q6!}^Fm&mc@wZxS`9=Hj&{gI)zHPVON?WxuZ&%Uz9e$j}_n z+qW-}wdlZs-9R(}{fma_ART>&(t71HHwbco#zE_N5h#uw2Q-MPk@n4a**?}86xHXm zp=u8c?ox#~X!4{wHaGWY*(v#2I{ZxLpC%&;sAgm2(ywmOjXDGUaGuCLrijL*Kw>5V zz^;5Mj7Choo4S8GvBI|{#kRCy&8#AP&*30PdV6Er0d2+eOQcDCfJie#P*-+j!?(uJ zt}?%EW`CwWuKc(hltG+=vYLL(hIY5$Kzo{+Io!6KJ*nG}Iml6~{CY}QlvoUNI4gz^ zU!Ra1dRUk+kMnub@*yEL;AS0K5v!w7gu(2x-G(Vb>RQ}sGnA-zQB5ryZcSG7YcQUf z8OYe!8S8T|W(1EH)iOEfSIY|It0@59>HHNe0}jT>&&+H*avPUD$e3(7OUym9J$PY{ ztyBzm4z#O|Onj`esofyWnBMa(I&bwW980Mg-Xr)wc@BAx0H7SIYu5b|@Ohe(>f00? z;h3f7L9aI76+f<|ctR)QoPN4q;?E@BFyqT0y1)TOb$BHf+W@K=wt&+gcQ-2XY4AGx zcIyD}tC|*kiNf=6O7vFRJl46I^kBE)wbx%IjVer}fq1$-S?N+kL5_9+pw{`0_Bn*< zhJ5}8rm+jA;<8vC2=p5Q_Knhy7s{tZMft~31D_K#Q|@rrG*yM-h8nE^g$Xec|2XX( zMu;f6DhLga5f z^Re(Ut9db{Wsi|R5|1!sc?S9($hhXm5DWSwz)$`!%aTaS1jagLMmi9-9Ncy%& zr#Nj)SX_LNeBu7x#Nv`$QNx8`F1x9CYus3eB)82f1*^J+Hz}4Sf$28E@9Y==9F&0x z7Z@7MoBWq-{xSjQokz2GWaG7l15(2T+s*12`y0oxgW24~#?3eef>5D~ReD10(ScN2 zT@y3C0g^_VL-X()-6wioV)jsWZ1kU{=dsdyanw9K6$>hg3{af zYQZ^RxOyjc(9BO+Uj~tpWlH?I!c~&ZMlipl??2RU>mRu^&%lbR2SdnAM&VE1`Lt~0 zx49A(@;(AC85|cpv+t=zLi`~2!SD*tnQE2|jlD&Te2os%DF9F8R&;yLF+Py~dr(+FzsZffNyGeBMk(IE42fjU zL=}Se$>~a}`7AzeIy*(o{fh|_$=D%|mQRa=!!gS%U`kS;{!V$FWlj_B4X!pN? z$n{`;rBGH0AP$HBi=Jc3%k*q-57lp`ZmiaiWtXJeuzSD)(@ScE?3M+4QZEWA?sRpm zG7Rf^Bp{D5Oz=#|v}Akt>ND=bRFZ1BUk8%6LKPIhI_%dvWwogH4y^zHR+ho^-!vH~ zFP$fwoCan{T9?$SZZlT{GelUe^~EFjB!d4f!b$w8RIk>}J!<`7fPCDQ|7U__N&Wtq z&djmVXvf_y(c=W<6CME!^l4ASX|~B|iErM%sK+v)-4p|0nsfSX3$urg}>D*%UUcXB=umpV>$+@5v@ z7I=?%_bBNSq{5g0iI|Ftp6pCIrnXj>&BEfq4>-5~AHYhIAfAiC@RG0~@dIeYZ{3)C z6=*}dEIoTU%y;Sm)PEvIiwIS%a^)${9bS0Q);Ffj_A%rdVuw!9wlaj;rG77ss031? zZOuwv!$t+eHAZ}~P}W({y0F_^N;Fqv8drav>fVe56}zC>dd9lI^T60M__-YkuqDz* zfwRjm`~vTil>jjPKH&mOo_#A6`4XYGQ0`Q;@$LHT$0*@k=a@Y9f}z0R@R)!vh7O7L zEBD(s6PBu~K&68pv)uqnt6hy_ES$5Uw{9$<;#Fye)81 zduu93sb0mlCbgh|)|GSL4Pja^zMT06N+Cp%kl$p@rEShZC-iILZqvi5yVWmMdn*Bj zwSMYZ81gPc-(s2zePfuOt9Cn9eRxooYlmBC^t9lXsPtvHu1RyeW>ECAi#tcQT1IQE z9@q#~jpc$z2Vp04uvL%cjbJyicP9%Q-`#-hYgDJaw;9U56MS!<*XAJ51xHoy$GHe# zrZEKEKuM1+#{up$4zz2ebLM-NZ9%3KD;%0^{V2$?$l}s~rgse2KDoeS{0=wY_*BRW zFzRj-@K8vhpL@l@)McZSgss+`(=-8PHNETMi-fZlcbC8Z2c7n0x2(F&0l)!Uq;>AX zi=y%953TIz@_*K2EmMBt7hjJ588UElA<4aQ{@qs!R1!^~&HI)oX@ohoi4EGS+ZTofr z3NEDg>?V1@^T!^B6owQK7AA}6Z`;;rt*whs49O|4O}=`n%hRFHv_X(XW$>{+8JLNb zb*Gv`r*#-11s`gF5?8JUmEh=v7?$2dyf8gMxDYYI7_@VI{lhv={W=jYPS-|t{vOf8 zhb^PAGhpwjV9xuTlW#wPnT6d~C}z*x2i_R)Tsu3SU{VF?e?W>_kGvNIkeyJg9HQ95 zLkY(X&hjx=zo^Njbq9{PLM?05G|X~SBXrn=p}^IYRw zndrt&ujOvtEi`Y4wSNd#+HdSSu91@vavn4v zSN%Q;@PEk5ZUU+(06cM zJ!VYp8MV-Go>To%b3pLgh2byY_Cb@OF(UM_r^k*W60?JFISJRgZ2UYtJq>_C%KkY2 z*#E7<|HYX;GuwD3)5X6yC@8EDO%SW(f61I92?+jF)9CT#K~(o_vFjv zhB`oD{T~tz6%3BPysg}2JX$fj%fEKyxm0tvZI(#^5UU>5-FYy(DXFPK`#&_}z~m*X z@g;Uw16y0=3NzROCVib~j2pWO!s_FG!p-^J0ay8)WOhN<-AYJ+8hm9eO^&A*{z1iU zOt)A8Ds38+u6m9&Nm$?&{} ze*j^kzL;V@Eg{voc&AMV-zDipfm%;b0CdJ3aD*_PXtOII$fW>Zi(*;ZUyo_%ljaovYTwG>!4k?ng$HBb@nM~i_tJG`}MXDK-&-oF@X~G11;r% zPEIU;!k_#NgB*b7?@GjD0nY%Z@DvwF&V7vfGKBeBh7#0QHPw(pji(7#rtOMDU z5?iZFkJ{IS^ZF}|J9$3s)bxOGpo40$82#8->&IyYAk*=_7k8VgS(LOyIIIKnZP~O_ zx{OJ?DW^^hyEd&d?p{UwiRLC#3XhhU`v?gegWI8ONuH7(L$y~5HT>z6RP9y00`}7Vb_FIoflg2j3b8*<3`1H9g*&y1Dbu6#sZ?T(K#28dX z%Zu1v2!PkoT+Edf9y1zh302iCI++KJ+S&K)YfzR5hGSr$sWbrV;!>QiJg@JiD4FmF z+RUZT-{S*idMkfVtZ6J>klEUnA{uhOFLNrA%HscHtyE6@cSEo@A*9V&dFBJG0a!b@ z28#Eh9&IhsZ!l|o#hlc;ezsV{!wu3kX&E3+$Uk7pVh)x~PEBLupye}lf9A0Hs#~NK zyD!_^%+HZnVXoZ z@lu`}cxZs#q@Ziit{;7*Ya~s#4v1G(*8ii?=_Fv;5DL9o%178fEaO*;lEJH3GEVBz zbm$h)>c58Hl}VJk*#Thfw6R1LXY&fJLBbLi6-mH=jrkPHMTodF9$n81pq{=zsC`5n zYX>(R>oke7pem(C{>L#)yLK7+Y($hYiJbR63h%6YB@R3RWRy8>2ko<2u#_`izVAQH zi3+Nj5fX?Y2&M4 z{|{}j9})!09&AMLA?T2d8Nc|=`ADajen*r;Cfw3z~gj$^^5chG6ldR-V)SH_>lz%5M;YzzL zfHix*K02E6&g1ZNTZps%T{=-n_d+K-oM!GmG+mqR0SpjxrrxHmC>LnO&iz#teh?dx z@F*eHx<{}0Vt-`*Az5ks<*t8^!z*M%T^JTpc`AqNJ-`n{(uRa zS@`ue!I2?X%)&k#G^_``QIkeNmrGSUv`77vmV4VG2U=biO3Sk`mKCLI*;w1Bn$NxNcO~DFx^x8Ea=4R}#l?KZMf_@S6oBy!?IZFZ3>a+Teg09!c z74l?E)=qFbk}YYli8WaJGzoPjiHIZaq{z?^m20RiA_2U=37jB z2Z!1Bgq|mLC9XCfs;DiDaE@Lv{4#(P*%}_#HqTZVbE+?D0#w#-M5cu=cB2a>tMoii zkk%c!=Ql;i3r9;7f!X5#y1Ga?nbGO3(B5C8f5v){1>-a7`q*S(LuT@|VuPWo@()jE zrCx!(LQ%7;t4}42uxLqvq|t#5&o50~T|+;~8vFJLU9uZ{5AO{0aOh-d`bG#%1M~zl zKONCjVH&7r#?a3eMzt7?rtXw3)NxvxT)4yhvW+<`f5J2=y>OUZak>^|U1&122wU4t zM*KkJ{mGX!5|8>)5KhMiP~!;NpMS7I29Xc$mG#6zzk4?|$pkAdgxL4xBm3U!w1YNZ z5XGRZhxrl}=cYhKdo$l#3(^96p+l06g}*1rboO*M@g1NRu19-*-^357treGhjH~MOv zHZfN8FC>re$iDbhhtFO6PuhSvYLlOQM74T;YEPYr1gAUqcVT-@5)Ja5kDdDU{y zqN=wu{OO}ct$)Y0dToEz<;yr9X63842_d>o-Fmxi@v=Q9#a+KUi4*$xWy!s(LOz~i{4s`{2re<$tR#=w}iNv4iAKYBsWu7nI9}2#jPcEzVI=WDYE$Y-@DVXlOrmzOs zvX>o}V-2)n6+9-!6flt^wdVKh8{xv%9OEA9jOh3+30DA?~%`bO{I!bgYi_ zs^vY0)eQV90UX!%;(#t1Y*jD0ae|)YfGPlvivMmzwgq5ZwT(!-#w#@9kP>)2fVuqi zJKzOVi4&x#u|B#pjf~ah$GkM4_^Ox0Jx+i-OUlE^!4U-@HfjrEt?KWUt^J_(54;yC zu84E`X8U26P?f|>U`FxyR%+j?T`)NQs$hh?W#B-BT8ty7p;#cIB@qvmx|Q+c+334S zEHRZDxZ(T29B{KbOmdoJgAF6%a#BzIu zX<=nrY=#ETWC|R#&o5iCsR$U!rrWIQyLHoCEnN!$blmo736(1W<{Py*C;+5}qpg6u zr^nj&2AExVKWInd1LKus)oSZDS}^fl93?p!otFcFxqhi9UUF1 z>RuL{SuBeNwvIJt+p3kPd3g1s`~py7nerB!j9=tgn!p~AfMR{(sD~5EENFq`Ue(g# zH|xO%6lAHQW~m~(ZF9DrUHokx)79gG)7c;%N5?-ec7hGWSb9V+B1I0HPE3x=^XNDd ztw|;47RyX}E_W59i0mxqf7ruEY^;O1r>m=h*;>P5baK#0g|Ko!rZ!<-dbv;x4BpNn zvaFn9PfbiHBIDxN5)vLJvapwy5^%`>H1sp)yt z!VVMH48PAYAQNV@?{Zak@FnbRb4R94cWO`FG3bc)qa`otK(1G|s- zcpt$bB$J<8ydqvKyJwyl|L$sS>};&R(=d(qlOB5UlhyazrlSZo1{Obn6(Ds`y7 zQ};h>H*sKnaPCH*Li#R+AL&f=Pci_Q;{1RA_HAj*h^w4PWVm)nOG zImqgH#{y!`e795QK!6@6Z)IiH-qv%fV@KJYDIzua!| zqwf8OkN8N~h2K5p2*0|6L7+7oQfs7&SqX0~^&(;(=bvwy~Ch;*BJe42{+*S(cYS9g4Ubp>?Y z@^!H8f8M-*G=W0&k9VZOi!m%VlgH6JaW}HoKAcwA%BO{*9|6|%Y0;NpS8xH^EnTBa zAGjkh?zO8zn;PH=Jibo_m1w$g`B=Aabn%MWODVPSPis9p$$toXQJ=S&@RF0uAa$f% zM~sclytf8+5*Aq$dVlP_AR&pYdhLzlnQV89?hr!`gT$9`t6w%4jp6o?HQ&3{}_wOZSXv*kQo}`%5q0gB0S) zbqyKp2TNSi8m{6g>jY8qYgk zD*_IPH3{rGr>RH-J;-KjVQRtn=^j@@(Qtj$G{Dcb`mm3+pUgx7NjnaF8_g&uoIOnJ=omS0X&tk3{RA0HW0X4;P{;+vgZG1jaJ4#M_r}(A8J3& zX?|9IWxjjmc-DBEr}eNm_@QHmK?Ns~-Rp=`;?aJjrSPb}Dmw*|Hx)CM(iXc^lr&Qn z<_EYe1Dv$N5-j%T^`EQacMvx=4nw{Q*i-XvyTkgnBJVN3rx|~%FPAH;XNF7^)UIQLtE>wk(8@aHxb|<9^Z@{Zffe&(GQ`C$$R~w# zLAobZj+=tu|6%PZGG0vLt&SZ=@$O@Ne%0$0{?jtm0;@tQ8Ahm~4r&ieNozm%^&B;PwxvivqaY5dgy}tGc@7*vWaAGX+a1%PyLHm4vsi zzv*{ZY>a)8Kg6VTOIbmIux1l7_GMfSkYHI%Rd-g?`G=8%hrhe&Yp!jwoYmx)u%OpS ztuC-^vU5IQ(JjlSzN!k|bA7gS7I&P+LFKUdSp4|VV^qy?LYq#=PGhrgTiK}lj^6JR zaw-885UX%dxGcyNJnFe#9G%z@r2vN;YxJ3+Va#NP^rK}J$f@l7d?m6SO+R~!sK=ye72F?)d@ z2@7`;+*Ae-K)7VfQ(!^?jR#R$MKYthk;3O7wj!MGeWZF~9<vB$nZoR+hr!NzG`AR0s`4yTk|32=XeV*!`>n@r-ZS(i#%i8XRa7@l0H z9H5g;^iLX!j2U_{>)X<@-{guDsqw!trLpW3Sg1F8OWCdim;lX25OtgW#bUhoG} zsc)`jGk9d?2cDemME1zMWvKSW&rO}mF$<<|V8L?-@ak`Am|H{wqK5CwSx&4rEX${@ z>&m1CCt=XxLd4sKSwrj%-@{P0+#2^G|I{^L;~1~b6J{waCEr@xs|55x;7(=!NBzWf zCk9BX?-nn9s+~Pe;hGXa{uDFRRx$ONv72&N&d<*mbsB)n@Uu0~T!LBDx!GWs-acX&7qSNj1F{h=s^W? zFr#4Zs+NcLDY?)TV5^k3H8)E1sz$!kd$U9H=A0b>>C1o4qdtHQsj5okKcvoko($Vz zxu!?EOC^(DMkO%AGM?Oq2R9I;6)(%|%OI3}RQgX%)6NbQQMV0sA;YOseeyN?gDlJn z+i&+~smYed0kw;I^^I7aD#ux-@0e^Gk0CLDgpc)I)NDa=dET8$^lhO=iR!qQ-pl*q z0Zc8_`a{m98gD+`btx4{2l1o|S{nLVmycF^gcoS-lr(30Pgv;*E5vaMmR|h$An15H zkE(W0#AkKl({P)N0x5c)FYqIzm(qk^e<7k>*0=292inAm)9rPb9dKE=pU#>4@QsM$%i^?iZbG6Hv#RT;s4Y`_f$HIvgzmDSm zFxj0js%mnc7$oz4cmoD=V}h)EGy{m_y2tXo4j_rFDr7dpnzTMi{B(9#{4D_i}dlz3045^NkPwk_3Rt9 zl5)NHpsYPUi$#8%(4+?=NH?PUfC7-YsQ5_cVMT}kLxO@mK&NG-VS$=*KleYOO9F84?}GUzSbnRTObV~1mw(~uNCpkqe!b1 zGcnr!66^rJQMU)^WNTj60gC5AV+-s;Fp&5GS6DnNhG4G-IQ81^zWF0`c4BUNZ)0r( z0~lJi5E)rKAGts9N`awPME^F+AkJ;k41bkKl1LK3H=4)DmvDp6s`6lJZBO3;F#4Mx z1+Qcd$mIx6%3WMfbIj?nc0_(pxbVDrgMs8dPHj~>`TONwU6O0pNp8#DaD9~b!mp*O z%0>MbWwfelBvh-MpiN2QyX23sPjo$!5DUCpISkis054BzhKlmfvyThLjrilf1a8Is zo@JB|EDajuB&Sdnx**Fzotm-*?OU?WBHGFX6i+IhDSA$sYck_GxV{uqNUx!1g$jI# zejAfhZKGzN!h@-9h8H7SzNWuNy)=i(m4-BbHY420i)x1MA?u~)d>RdpSCc662U917 z`ig&g*zZ}0ahKVdKMD?QCR!i%J>Dxc*8nj;d-m*Gqv3{==gjj+jxZrRL)`Mn2LV5{ z3+@Gz1!rpO#@=RaE-n2$Dy%IWU26>Mk3TEFuhmg`p4j;; zq@u3E$!>{5!w}?FQml2ZS7!we+E^b0gf^mCW;&tl34ZI0sWH`FEiS=p(>V|KRz{_1 zlTKO^r01%413P}V)02*L?mauR?TR6T{fewl+F5YwnAQ)_O>^|BFua+vbWX~QPV@8C z5^#LN)4g<}Sil*))^fv$)OB3AB4HFRYKxxwWnd_;j`!?AkN1y8Of2;Qpg1c zaxCvA5VGEN%P0}H(bJgSIqJ-q>O?2utuo{* zd)-eE5QOCK*{bUG@4V6{qo!g~`)HqCHXD6`F!z91K!sgBhh2rVjgcW6?2;zhG`Rl5 zbgkMthbMU6`P-04uUS@wqa#ZFU!WtOJjOCMrj}dpl5$@Y6cT(7Ib~&KM|_Lr@PQcf zuW{=Y$i#tS2O`#K_H@@frZY^bbQ7h_2nllablI6&M#SI;DO}%{Ovl4&ew#m>tt{M; zB6^1sc9DXt6C-qHr69V5G&tVZZhyLVdobzR=a#)U0e2*>;b31stnrue15k*2XQ)uf zee63veLA?EENHD)ZuvH&gnhnqbL`I_lGKRCZj8Zza){GX{u&zbdb=>s!o8)H;XZ1~HPuC@d>@Ma3(6O8&m;52);0e-e6|i*|we zTPLaISjnfCjmf`Owl+ct?W-A-@dX}h6_`7kjWk3ztDA438tm9yL~MBYlOn%;dlpgA z$5%skRHd%2|E4Zdm1y%@DXUPb#v8Yn+*Qf4tU0PoPj25u63b?ux=%S|*ty@3PW)xd z_(!DCr<9WP!yq4LSoe}n#rwDrWeQ_8PZt(sc<7SlFZkN~y!`q7`Futvtj#+264QPfXu62Y5JHO0c3S~rg%j@1BAi4bMumy6J&FI(FD!LM*&9xfNA1GpW zl>AE-oo@%{uUFuU8)!)+Fi8)xKK&B;7>-b<>kw6Vu+F7~Q^vmVq+6+~G02d04pH0W z+X%BDOYIr|teJp1MP)Ov&Lf%?^5p~gmrQRB4ToDCrF4!vb;eGYWV|rWW6f!lhdc82 zYi^f$Jk2vjYeLu!2bkEQ2l%Aj%=HZ)hkm`ji(_wEoaga?81M)7_fo!@RQm z>7q)D5RYP^;WL)T0c}m~B4zwT$9A2Lj&`*kIy1%vHM8!44kTDzjM0!vvUGPmj!OD3 z>yM4_zj4*U+=QXl$-I8CMWb&Yu>i->S=)0Yz>MNpPN>J^suc`Q_{ zQ)0SuHU`R-FoVeao1&H#nN%g74}#Hi+7?{Hz5Ou{S7;23!U{L*@U(VoJknSlsSiSL zN6}UlQ5C8hI#)4Ur-}}}ixxU*=Vd!6)U{L1@xTk~Tg13&xL(F2CSUHQ{*|_pfx+)E znS1Zb9T($hGsWNB-7NC85Npsa_W4Cn()2n&-FblUrn@KhF~m&+NeTe~#TwdVbn-?~NgH^dr>(&Q`o^zq(DO?au{r zngrNu?qF+{fX)b^zd5{$dkUh4L_*IBUN5L=fJF79Lh`i=9{$4QvxhDTX*Cc^TYx1^ z)OBNI9%;;w)1!TMkd$nCF|hXRj&$3gT<8bxRE~u>iJ)hi_?}=~hneZeZ!}ooZHta7XPf8``AG~B)u(Iqli6_+4I2fmQz6H;qofaO`$I;EaFce z=Wl6J&Ev^9q)=@;s67I%le#MbS!ep%cIzq(KDvH8l-AIj`7#1xBPCfc8Of*X*z^y) zHb@{qFg(ph5`ZW<$3>6-vyoa4|G(OH%ERcKsBhS$^#gx?K1=AOqlJ~o_vtlPy8qx2R9)KB5 z-Wfxqfp>hM3fjplh~xl&DU*H4(@63$Rz23Hnvn@@N!mhLc_@yt?cB-xmhZ#p``GeV z3R5kK0fa?Gs`pTZ^!SU4k~AM7*O|fdywN{oI1=d_IP>6Uu#^$$bNsG_ zl=(qwYfE18lG1?Kl&X<Ei&7wz5&^94KjMlr?Wv1_P!yc#YQ)(fX`)Oq8 z#|d9#c`$-F*zC?dR%Ib4Gs)H(u`KQQ>{?xYqvP&D3|crXjGyf1U(2#L8k7xuQ!fc( zmr^uSVm}bN_t4CE;j7lg(3*c(e=vn6sT9m9R(iBkE15$HXSQ)-os(8P`4@qW$0Tza z7bw;VT=6!$o$Ss1(e^#2Glm;lq>Vy$^j;`g{EBguT$WtiogFPm@-MUlcNxuroR-$J zKoYe6?nZ%9;b|B8vp?~=Vx6l!U!?Px)#IB3-t~)^BJ05Ivld$UKU}T+J*kVk=XzC+ z-0ht=W(yOT&!%58e6hWNkLbuLazlqw?m%1Md9vcPTEX=84r2aVS(O z>pWG_w`Uwf=;M>oWLC<^ShZ;s$Zr`>n7IFX=b}z<*nC`Pqq8n2`T|Blt?Ac0Qn{rY z$10Qp{>^otVn;zgaFDS>C^Za!hAPy@Xjxr}C5y>lEzJ?NI$&7n2M@b(4oqG6Yk ziAE{!Is=r}K$I_z0T3|8b&fF&y^U&bc>Kii9=MN!ij4HN9$0%WrMocGF%Ui1w8R!; zq8Ip>E1;y$c{Tnwm%m;J+xhIaLjJSvC$$`Zb{F+1hC~i@cJm7UO8A@JQXiB zr%P!^K@p=OFMqGyhm!^)2JU0AMW?|+kwx@Y#&G^PZ~9DyB)}W ze{|C=&v{#hFcc}nNQlRzTaZa7?h?CCD`Ki8urZ1tBYHR?BaJY|jq~I9S~OXlqLfzm zgVMm)e19lPBYsejXOJ~0ikHtkiBlY*243yY6J;uv2ClL!y7<7X5zrViX+kEW$`-Y! z&cPG=yj?l|2{TjgBTC^QTCf8TT%7@A5v2h!NHR8rVGIaov|p)&d@}FV!#(iY@)q}#8wz=Giy2LvLTzxlc&J@+gDr%vW_^)K+5baXVDrA>qLPEj(bN29d}O)_v|B`dOt3H zV;k$2DPtBS{2~t6ba_{I6CPF1kWjnj;W6;+-;*^4`bi)y{Q3GRHTP5R$Rj#upUc|% zlY|5|YfL4Q+=0YHM6jC+=h}4x5q^SE)&%y&mYv4*v)G^4KhY@ST#v)q^}x?4QBV)~ zgNI{vZup1-&+J%Ip%)OFh~LnNsrBQx)hBgG##`LLzIL@^VwG<YF0MsHtHQHLLzdNVxJq(rpr0UO7Jm-L zTWY!=eL|%hPq(F%)Z}N#zjp){e-!Yup+-?^|1{6{c_t`TP^O>+iqnpe%=$UH`};Zk zJwM`AKJoUUT7g3lgJwZDl$o(!9kn>_?N`W168ipn>0{;_CUR^_I3A4aWlpA&TSR5q zDq6XFOs~rtZbugtmpOue8XA(uue$1ab(wr|P-8LbI<}Pm%HBAZRG0!aUn2PjP1odsrNIH^%k3k8C4cfS0TI&gIh5FUg8cL`-P6)< zq4br03v)D;w2AA+#2jijcAYc6tlwuX(Xp(~{hi?aQCCIl_qVN>{BFk2bzz7$C~59) z25^9fD>OB!2OInc?$v9T#+JHN_{bK1*ZMZpo$Q|(=f0kz4Y9Dk4xa7cJzwyl$PZ&I zPUUk6@u0Ly3%;*kC}}fBP}coR*GzdFu@l)d_PNEDw&!eBn4*pX92E;|no4M{xW^Y! z)ajVL)-P6HvxE%v$L!crIN^fz#acm?($~Zt=NTSX)lV;s-ODK9W=0oKah~bphCg`m zwV`2*RbhOujyMTgmu!>UH9an6#In{R*qO_7S}-5xS@hMYi z)=8^_Bjp`0z%}j0Wzp62ujsPC)z;CG2kxRFfB3MI5Rb|$z%}qi>2)B8drLgMmSMwi zAT~z)ukJ!(&l3sta5sL&RUrnt;cWFs9=PvDMq)aSgqpvuUNW>+`42y#WA98*%2dw? zo**cQp^P=!M@!_vFDYpzXXESN9T|U-e=yQuBBbjy6tqIdD`b6$FbU=P$zFTMs1LVQ zqfy?DdMoZDcqkKv}^B27odF54sAswKaEN>YVYfCM3Oh9;Ks1; z&R-a6KQW*3smlHKxkH_LDsn9P3z3;>J(IEt?ZXM5&c3XV`U_0#5$yA}j4Yh&UyM(d z8dZtSwoD=Gg6GEY?|ymFKhPpgTvk>py6;+4e@hV{f-*C|k`us73FNYpL;7j*=M$Mf zKP^*Hvq0(Si8WNJtHivTk$lHqU9Q77_~Aj;5jl;jr0Bh<5KAOeL3wSE66L>^~G z(Xydy!x_Y4J*g*8tMlt!f%yq^^y%qqeKBeO&+l4a!x9Id!zKRGSd*oysY<0petQ<= zM8H+VnnOeB6I;T$Bd|G3@__mc?JT?#pOE1D_N)LwID59FCHTIBux7GibFA%{L-tqO zV4o_hp|i&h(Uy&6ozC#>WgPjS5~--#ds3s3P*;3HC13N!KdZJ+LMix#^;EGeL(MCQl{3uL+a|4Gp1?RX8j5*0H zK!9&!7QF~WDnbSAU+v&fVcXJX7j@^ZV!~QQXDE$990J;I+4M_z7~keNl_A4p9K;Fcj;v(};-nlbJB6I#YuK{~N2U zY)kZO8PGCL{%vUF<`l+pH@Ho8;&aKXT#s?k8*&a2`=>nU+26~{vWdJNkrCbQ#U>|W zCf+0ZwYh#Rau$fgARy$(MML(2k2+%vpaj8i=FuRy^k9BdbABP}2OEBQuU1D*g!Hd4 z{k92|oj7L7>Ggs&rK#6;v!TgMg~E~}J0o3sBjy6KHfTtp!@eE_w4VN@#Z^><$#n~_ zae!$CTW&~m;p{qYf$5{;Vo47z-N|efp=;@z_1d za;*zAtoxqX%isub*)t&5o{Fl_2e%-HWC$@B+{1nI-v?=)KYxs$ec&tu%2-{QlesS> z)C~bqQv9P)naV|To6V~kW#ARk2RMn3f#S=Kmur3vB?*wl=^%wtb57G| zcy;?Z!?dch3Ttm4%Y0JLdZ;v|^t&rdS?nxY?EH{S$aOb2Li6q0J6)B> z(CR%j{k!RUG)5srLhNuwRQ&s9Lq)x$@qTznNM?C?_aI!8tJ-w&Ewzw+z*csWAYB-? zTx9rqdzs#&7(ydk7l!&TQBU4p#=m_#bghN31Y2}6^x_}RR=rbI?I4_?An!u|tTlhZ z)_Zafb3lLNxZWO_{`u(9#mbI^Rbar2X??pO$80l|gU{+rIKMdy7?0w5S}X_x{1PQ! zMBk@Fd=8JGLJHw=Z)^3MXB6V&lYh9E8XNbzuWCYGJ~S+29w!!|Gh(8t^d8R*R5Q`DxjwzV+83 z31D?;J@AnFs{q-TiQ~_+TcsTkEFUO?rKIneZ`xD4T{mG;CQdVvga`{~=C=^4Ee&_xjY#IG=fMwPl>$@!FAO z@`^x=m%nmJ@T<^)&~#Wo50D*A82DyD+7_e&64sQO6SP>+z$p%7rvwT^Mdq?25j#%b zFgkI>sj0qTgrQM^l&79)`2S+;ucNB|qHkeX5Cuf(P*Omo4xrMFq=0m{lr%_ph%_8J zln&|c29=Ud>5%U3e)a+U-ruZSI#ufy#wr8m=w$k54Sg<>3Z8$i!FpssCb7_dC?LoT{-& zR2o-ZC0Xejv%!_- ztoTr{Zh?yv@^m1k#(wkN^cI>%v%zg|CruIak97h#$Wo-N$Q@37DCV4WNOU5d3L3J{)PfhP!p|vUZP=gJKt>V z3uLI@2>%sHEw_@-di{QOmWx2g3fxSUQoDUcoxt5@K|V4^d_HBdT2Skz!x&n-S;1*| z7|UG#z2qU3gf~&s`A}a>vh_n;&=A9^ew0upSQdM~25IOLj-g+d7yfeKe^9vDC!yQj^g&bx_Y*<&}Der?#`D zIjE*f+5Q-{+QH4YJx)R0%)^Z+@2gTm!(~Ow!(|o6v_OJ#+8PSP1mWu`-Cxf}QocSv zC9_TS?xK`TNc*#1!4b6GC5K|(4ccUu-lX^k&A7+(S7v_Z(4p`zaZ_>QUDpMALDs_YD~W9O;W-TZZ5Gd zper}gzh65%*q-V#v6F)y8)<_)#oKU3fjfc3b|3DVBDu}FV9DD>;vTGQ_Gm=E(BAjwfxg?0F+Ee^i;1-K}D!1HvUioVB=;6(x+ z4=gqQm_hzP+CJm_bo2gA4Sf%;7jy$aUgS3Li-Zv_^mhm@yOW_UN@Jevo|U1tdNMSj zCu#Z5|N40}Flf+GX}kT#;6AzSEO_vJ!0Ma#^TEY8>F^CnOg-e?kk8cVSB4M-#&s&% ziL1C!OG2<}t#qQ4)#~$e`;^sQN=gP~8b!1{6&iZUL{H0*$*$#=IoDxo0@bZJwQ|T~)TlbC79@iIg`<>sS<5i9^k6`i`Zb4g?uEmjW^<;)BgEi4+ z2!WU(WHB-li~FM6oI|rbf$H7+Y!!|36}IW>7vZRj26DwMG($0=9jVwg4eQc1W?l;D zZm&6b_?~}2TG@@y1$xQ-&wZof+Z|s*^LA=5G z@AISWOgt@@v5XCH`I!Vm<3Xx~8`~`{C-w0D&bMk*2E;)SHTMuEDU&ImKWDN_B9etQ zjQE~o{;(!TcP273Ujt?Bs_|RoeF2GjN*UfeZN|_A-ic5~E2TJy@x&e1zoT)yB^U4r z{=R@m1c9aEN@l6n%ZyYkFJnJys+f6K&c>cyJV6=NWn0E;{w}4M-sCFS z<;-T=t>X!g(A!yNsInq%#djV$j=|nGoAe{m0xg98(>W}J3n=JHSH}YNy7s1!ItlD^ zINnO&O7>&Ps=HcdT`3>A(u;50uWTGxjFCzKq^d7HBJ=4L8TQrOel<1@j{ZsePpzvx zC8ybzn8%Ih?v^B%Yf6ps%O6wre!$&d$t`SnHP`;u+?-y6(S(JF+i7TLrb?Tr+;nV! ztqtx*%XkC_dGSC@DlOr*7JL4e2aX#KE~WT`7>_#EvpKS$Dpy^!%A73-zs!Y`8a~=;Sx{5?r zzIuXEdKHa%6=nJ(U!+o!$>kHtx!#)kua?;2F-JLYvWVJVNI+0>ZYGp<&47N;rOxqO z6O%NjO1up%lO^9+mHzT`OXoR5Kn(Z;W#-`?2otW!C=eR{ylu_IBwTI7yw zInz;@j4OEU)ru>g?&Qd~rBW=rv69Hr2IEAYBRz4KDf^L9*54$uHJ3QXNmzZrk#LR& z{1j$fVN%&)Eko2ie#41N37c4$hRVyI0-$-9i?|7hJhwfJo3z3RbS#io3i;=|<0|_= z24JPSTw-m^ICr~pXGUngK53gV+DnhY-#vIMDvAuP*W=Rvs5*naHd;)cuUf7CpcWHf z{Cj$5biaoErM!ViFZcQ5%N3Ezr^{?Gb@nqK>2u!b=JpwyM8YEFoY6;h-ja#sS6{u0 z-p&3bxl0l-O9njr{AZ61Hzxd>Eb|gD5FaF{e&Q=?WPaUB&d12`p8s%%>N!0k6Xw5s zM3&r!afpK-=bc70UY@$E>%*4kt8&5dHQ)cJ+E7B?tB!01hm!0A#{CISIx-xL=~0>c zPu>=*fQ|s!JS}}djIC2(3xASpeNaayZRCh8BSV_s&MTt#Cak8Jx|EP}BwZ^T?(E^ogI69bxxpj)7Z(b2vn&_yxuW z_VbLzd&kN0{frDWU#Iv`)m43$_ZOw8vu>;K!7;EvhN6*h>m#WOU2uI_M}LN4UeM4q z4?Kyn=YQ;J-p}=Z=p50`z>_Jp+B2NBpUJ)Q3kXOyDJ=PuoTjIB32|~4fK2sl=_MhY0A(KrXGnd{Z1qJNldcUo1^Oo3do3o7v zi?;1qZ-;<#Og`Gx9OjL}0z@b^)9{~P7ojgdOQ9Ft(G*iT=BsCb#_DVp^6NSW zwz|77TQKQ&=pTUlMF%L8T#WlB8ZFR-1O=ZiFMUBIcJW*4x$N5Eu=&(jqArUE+y{II zYf~fdoJTZxQ`$(*6D))8!-53~8(#U{qsT;I&bxNN4_8>|@arCrkv_P|EM#z8tnkGn z{Yx2=Kqo4|jeNyBG~|qVct>-9ap5*#0@-c~_TO@<{bck$57Aac+b>FzgWfg=tOIul zHRFWwq4J!%^I>{NY(8P2TEiJ4hc&$hQD(-AaAgGvzmT-}Nf!>6jY#coMZw^aQY2Zm z6=sl;iv8F`9&hI6MFkXDk4y`Q5mIX#C5-of#kjxF_erPSb}EBtt&Ul(eRCo=utQBv zn7%OU!|bLQjs9$ERU$-eqZ@v8CF>nWQet}E>!ijH%<;H*1o>X2G-TICk5h^x|Ky7! z>Zd5#d9ZhEjuMKN$uynGjg%d&DPQU7mp+f7lNN9Ela?3kAgjYEFzCsMP&TEb zr&ri@w%L5wR87+CC}8Na*7X3`F-tq7t{y)d4YcpFGrd&(HBtPIsaY?7%mw{9#&|?Lwa$HW861b)9uEE`&9*PdRWQ9hGd3h&?Y! zF025lX`(_hD$57Jq^&RvuzN5os$6DMTlA}a)3@h!Qb99(hVzK)o7|7)aVKC;Ag!O|zJjwo5EaF`qbol&+92Fo6zIXu3efMC6 zl#eno*19N$X}K7#*DQcaQ{OeNtT9BdwvpBd1Yn-#`2QR2oSF}xw|4jQQt2Kw0 zvt#UOf__YiA7rjO+mhL+^ga$!p=Ff%?10}U+L?{^}_MxDtn`KW(=F0 z4(|;zc|@KVklGpKqSvN)wVrVlQIEF!BZak;RE+(poZ?_m0#6d}dq~+kjZ8-OfT;Ci za>UsBAxkh+rWT}`72FcA^IhEMkKcSp6RhQ&$e<ME7M6)Ss^j#wHIgFc)$vvhFI z-@L4}bL?Hm^+f{t;yB{|NHXi-$eZif9x~PeDNC!xH73-?Bz25eE4YXy~|(zKm8d;tP9v zOYcBg{DG^F&>7A4A?ydOl(4$k+&r-)J~BL9Pnpi-B05bF-LU3AiX%~pCc}6KYCAYE z*#+S7c&L{2I|7#Nmu9mglk^zUt!-@sRWe_wU$z$GsA23C=8>Q*<&PN8k5`57 zpV?I+S1Qx2HYPF1x_x0cBk2*~6s24RU6P-_mXuZN%?T9t&XVl*JU>>Jp>~v%9+h5W zr=%;7<6xAJiK-TF(cq?o_Bp7zMSe+G6ZZr+Di=-q6qh=TyDvpyQ4epahS`bp#(!M@ z{c*O^uj%|?P0V$4+{Vm&J@~Th_=n8=*&DTLI}t+&{}92bthq*f1L_*)NLZip0EnD$ zUs%D7QM@bM;2V;}W%3Hs-Ep^)Q>`c3q$e!mTo=GE&AYsB$Ezx?^&A1)zk5OWXj6>D zDlb)3zA>j)f`k`NR5b}-(2q3MMZVe%Phr6w>0VtJjkp4qy%GyGjb2w$rq&B-4QIq% z_LSo}+Wp)a!#{`^3!u=F9d zyi<-`3nLZw#gaezr;&iC{Q8y0;a3ycFKzjz)S5bJo!)b!*^7-J?30;(fVVb=e}IrG z#$knDpb<-BZNSMHdRWy#ajolfGhE6|97`i>t3#to&do^Yl;k46W~&O?hBnD~8Te1_ zS`aw#q?7UXa=POZTFMbOMM--9-xH=`lL{O}TjuV-qqKT7bU64wckz(z|4P|`ead-Q zCL{IE_V_%eR8I(*LSIV68#0Ev?sr$NEGlXKky+*4ZWNhsRYAP;p(Kfnit6`5j#$~K zw(h8vSRXDkpHj6|$4lAmh{|0F=5#mJJKbQE8qBY}`u%@j(cDWU_&mC9Xe~#Xye*Cd zjdPMpal0#j`VNp*EWIir_~)tK!CtKmS%@77poLZBIH5Uizw@;Oo__ep>_w6X1273m z;m{$#_1@*EUaMnG8W3mA16p3KK*U>M^-R@}W&iZ|xdxAIEQZBj4>%@+9?FZCDVu6R z+n49APJ8W{K@QjFjl5~TBu>%^fNg^b+5zU$g7hzlXwO#fa7sUZ{-!*K_Xd87&jW*o z|J+PfQn%V359jw=I{pHd!${SnY3S(Y&7#-MqiE63ADW@6|I_tSe$)&1S>5HZPr^Xh z1J%AT(iQmTwxmT4V@_hdT^TI-vMWH>S`SCCjAe(@LV~{L9qMAhmv8)e`#n=0=JF9S z`t(%=C#wsgFr^glRL%Ot8O~=&JdFMM1#u87QJs^=7uvan0IsA*|^Im#@=xt(oN;9Q-lEpu{Tjp`wvcxsKFglS71`l z+Cs)C9mCx5?t8i~(0yd}wuRv9t&(B<*SM;Sm|r)>Zw;3e-Mf|lKcZ zlLv>nTGLX;Q^(eEEnYQ`pdyb+BrWQ8IT$uh%;7SITS?JjD}?{~9&R{3+?xPcT*Kh` zqZkNvCWRDBMM>g(<=QAKtNnJJZ23qb!{|P;=$Ao6@2N!{Qp&z*I%TmSIe2@t=%j@3 zCWx%Fm|K2La?!e&bKm~HH8nu!1J*C?JsL5Ou)EVf2@MtX>%>IIxzG6hxC|N+S{m4> zard`t=7sU!WF?J>Bbz2U?@CNpufvy{OvDnq{?$yPA3p^RB^4DTBxvymBWuUM2ng74 zu39y!(!Vay>7U+ht$T3JKpE?g_ijCXAk-0V3@RZ_$;#~yu#Sxf-+heRReLh@?RUl4 zU4%85Q~hfUTupGgXYyXmhCKA1s1?>C_w_MB^(cH4C_aSBr7vW*|vy_e{x0q{)i+QhH{7ZUX zuje3RliN*#={IH_cbVF0vu^W1;8?3&T$6+lB zcyNI$j-x_DXR~KoVQeKwh{jUcz~_30(aF^qK*nBzfO+ID87c2?}2+LAP z@3NZ@)kFdpDU+SABAsPiZeLaOOGoU;gaiS+0S4*7DmLS>5(_pu(!w(y@w*o z{0+84Zg=*Nn>c0G7S&h4xm<5LeUa2|TJEsokvNp1AudBu>hUUp#dJ&pHgD0j%-f(} z(~ZjZWUO-AZKoWQN6Y^3h1h#Pli#VKtboX(z~c=tu4FH3DHWd`Zi?DZxsiMO`aa8+ zOymG7w8*gLvas{k=A5n+`iecv!pZvMw)?>|vr&0E(_w7@T)_AJJ?8o#IAAX`#!X5) zB_*_g_S>m+*VA6t`gF}ociN`uP(S4Q9)@AUJ@ts$DgI$AzInWgM#fkNYJoCqz zl06Cw??ujF|5w(;>TIV-{?iH7K#&8S(Bd2}{U)%j$^W9Hyk7E+olx*RV*#B>Sc7;- z`Os1k)vLAVchxFdN^#r|bfTNZ`auVhq7@1r8SGDQh!qCRWQB|cv{wZ!oMqT1h zVDo3t(Z`^gs0H^kgtvEqnHP8+46f2&U$0L4;VGCJmO6GL<41oPX@*xKrKF{iQIU~N zHc;6X><=AA?N3g^`@%2n1w0DR=Sw#aUfU|VcNBRPuxMcRq^2m#>l8soUQZDEf?d7B zlyQx!i>G8LJufeQZZyZ*K{?CyQ@$&yt{gLu?Eo6{n=gn+Y@|DftTX+;D2AsBu67QZ zF6Nv}pXTv`3g=kbzUhhEk-tag99+`p7E+8<8n$kj?pgapu~fAI|oBTv~a zm^xo&*mnD%Td%z3pLBhO9CejFa~U8zN@M*%jmIsZrA=k5`hsZ0-_3SrYKhF%Zew%V zrx)MT^X-oiq<_WeMb=3rrT|3wv_IRgqvAe;R@)(s+I`@tS=->8+t;q}beFG2G`dFnLu^xC9aC;{5*NhDn=f-My3LkU7{SSl{2 z+lu)U!sloSA9gKXT&~n~LjP{oqV*3GA--#_o8#yA%vLbQgyN4YsmS3rvhPQSAz5x} z7+b;nuPE2N-GV{;Nd;Bq6XsKz=EZK(eafo4K!#% z@ZDsJD{YO-91;+JzJOT(exXUpO(&a8KCITq!FpYG#}n=gY^8 z2;&2YBt05=&CQqRHVXQ2SSxPEQL*nBGoXx!vriEw$wI$HHAQD8#zae7Y6!J+CZQX7G5`Sv;b ze=!0-Ys^RRub$z)-Pz8Q=mfCM3ZDRDyI)Bj9ps{J+5_IWtlo{nEHi!g zJV1aJp*uKOrjXb9Q^c`||4jIxxjc-Csk_{9UO+^O`g6YC%T!g2ks7PGimi0BT2vbC z?F3dW74kFZ>q{SRV;nu)#sdA>jl}zH^6JG9!uDa`@+?*|uAm3)a#2}kE#vu+GYQIK zB#2~l6)9n(Mx4CBL0p^?ADBy{)X)Ap??<6aErk+%4myq-zu{==FZzKffgx7c*N0xB zOp`zC#;(4H3mRFAFY;17yM?rD1Q3tDliqh)lk-hdHH7@q?{^dDsey<--^58N^Gj{< z|DoD}N4Yp<*TnSbN%2vXvh$T+OOt94onydPS(F%xD~VEi#ynDs>4v0=jnP5~^^D6V zHm;{gj!U}x_oU`ud(e^h9|H^eJ4oF5l1Y(%GhYww7t+4A;^#+k+B!z7QF!k<0My;+ zZLf0@7cp1X#~U+ot--{?D7f@#^OTYVzZL{Uf(K13>T=i4BPJ}8Q@)(nDjfR+Z9tcO zY7aZRyLAKiDLMv9T|#~WQDhYJmJOe3Vr8~IxX{ommJdrG;HT{UNPB%2gsAZF8Ik@tV1U8kfgv>k_Y16B_HpxNmMgm&Cegt)4o#znWkn{ zWqI*u#~%ahn$GY~>&}0Uh!r_c{fVG@P1>`A2e&0+9YZynKV-`h!;q?Psd|sDZA3EZ zgRNoa-Kb5&p-deL(+~c+rbl1l@`Wq%!rn89~m9FfKyWTe! zoj?8FHzYw3ezubmnjE~TN`3vlg66V?HCJ9!*XKC1p?)B;@#1u)v_k8m}@8< zYy4fe{~nTjFUniPpj^0HlqS04ND0LJlYF<{e#RRq?p{i93?CW6?Zfs(C<)U(Kv3R=dd{_BMpc`di`2P z>>g*878*q}GiB`gp;bpuduCa%*-8m=6Ery;63P9Gf2{e04R=yf_NoOUc=4f!%$Dms z$KO=6%o{^14=W}zQYJTA)F+9M4GW)y-OVSu;OwoxtwlY!9ce6Hy1D8ZWM^|MpBzfU z{qBJg5Zhntu2Bdd)LroFZz^*Mx`shu@wIx%=Dkjo z$){Oo^3w(l1{HYhr)|=ow7Fj&t5JLhWXeu%;MhXng zJsoat!QV-!)XdCt7*YJ_IvBTaN5K?bb&g7ykw0O#8~DJ0I^S9ZpU38&?bc}G)#a=~ z*{-iy2ThH#c5pz6Dgx{BcIW&V537rcedH7PE3q3p?YRkBn#LVz>-&Uozy{Ah@1q+O z56kvHNRUs!JZT7F|4a0phj*SnXvtaxBA6#lF%UyZDMo&XdW#EnlE9u)NG{~_j{vfQ zGS(}Tf4+8_Is=dZ^IgLv?DyAIlsP>{&9b{^BzA-TgUi`5fZ+aqlCUF-BCcX zq}V7R(a>+cTo&1nV(uy?e@NB&o8#|%Z;UiRPobiyE--vSL;6YCFblO{clEs?WKN5^ zR?c_0gQLjxSAuhJUr)U+H8cC?f@-U}M_>z!47*Ad%@sNXvZ71>~Ki z;wN}h5^*iggSa?_1*u@0{Gu%;1VA}3msBI9~5t;JYLe+Zggd9trx`8 z4J@CVGJR%${c~Q-k2c!1&;X@nmo9JEi7r~~Y@`h(^1(uOgs^nmQGS%6Vsk0xaT}{t zW@zY#w2dayMTeGHIvR$}XWhdBwKnGBO%IP!i(aX{jblvNHP9+d&Wq0?Brjsg`y+ZMTWvMm-(^KK=Z#DOccOGJXEKhY^4-2lGYJhnh)gHr34Ogy$P6Dl@2 z`0(D8L>W%R3kQSZF`f5{(IABseS3ly+WL6gA_;r>`ClA(UemF+wa3KYFD~FK4C5sM zH5P8DoUx*V67r0)+1p6Z94v8hV*r&6XK-GsG0*EfO$0SX%_26vq%Jh^tw>11cW@ND z^aM-(ko~vnyjGq9Sl&DnOTxvAk(HI@@@h@ICy3t&(+rhR#J-a3or}Xg`A3H61rqRhY5Raj_WYKCdw2-IN+G`oiFfS}}TT5Ch(PgNl>5zS<_N2OZk zazBC1R#SziL1)j9JduYAn6IA19ryLm8)TK`sXNoswlR*KeR5H^)kr{w@?IK0TU^4S z>a3Ru3lkfTU$zB)i0eC zG#(AXMI1%(Ay+4x4AA*`diocLHsL>h3W&g}m1M74*&arz3!iXItTlB#*8yiTCS37W zoqjfY7N0~wOXXEmL}4XtWMY`n5IYbLVB!iWeOWK?&yyQ^p{)fB9rr);J^#1RkGyi> z%>FGj&@5mKWy?~)^k$)LU<(a8xMd^=@u0?s>2*B=tkJxHmXZOx`2PW=42}8cu`+vP zM2*8Vb@Mx&#Rva<9Q%DaBa`ym{h)sk?VlZC63VKbcGk?`SiT+DFP}9yJTU*ZUK$) zn*O{|>jAYn&bpD4y?1LIi$&%!&)3|wqaT;Y(yGg-2d!GuY2f-#T5t-NbKmr(Z{!IZ zGsU;Wiz$XFV_#PCk>l!FQH_pMZ*-K#Ds*Dvw?B1oNl-!l_qmf$42n&KWm*^*l_3gx z*=2q0rDHU_Qf*&YqJAR(YgF)+!VDQ;JR{d!K>r3jmJwWF&6d#KS|S|7RD=VEo4k8y%o89xiM+{QF2%#lcn`){J^9?~n|F`CUT(p#eSmX|d{sFHk7-sIPCCQ%;s zLByZu%mo<-7nc*eaP8z@by#SRhtHjtbflQH?Ro(%Nu5ZSQ{(s*9ni!tpkm{aE)gFd z{)WS8E(r5y0N?0_V&RPBIVy4H@86$lHqVTNLvitY>vZCC;!wfC#V=q=SBa;~`jf#( zfCTN!#SzPq(yaM%1dq^k?`_0J^qp*9f6H8R`Ln1C?45eHdDmUvDub*>bBgQx*tp4k z8!qgk0$8-WK8#!crBeIYo$~c7Rn4O6adTn~#KqHt62a}XPflJ_^X>h!!_@2QbrExe zSy3l@FK{f$>A~nA11-kxf~fB5__M*GUDw9b`keLp<4H+ZXZy^3yf-VWymbW^S0`QM z9ec$S&|Q8{fahG<{O0DwIK>p_z_a@Z1?BJs%6B-p#+Uy#$liMAJ?KBTCn)?a1(#9F z8^3PKEWJax(R2S+A_OPAS2EkT(fEn=3ZyPC`~d{`JG?i+{r@uscY`4RJ8DQG@myFU zn{k?31}-K`k{-SG1y#ZPe5-TqtVraZt)bWl(Jh>&Z08=K5IdJ&DbUQmsmr zhhnK`CzL&qZJ($J_C1U4u zj_`}-y)Z4tM65805R-d}sxKU$2TXg2EKXV|)YeYi2*^0xiSw!+M^4<&Qt_GLi8 zqkw<_y};I=iF%&_@{jz7{BEw#k}dxcD-2kBnd&v>Eh$Iff|DA-;ew;w7g*%t#fF}e zO6`zBN&YFv!Z0fSf3w|Iz5a$L;2i9E%2q1#yyEuEI4GPVOZU4kMt=r~g)X0`zrxJBjbzl)oBx@h#*%*_>EI!5eCrf3;#r1lfd+?m5Nhh#_ey1m&Cbqidd6=p2g5PgK|!a+8=4t={PHAuU>TEm}!!Y>GZ2~3RMWX;YXd^UKP zk^-zi{|Cs*>h=0tsuek~cKK&+X8cF+`ZKYR?tm=101U-ePn}}6Iv95?VuU|=PV>go z=gFFoPWI@xbH98{yb@{l;0KLlJGKjZdniWTK13ZHCAfs*by-6F_%j_@#LuX-}nbdi;lawelkht6^DL_3F`qXa2M2%RoEtcAa1 z>~j7~VN{kAAkdK>O1}QyABwRdTbY&JebcDC>EIxKprhG6owAg(C8F5N$cG?I+x8W) znD+1uyc_3%%n_SlS_Vd~f?40OvRnmYGPMZFn@7lfKVPMeY`BLn%c1disL{izY_vcDaA7 zFxIYSvwfpJD8(ox9WY$3TG(uyP)Gf-Ai3Z*9;qnrQFH~=9ilUrd9_o6iQ4?;IZ)fAy2J=W+7Z;R@ zEy6i-t7b&F{||~N=(^-RNso;T2t9bkas#ITFR-y~Fc2^$e+Ft?|DQVP`#4(5rld>- zj5*`v;FKRu60h3CS3ybij)29T4IZ6DTf2Z#X1a|LwT5rELfHLqgE=js^pPBwisKONg}jW zJ9=YdVP$*O1$nhlmp&gOi9hfz%PlL5XQvqTW4TOmH5AwHXE|Rc4vvy5wS1Z20@tXW!P?@~sh_{$4qE$q*cls)6;TNr;OR5fY*R zt{g!!8ef2Mz=n9oze^T<{yB2)!EM)hpa$P2(9a@#*Qoj1HJ+RcuXq6)LsfIoAy z0n=(GFaIx*Zu%?wq{|S$$!N)L@qt)Qk@9Z9Y3eP2Bp;Y2#2`wWiK9KhSh9mpPBj;zvRWg<;^aJV%FEl6UnSCpxvTwQi)@KDUt z>>d6?zPc;o{&tsc&Zc;6FbWJG<=8SE2U-k?V@X{d#YD!(8%AhK(m-&}CTd9r5?v9Y zMc_!*fy?77FS4oH_hEsUECUARPE*_mb=!pJqIch5VNbwB7w+}f#7@TY@ZJNiw|u` z(sp4ZCnY7;*~!TssvtQlsBZ-MbFS{AJfdcKS>r>YW8mn#rlqLZL$+2rlwm6lF!F$j zpfG*E#abZmosyzrm~vd3PWVU-=Cf0bfBn`_5?hW~_`82W6Glz1-Y_gsK>nTm^5AxB zEu_k!6BZ#HT&}=ugC75vy5)uTTOeF`PM>eH3OBa42oJ&p-5yJzkb;-AJ3MHVeK6@d zJ0`FK-TnV&2^&!RIPMbvju%M$Crx#sl$#>>w?FGe0*n0ll(hHkQ8qA;G>~X?qnyTq zQbuzP98*(|fH`)H5o|9!!15~px4h4Pz;qT~2o+9DGt*81!@8x|Rcw-(UoX|q zoaS5U%Ivq{IINc-wrfM5&yKeR?mrxI?R2o;S1w<39kUGa_-6fc@bkbDtufYM_dHpvO0IxRqxzOhs>QGyY1rp#%6jr-pJ%;H&&niyY6 zj1wq;u+I(`#8ZOop12D$Fj)a3gQqvg4e(0#{GX=?%29z&h3jhyN%J! zvP3im(c)QEcdxF(Vx}KT1SX#Sy0236DjbU=5XnEp2b-t zO6ax)Gj*UBAIw}G5!^8cYfl2V6C7+J12Lb7qRbL&tElwC|t$ zs$^cJp~Kz+Ng2ow#)%r&7yE@JIDf5edb#bTt*m6B!rwD8q#Yc-&R#FZpsdtxE6NHA zdVxAu&RKu#MC`bN5xDQaG zOtiHzxObaLfY&BI(Q&Dg8S*MFpq2FYNrxbv=zYS$B z`XA!Rab806r3StIgS`#!fFglMK#2FEh&Ti5nmRrZ8EH zWO~^D^w%BXIg@#!>)GEgQqq=|$n|Gy)-0YnBKgJ25Xhcu{DXR&gO#+#RJ+abr~MUX z6GGb!=M9*&yoW>NK8=^3DIG5^meIzL0!iF29BF82)9^GMWc9C)Ca%A8J0JBY*iZ8} z`7lq#G;FB+C4@a?cz>Xt|L~N3e#kNY2$paX!QQk^OZ}CqnHZTM@9F8uRmdgl>5+8T z*6BiH?nSu=Y&fMe(k3^tMGq5s_xZci+oW&WF^2dc*e-rtNDrTG0k z8BEZsUo`SwGcPXV^@aYtznW=3BhzG6j1+o(wbf_@Zk@x%!xMLR+*iO9Z*IMte;T%vnn#nL3|O@ERQiRo0z0%a=7+K7hP%(ChA&1rC8?V&Po9_9Z^6$E4%k z`+Ygo;L2%TWVs2=CQBv(ch&SNlm)Sz3+L2c=1u zqg059w^1Pxc)KQpYj{HsZ5q2(i=-eYw;XmF2oSx)-pl;G5sF1o#_l8>JZ)FIM7PG5r{$rl2ZFQ&3 z!^)`9lg?fq*`)H9hRu9PPy!5=0C=$RKHmd58hrWHZ{Ji7&S$P=R7ev+au{#Ce%`JY zTkm}QU9-MMPEXHEBCX-_h*P!b!)p!KL-|+^+Y*Vd@qT}myc)|@aF1Sugz&_Q&$u_r zAjh}F?s=oEGMSC*)hvX|95iFOe@L-;%DvwO^J?S>C;YuVwXBcnHZw9qulVS0usa(T z9l!&pRnPV?a9nLq!Xz)^7< zAfaX?e;*?-!MXC*#NrL?x*o2|rR)y&*75B(stDT8*m6!;A14HS_6xx)N^%LnLTMc= zj5qcRm~lMjb~+~69#q&kZk|WWWs{gi^Jxp_WlB>W>9tY0);56w92HV~$qw>5?`rKGH1-}nYWcGUrpiGUj!tK62% z0sG2*g0Q0i!jiP!QBY7setjyHl9D13`8ekRd;|GEI=QDo;;8y&$(M`5*XDMaY{A3} zK$INX*Uh)$3OWFOw-0VeBg9B-KztDaT4S&rYhq!qS1Z|zM3>XY0Z?d)zIcNo9d4uA zc9m}rxKBVJSt4%u;Ai8EjE=59}Ii2l{A3 z7aVGkr|vsH3B&2$v_T0ZfNwH2CvXY;2=4TdVcyEGoKCNIMq|S{ z602diZb(JOY8^Nn>9s*>CUAV$+8I-r(aUolD-6Y#tekeLZz@@vS5Z`KZT~{W#r1v{ zL%bs;g%sGs_^lvaWMscY3(iYQtd7tWbr6b?=zgsf6-i?jS2Qk=n}t^>ROYJB=0l|% z9N5~5_b_n7hf7_4$*cT&b~;ptnvS-h8fB7y!fo_$Gtj2D!qnYFpFX) z>;^2?XrH*>=6H4VzFw#~k(_#v!bPfhelsr4!-iY8b?Jb*fq8p6V$GrjRs5Lvyfb#_w_#=OE_ceX=~XW{P6RRxurZ@ z_k7q1oQysFXPtGyl}ou?aU(x3q&N2srsI#T+%?4f_$1)Z?5UP~*WQrK=R3aSwwN_E8%5C#aOz>ycFS_2t5_l$ zEaJK0) z%)vhf$@raGg=uE(Rt@wa+Ll(@&p7jCy*rt-HT`qfi4di)QxrjeU?ZA*Slqv*iX%>|G2#!a> zt29r@@rqhq{RRwVZ;_F~;dSr|Aqxu#<>=c~Bx6s=Sy*C0ctt)fRmhbe-ccCvM)`*Q z>{$vVt3A-yoeeQ3 zJui?7$mU60i1@jg%CR8OMcLGxDP2FL)ScOI+RV6&#Npn+ku)$MyOpNi@{*q3=iBlp zwN81B^d3y5<|SD~$Dh*EpK#ah2Yh9fhV^B06{#oNj!qY7KK|;dcj*{nCTDo7x}LT# zy5!=yCY?l6AeB?I^u2I#Jj_I)HW{cv~L2 zuhuU#{yG;12wlsPs9bb+b;%rOP3E$*SG#OShfg+SDf#F&9JU#u2@Upp2|Jup~0)cM|QyiA_KPhU?@jwvK+ z&M`0Yzxw;TrVW?#k*5(MfVjW0A^VQ#S{Nkq@;o0MCjY7nJx&_=jR6Dxi*FuRL;3H10hF|C5tKi^hyO zqqil%bT(7e%H!KtRqUU}bwi0E0I>E7ucnK2S?l+E8nZ=03JwCbE<%ha@wB=!)5Vpj zOImOr)IkV!ab03AEB@huCg|s@=`3h&U%kTz2d`j7?c

^ADoi;Z&Q~fMyelp9{ zAFo*Owi-8gpIXOL0q=B(6#V8Q{t+a}kV0AUaMy`vQLHL|g5o%F@{1MpH#haMr)y(p zCmdOFMSch~2?lLox>>tO-kiV3#QCXL_BN_3k&|Xp;OUON%ma5yQ68P2s+wY<+xRB# z)#fqEJh-px{IZ$@v~-u!D4!Q4e{UGrx%JTgcmTq9Wwge7Rb{#TX=Zfsy^y$H4j12B z;kh!hhyiM4UFYCPbpp3@VxsdFPDNkrkKr%wxjE!yIv7}JL>zu@7xQYy z^1Cf~*Liu*XKqoaRO6Y3{1O`o)-^-j z&iAIh*;^s%F9FPu$_{jr-9Xeg1sJa}fa=co0h7&gkBOmyF!{1B6f~TL5;!WzRlJ@J zHHMT7X%a;3U+_zl0f&CW;0B=ss<&cg;MY}!|}hw@F9$HRy5D-34dmKRY3s_R6R zTW6vUr8(n2A?{OB;j)c(Xv)YxXo^m-IqPCq2$3OwIOyS4PbA#?x5ACxz4%eB)!GZ= ziHxWw2k7i77`v#;q6oAgQ|+H?Z#AUt0Aq;!u+jxG@&U}792icm`JblLSn@+)Dd^tk zabPGAl#9pX0R9JDdbL9QzFH9je9qJ*^WdX=P8(p@KXJ?5BYu;N_~hAN2kvGbq8?E7 z#G-u`n#qT`>Dls%x}IJ1YE(+|QktZgG|UK+^nP1@mG96~XZ%Q`XFYz4?KQ{VoQZon zWIBByjDSb)-jwCKEepeEF|JeBqb05D{H4gQ)n=s5ZQ_~`Sx1rQr4j6zZHaCw&m3a8 zj364EO*w&#ZAM+Xw-WYO?x2!btlQFI&o&O^VV+Na(Wji+xJ}y&30!x!?XeNf7OMam z_VG|gXgBChBriRjBbmCA<8at15~Ey=^E5H%pT95C%lyDJ>&6Ac#179r0PLJA>j65X z?IYZO-A-p*D?JtSl*Q*;p&8k74CU<~HpibF?6xKK{|*yat(Y*E*M9cw+rdHvLzd97 zl9uc6(i6oo*%Kg7$Z0dwAC#56Fo~FLi8x!ZoNK1Wd~I!Ig$bmIFC8UgjJ?A?%**)a)ml5{g) zeiCFzRcq2>k|Z-LtXl6=zm1}tMIa+m0ut1%e_QDEfyKxUJV7Eu7;|gO$(Q}P?DS6C za+-^s+LtY6Ilf+C{9$&uVZxN)i2b}91EMy8#IIiphQGFp!#WHc)*FxO zVgeEN&90TYhjHk#!(fq3pwDP5aUg;bV?A?4j&nmJxn<4l=7%kC%5 zVT72NsF?UzDPP52+>hOY<_!`V=npH>4mOU5(zRC%oJ>btPu$VgmLN?hO>3;>sz0j- z7>GVJ|NeOghtPoR@S-#140V0f)3Xlx!uSdKw_bo~GY^LW4LSATWQpsG(CHJ(cGxg9 zdau`KyHCX&D}tMK zGuv})ge8@>oiepTkCG9USr6j5vV?s>AD_!PRoU?eAr*r8jtEMImx?%GwKArQrEYe- z6hIIJi!R|CBx%s{6dnWb_2S9sJukjxsLG6GF_H#}f`NfB{T*)M)_?BFj#sf(DfP;irHyDrt80Pg|WhQ~A! zrq2-YB;s?s{Ei;QrV?-{_<*)L{n_XD0ZZG3b&mxRpQ^Pzx&bbuHz1}RT0)}C_l zpe;9f_O4Z%WjBU3H28tDo#Lf}CBqG~7*Df^__ak*Zb{6BbmYjSB*aKmb(R*&M?&Jv}W;sgvgrcLtLvkk2

B-gTHvDem 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

U2sRJ$HkzEpmqgZC0k);465aE zD)tLU?I&ejTmA~r8F8)K^Ig%k-nR^w0ycTfwx>lQmLEk7ZD&K+-s{6IaG8uX99DDM z%+qg*b`;>QzD)K!dXS0<97$#s6K^;(2PiCdlOen2C!qaCPE{^ZZha3#Bi)w|%tdm< zURhs7LF6K#>05$weT0nZX#==e&}|e6-^S+n%0nXXb3Z^-fJPjl1iSz$a4QTcO4?{;t?N=rP%Y4oUAMM8iPP z9I{dPRcEptOUJkT#4@qBd)!#hcMHq2J}S7-j{{Tg#mCsGuq9N$d)uFRF|3w}?bx%i zzjubqoLfA;H8Z`yq+F){d8l@QV$*kR-k8<6_1Rm^nQzFA47|Vzh?s)><05O$dt74z zSAt)rWtvh++_!Z-_a0Av(U6xc>fW`K1{BB;^2NK~Bs7{qjvTkgg(lS6zo*8ltwAEN6@Ga3pPG&q^qKV$5pRv~*%n-qr)t@U zumD;si>&LSJ665Tg5m&S+X&Q3@OoLvJ-y(|rQ5P!t6Qx!&{Y|r*TKPNy$W`2tIL_5 zHifF?nnebIdjES*^D+jUZy1DxnEz)=;}Ng8C8t$k%nwgRz`g&rT%*$+57-7S#h)q= zYl9IJ8}sS?42m6lqKK5W!cUD?6wwTT%?Cv2^v*uv{kF-5L?PnlqV^7ZpJ&mP( z!|BnjzQXi8VuG51Ss~r?^ORf{)CKP2r3J~Eo}Jj^6ZnQlFFbn*s>5i5ktOl+?lP{* zOtlk@T{ZO8mjycYTufxs95ZXt)7>{SX17_3XVQf}?uXg- zm+hd*f~I8;!ozYXH~CXU0cX3nr>k%)XTX!zY*8usQ3;`hM<_&N)p?{@(8jJc^}A$> zE4UrcooyZti_bACC05#IqJ?jsZb>@a@E*6{ADxH|zxL zMKpWGNF6(530qmdm=Pd*&k_jEJzcTl6r91&7-pV)8#&v?TDr;;gM;Ulv6N=0G!# zoI)0TTk)d(QHk@b<9LPHCre{$U+k1mPSQlGw)0G+ZoWpLD{o$l9LDp}ULkJFNUz}a z%pKxZVk>-KtGh|Xia=FL;^lR}CF;0Ys;rT_O>34Z-DIn=)z*dwpixnh&|`T~gkQZC7Vl%&PS#f<}@9G{F@b zkB@`H6vY=dEiRWOC?Xmzfl;~Pelh84^!N?V`@`4Y_|28%c;lbzEmT%0GQZ~&a-T5{ihf!UA5&qk*!f|l=h`Gj{fmyG)eLJH5HJvt ztIV|Fnm8#`r!udSn)zciz{alaYxTrSUpj z3_hVjy1NI~pt(T?*T;Nl<3m}U_?}k;71Lg~JD#UG+$HMCf=0b2f)mcfhS222^^?`G zN=x`&B+@o!Jtdjpa$r((_6`;?{211&A^i>IgC99MEeh1FzZq)=#~B4L4$JubD*;J+ zLu*c@kjJ$7H#Sl{^dUyNmsAn=-G_cFa=Rlqg}Tg`yW=C2d>eaUj!0 zSR)OW91002F1<~?xa?hhG^)98b=`D)8an&qR_BJW=ULkst3s#VZA#i+k-9NAhCkdc zQwjtk!|c+t@^|k5$A^~1i%TTE^>;~B(3!e$g0YMJi?jwyXtG!ozCVWW-PVrMD1x)M zxE!=8pppT;Jskrx$uFJ}H{wFuRxrsLQ5{&DBjE~7?oRzI+zWO&&{VH>^4oxF&=I?i z8iB%S{g5tgsugS3!+5~<{U0|!J|9tfHn`g$B&ypsDjUew`urDJo44e-SVlg3CVmcs zr1?_cKp~xvnkblolW%B4)yK=VXl^8BTF}Kprq0S6O(K`O>v%*sZH*AK8V?|rf&;DW?tY9^f9=9WM6$)JRPMxrV}74q5NtOOZ`d1&E?37# z$n~qu{mg#*Pc^^0)2GVGGA%B2CQbI+upe$OhLocG zjbcMBr{Df8(_mSrtF4dXj|hM3b89a6mQ;|Mf`Q9?OrAlb$qvQkXfXbn~{rp~-dv}&`moK0e&C?tQXMyHj9UJpcIdwJQ>{EmBlmHCQ5pQ4jK z`ENcNyth?Ux5Ts!F7pCq>+2!~9MpWESo}rN z$QV6B?g-+`CX*7%ywrEQ6jOM84aVMF->JP6v2RFZtF4JnO?~StM4EQk^XFy_Gj`=@ zk7CKHA6(7xTiZtR8>N1%ADs#=n(NiU0*R(@2+FMMb;!!z z@}P>IVt==Wh9Tm5;V7lJolWVeH;f%aG{)K10!h8@-+;Tj!XtX-h|>}V%V|y$>tZzNWj20T|q;>uZV3>NfrFm*pe;E;X6^RgH>;V z`|y;zOVnlz57du%JosJF*i7&VlbY$gLj@)H-PWJDq>UF;qq#&F`p_mKCKFa!DjFK3 z>7LTuhlhvyzOJbjIce;ext@#ndQ0DX7(5p0($cj2bpDQs`9%zVf(wHf>&LhS!@f5i zd=DMLljoeKb`|+M2JVOet9y;7nB70SE=RxQ{WDwMFQ%`BkUg{*+{_Z!4FA9i>gwt` ze(E_}Nvd|9{+jai=Ye8{8onC8ux#Jz{h7mK9Sg%r5@=09 z*u!8a)tcN*j+r`w5Lt+94VP0yH>Brw+52>Hz=@T5{CqEKujhwo3O;8Q-|jTZpU_I} z_DH7Iw;`WC1U8B&zE7q9!g)AT@Q#41EO%0g@9u5p&wyZtFL`ZeAH2UcRd5u^;kkLf z%QII=YFNR5a(nHEd*vpz1gV#ra5$OGNk>lq{fiPM{my#c|0?B^A0m18oJ#5So!@sF zs*uL+_RB=F-_^xt(!|&WhmB8HgtF zZ&^hIF7d8(c8(6zbf1vvRv%3jK!&?PKBj+!zt=8#=YMJz(z-u%f8202)|m{1n9*a+ z(Gxt~-{~P^_+@RkIfB?X#w2%dqcef+M@^jTyUHlVe}UK3^hoH-^S914VF&XCH@HX{ zSpMyMAJDAl6$YgUT8Ws}YvBJ4FS+FI%Bfnp@NFy08#C^xv+zE0RJaa5TQzAk3{{J*GxiXY+^#rnL2)yY3ykeH0#M3Irj3KRsH;iOARAI(p>&V2rC@5`~c9KnKxc6kAHkdh4^sJ6cTb!?!p>A2LYWG%&b63 za*H=K)XQeT*SXZ;tenJ~0_Y-XYjUF*_HhElP$_nwuXnuuR1iFiS2FjdtK&WtWep+C zxKRmvuKgZLG;ia^_7~AHR<6%q$gi&;9TJyZRGWJuGl!bBKl%tJbGu|G%JE65S_^v_ zu@{+6}Awt}c1JA?Yai9_pP9OZ!?j5%INwGTg zTZ_-24@g8$7^icf$#wr9o)JTuk+q*IaSpzpY=N6!F=UdCil=YN(1*mi3&eX21K&}~ zV3uyN{H3KRRV`l)TR}J)BPX$)^G4ia#wYJ`02zkF3+=zxmm%Ri98=T@#l8oO{{y>G zLbv~jKk8L`#9jXl9&ahq>_J;-ap~S(K|l?sE>q$BOZOIf-D67Hg}3xbX}q1iDRVr8 zH7+w^!0olw#e#w5DFYIz4DXMFtab_wCA|p1iJ)UU1yhw)n=X<4eeCe;&9<$y`QIl% zTS^@ASRvb#oEqWu*1W8j?TqJ@1dxY=KP5%j3&=7AJV~OS_HMomLLjjxzMUyyo5N|E znK`ogj0Ag#sd8Pgrc;y+gsdVPRd1wV7yuYr@|kae41OyNe48MRS0u>KSuc(L9}+>t zCou}329QXAu1{v$2=LLVcidT#01$PM%WeX#d8#pi8qg6?S-Ech%xvBIEMnG3wrqbOL=cH?UeN)0}?VE%qq-vnaR zYyDC36@rj!oL2i4<4d+6Jq4~@$_H$cLz^0HZ$|YNl;UD89&k1M@3}8nRg`FHE+)k` z28wJZ?HAQnW2Itv`-`4`>Y82V%cYR`&wnBw%p_*4qDSaGUafJvU2}hLJV-3`dMZy@ zg@fxlBIgJkRDfO|$JuU>iI}`CQXpP>IBw-{pd@fToWVV8^cCC@^sRAoTfPqn)2usv z^gjIEeUdw2E@@m^fwn_OkTd|g$&=1T2Y!eRuS+LDh6K10U0L3b5%CdxuDjpFOr;U5 zhx3JlqE>@QeP3A9#h!F#-KphJkfrT4Hk|_b$Q(P51`E$Olw=B^s`JpNt4+bik}1{j zUSM?nq(KG*N<)K=gyy*>vm*anlX*JG!PQ7&>@MN9|3v*J0?P5Q!U{jNJR9&AVSZOJ z&j5TiPSPj)5QuB#2hcVnWBCL zq)S}yMYZc$`Hyi93xwDTz- zTDUiF`|0Gaa>Z*#Bn@Q9A?rAo_*v%jn1lYoKaM>u8^zC9j|i&XxUqrt_c`a5B~{o9 zazw=R5^7E^i34ds9e10xUNx-!J#zPZOAgczx0k;OpWNRiFx;tUrYODBiTz)@07hW> z_&Qy#_c53+wcTWe8E7v!?_eqh>do!N?($isZ#NGax)S25oM3Xk2$9@q-_N0G z!DyjD9lrXmb0iw_^X_+PptXVs!r;gG`r^ETd@}M=$;>6xQU03`-%~lJcDLJepHs5& z+)*UE@Z;NV1@!nh-JMXzR`LA^{#+|3L+9QtG|DK5BGS!3vtK zG253P{PpAOGot2$^}SZA@@OmrXww&FKDktYNg)Q(vJAmU@WpfV{?}Y*+swO?7(B8O zAA=BFq?4ZfEf>JtGf-9kUZqSFAdfTElC~f~9-E`nGDEKyRZwFx(zJ@`nz(sZDp}*0 z8ZePc?1%+(4U5Lc%N*0@QRqOXtHw(GnqtlTvtJf%y#JNesv*kYo$*mq? zZJ}aEoPl1GaLHqN852$TpIEjX`M%(0^VoRx%C3~5g6!MT(bh4AMs0a1m z8Frl(M$lS0BSD(Ois2lJdTfx4XSMRxeSlQ*-6UEKig%}w#}&@_=IQnFN+;`4V~@jA zeah39j89!haJ2~$Y+*|5Zw2VqSB`v>+DF~C1)X;Ph#uN5RO9(FX)#>sxt~Z(lq$`c zK$ABuZyjZ>?xKi=0*ir=W!qx~!Afcu6AD@|ths#wvdW<*n*R-K zQu`*0I1xc9AYzzN04e+m?}7zH&Bkdy8U;HQK(qm(kT*bI)rZGL!A>%}U%kBG&cZi6 z(Jly(c_>|p^XZbQtzR1&V!W?0%iu34>LMYr(M*|bCcp}Mt-w;H>I~2(O2(F7tXrpK zM4X_K+#dHtUJRaV9j!>_&hd!*hnu11R}p_sC*PusQ1U9(aDh)Y7^bV3-B{B7-}4*p z;!oDk$M)Ti-%qY;3~1c|I5d=pry02wKfoJFcte}cVz*AB>+_8elR8tW;*!%_OY^zI zE^gPAn&=t?|MUd`y^GwOEp&%Ij1SJI z0tLex_L2i{+D;)>%|gHihS$4GgH{6LL#x;kJEqqg(?XbNFY+`^0-qIwW1LP6&AKyWu+!YlIYB41CO+8;sHZQa-&@Y|KU<8Rw_qDX##X);7uz! z79q>oK2AiOl47-)d)2<7_>&D=NfkdjDZR%B;?iIUC7KwhXW7Gxyam|j9(c-S^_L}0 zh;nn68cg}r;3hzOYhQVI@TbIGSffC&#?iq}I=Bmarx}>`Q@n5IsrKhxr9->Xr14+H zCPs{Z&rdT#G&VgEO%W>y=VV^>rq;)TlRB+3M@rl^F*RNLn_@diod{Y3#*OE;xCr2t zKb@mG1%<4h+UWq%r@sKPR&O6Uu6>*;+lq-#2a6c_EO)d*&niY7h`QzjTnSjU|u1^K>xs#~4_DjVY?mT-|7CKk8*U$JT20*P| zR?NoG853pgn19LVXA*_@Pg6)2tS+u3`XhD2CPf&k;n5IBN`1Mo%uDL??oBrX&*Yvs zv6&lxJe%x$a<*4FG^49Se?Oeu&bz&%qb_pC0><=LkB=PznZ)g2mq+l%>E=+?FK>lP z8~vO+`8UjBB8GD#-q}TbC#wY?A_^sPUz&|I!KHFpz9zNp+H+U&UOQOLw_KN@UE{AO zm9K5t&sF&0u}a+>G{9V6-Vy`MV(B`Qs678mz2M2`bQNU9q74SB!Hbv`FKYRF7_{;! zn5O`a7fu=sT7m30BQLm<^tF`NOjJr%);eB@eJps4KbM@w3w$LptxcYCxfNh(th`L3 z6CghS`#mP%mQt%E`RtMKRn)iAFsV!%POF8e;6YZlN}!paYKp3=az+Lt_d!{w>suh; zlSg41yIXC<*#?Vn0Fc%3zBsr)zN6<6WH~u%?hxS32H_#N<^$hM{c2m4kVmmIR@M(oP70afX=cZ4RiIaW;KvuH!UGvY&#@lh|Oj3bhYMHPU`5q0~y15N)A;sHLmY*V0arP>n z&zN=@*78X5Clqv`R3TBRXdv)zP~j$Z|fJOM{u;r*58=LCtOh{zBuHZYnvva0#PX1n50{@N_uB&&y+oJyYc z4)6G>GoQTxv%;VfA4jR$FOC>F=Xf*eJIc384w$E>;l+l^7x0a({y#l;8-7}9hvaR| zYc*%nLL}J>PH_zQtEaJyR7%zk4_}4$NpBTQ|nmD9&)ip@!$ zG@MXiqKRj974!J9S8wo$Q3vnVYa~t6U2|5(UoSKs&Bn8-)$+!out~&l_v*<h0WegDDUZw5Z3O&&B@;cU?)a8 z;{SMJvYDy>Pz7tPl5+C!G)Bjz{pd663J9GV-jA9!?zL+|!Kw-a65r+PnkbA=0r2BM zsF^fWgH{riswL(OkPO+#{U=czUM!$6>NN_3Qf2&uf(S{{-Dtp~$B{pR!$Uq_ z1_gO-5Mj8#2#O?1>LN?I+VB;MY;m^GBGNT6q5jRH3;Er{(Bpa`TgT)HNQXF^ z`*NLwSP@MMT^>a`rPSh|3eq$~Li%UjAmK#eE5f(ty%u63;NtzYh?j2;+bXV951HOI z^IXnmh-(^(zW#lj^Pr-%(D+Ou+gB7a*fjHY(QzOoba$Hau)>MKFjQ_ia#SHdfRUQ` zE15?l05moBUOpXMP4F~OH4am)l47x-SAoC|-iOiBtW zBK$UTpe0_Md{|8fO(tN#XtL3N6OM26uwuOHyVYR`13dA*bS(}59|YW;#uCRY;1Yfp z22u9yUCed3S1tgE!&>Y>Eq2T7n)O65vF(y0NY{}}LY=Ba4kKxP~F)?9Xk=u>4m#Ji6o`ksQVE|Q}a7; ztYw1ptip5XV)3ThQJP2-Kqw zaAE-BsLm}zjLId4)n4*4wow>D5kQIeH!It^mO9l=(fE745mkSR4e*#h3VSn(ih#=( zF8$sT{ao^Ydj~gtM`O&q1O!nyN^Ul8TUv0C z8^G<#+em$3FNlQsdh8!QN@V8dxJ7#b%5D7JZkH-leUimY3azB`df%|fhLROexiRnb zUp$uhjK?5;O|SEes)20q(GXD0-#k1`LI_8O`I z|Dj6xpFctu-uN@DUzf_)X-UFyl#p*~wuRTQ`6vs$dHK+u`?yJlGOA4um#Fx8@}qVQ!JO*>Ugbb}ING8QonG@m_V(}E#Yc6LF`1N(Rh&f2DchJ{fT4}h zTai#mT=F{5P_Ed|l}#`uY_sM{tWak;8(J`{p(ar3`e@3sJb1L(FK8n8B*$LnOLJO1 zG_fNLSPOth4=x-;D$+itD*L82=y;LDIE=K-eU&fD5j=R&53bZm6=n`tov?Z5s>Yhu`t1q7jPj;L?Mvl*Jms@~md4rNCjUy3|Jafxyxp0`8Js?h9wter)eYMD>PEbI zb38cHvR5_ayA6;e;Hqe&yFt>uygpuFVJ5q^75cgO{et&$Q+(27fCXlR*qfb@e9MNA z&NPR!Hj?qglhi3PR^Ii#9sVslM`w|(x1Y_%!PVx@Fj9LfEjpgOSIU5~y`#pkb#rwx z!+mMB&dmKoY)|Rg%Zr_Gtkq5YjIhVcT+WMbOTnPaqdPIo z57C!>Ur6}f^f!5(nx7&iY0v$2@dpg&W&+?&U%u=wEhH*C;C3M6wPOI$LRzID16cH( z&tXK6CF7~j#m<~bCt8UQ$S5BD`XLY7%1f!V3S1p(BE2LKT4O~(ES3?~aPG)+S9^r+ z&ZB9PCOTd%!p<29;lFtF`~xt#Yf9S$_19~GZ($Y=sUU;aQ_2EoDV`bbHl>{; z={@{M%E3KemC{?S@Y#%X2Vq2s4^N-mc1H5N(siB>EHml48}3F5@Fym!P3M5t4hrQo ziL5(u%K=l8crfZS{+7;e!_4+|QvhhcwhFtRWV|p4j$wv-BJc-oKWif|JZp{zBc;Qz z+=?m*3(lSD)qAy9D#ND8gh6@v;!PQINWadLXXTaW-Otnp4|H@ibFBxd-CKC=d5HiZ zBn5Z1LYJH8FJ75-Z}`_F+Fv@vUsDph7!aQ&__Lj*F1gI-KVeW!c7%;l{$bXrpG2=$ zJC}*!qdKtw^ebui*6c#-ReE6aFFb8M0KG^jq=B@zQhvP5>pV2t3eLWI_$S@ zc5y}8-$6+*&YA$7S0+#FR;HpNXl-qlTrAkKQSRjYP4PN5uQZH%$=YTj(_bI+2VF`i z1eWb7=Mi;uizcXEVefzph?0|jg5WS92%-GgI{na z?6${lD(Ta)_yw7i@@f)E0)p)=PGxv$VFO@)USr=opn2O}n-zs43S)e=lDQ0p?7VyD zwvuqQZl20%1IW`p6T5U+m~nRd*K`_{#`0K*6Jz7qf%4O}pZ>;L{rY{(U0?a% zDqFD{LPW~dq|@#vsp0AqW&V$Q5K257P+Fzj;jYhdLV?KQSTwuWz=HKDn>-BSpR~9M znzo)ui<6GwvOo{^Yvto7kL@n{;UNKU{9jkfsC@i8s?8wLm z8y?zJ-%=20krb>Y0b*gV9t8;*j9SWO#F7W20451{9QS=jf-_gxgaDIXLWS8MJDF0{ z9e$#(OwH2LI63whBAkg)FclGtZ0j`pBr#_4+T-&J%-16~W4mAbc?Ma?a9N}M5+VD2 zdw25FLP@X}X=mO*l=o!D=DF6y=iI4P!G5!f~}=vEOyIQ6;G#@hH{qAm?4fwNYhD8^?xUA-q$ zBG8Q}-26lwQzgC1*594x>i?dNUiDJ$j8L$uHGCkB&i??Yd=wj^so^hW6mnD)0gZtVbG&B!PH2^!?B`-xz?Qxz4GzAaJ7Mlp6toDkD9iAY)@_WT~l|L=xORWpM^fy@64Tn9OiOZEjddEY6GnVJdO^#s#T?q9B3w=wp&*U z9Zj^gFQ|BLqJnPGUs*+Eg$Z^zzMZ)$&VUMgO0IC~tUs8<(lE?F&QxE~j-*FLivcN#*KNu9!<8uB;kfQj^c(nXDabb~ z=93I2D@qNpK)z>6C&*s#p3SRGfE7?9R8(x}JdW=>Uys$;QyNeaAO#cZQA(8>4fU~G zoEF#O8BcumVA{@A>Mf#{2is3aGC^}>J~9cNpTD4UReFgsc(IFUX1v$9kN3qfTpK|X zRkDYPAdXwWc7@ywvsG=Phx zD1N~jSdk@od(H>aX{M(+IV5BOTi^(#(HK>l-Menn-5>S7IOUI$?Ib0hYizhl-=wF9 z&gk6>T28KxjFJje*>OWz8;c(akFNdXP!9gdn2>~MVemkLK>w^_9VBJR>ewE_n-SI8n`tFZfcn)6 zdvdx$($)mZFo$ry{B64_?Fs18Vr#K2%@);63y|XKpVs8G)JA*obe=f%)v0^?j@+WM zI^2`}oajqr`uDU_29g$E|FTj_eOHXHZnJrO3f?MW5O761_+-Sp*AAeR*)gCYNS8Zh zEzEXzy*2t6=G-{#Eseqq7y;Al2Lkw^f0Xdh)k}Fr-|WzZC74<9>rEbtVUQ)yM3Br% z^-WGHbB@^*NSUXwJ)SJ9GwFpuAg7!-ipp6VdoICYP3}EL^n5S|UBqc~Kyb0?Df4r@ z%0A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%0Ap_JR{t`?q|d~YRoLEIMU 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 OUAuDgGVbD?hyMePH@y)6 diff --git a/docs/apm/images/jvm-metrics.png b/docs/apm/images/jvm-metrics.png new file mode 100644 index 0000000000000000000000000000000000000000..ffeab27e102468a050b6d2f0ffedf6834fbe6fe8 GIT binary patch literal 422737 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

{C!B{Nlub zNnl&I!d8ppt1^m}8tBI@H$!}-lxfWuTYvj4dS1>SVco#S+aef}C& zbox++LkO_b{dT^>l2Y&;;`zP=X4r!ec1mI?*uc)Kz_^U~`C9|(Cwv7(`oq0gk=>xV zngcU?>L7Y~mA2~BT~(kBJ?U?6y-@j7vy||lD(!Ta>~QY5+G%+iuPz}S#8;>d1r)|4 z^JDhk?Pdu35fgJ74jnA{>+4&0XRcu>0`5u6G6h_U6O0*Qn8uQi%?Ms&9y;{%xpLw5 zT{0?jc-FFngE@{Pzb5d3()ix#2&kzHjxzUF4yCAL=;a8jPbV+V7`Vb-M)!p z&t-~uUWSL5cz~1Gm}}7Ah1|SFc4k21&+H4_X1w`mANTP?=`!7`z(7!rlpQ96W<(Hc z@)`~Mcy$l9T1w2HAh1n)cvkFH?m8vjJm-FOcd&=n+~85!Pe3BUsgKmJT}qOI-Lu%- z(3atVidUX9-z0i@`AgR+7)|7KOe0nTE}DGuS5rn}BEm!3HJU+#o$Dwwx>;7aqf6h< zpCJNF&BJIIUphNX#>hD(b#w|0ie*Z>e+&@>x?DBNcrwJHhznUgp{Sfj#PqhUGl(tq zLwSs)sK8n1Ws!qq?>~qb(n3A~H}KnFl}=%^elSi?L&{HNcb6Rr0^wtx zXS&$G>JRu$UPiD!^fjS;0P*SCv38DKdx-Cc5SerGX8OOwb#t& zUOFt6CpY6KzL zG6`osi(i+}vZasaWJD%FR?1uZP)C*}`nGsx$Dm!}s`=sR8I|9*c;g{T z<2eO{v-L`{{$VFIKvHTWqOZCrablOhJ(scd#Ej*$=iP=C4S!9#x;?yWQJw#q*2ew# z&ozo-W=mfl0_=)7)Q$e0HvKiDWs7*3!y!O;@`@lf1_E&2SnR3Hr6L}7&i)yd=k}M8H-9l5Apm7wk1xri4C|Sk zWg1NTje$tiOL&qZMxi53ay0K8i9uLJ+l_GA!dA=XE5o~&{>Fs%qg5R9V;$#ytjE6< z{a?wJYy?UypSItt6y+OnY6y|&K^iSVUrZl`>x zrSmPp!Y9v7pTAu(*<7$SWlO{!&moTpQgE{0AncvppHJ5Qz3CyHmRUv`BKwp%95H#d zzcZs*nB{5}v6Jfdbk`d^6_)cw%4EH{x%=6p>K*{E(4n9jT+x#bM5BD~YDChL+r+Os zZ&uQlokQ9=ciM*G_CoB2)AaX29tJuRot zzkhUMQ1QF&z5p)knJ#uAbRIz6Yk`M%xb6BDmyqz|h7l z2`}$=la8*7`Y*@{Y)qAL$h7U(TEtBWVFBUMhH4mn)uFUy!+{DkDU7j*JaqRS&o(pg zpn+%Pzpm}WTWvj~iDkU@<~Eegcu;x>PNp6fLD7#|rhxr{aRA&xv~kVjr^|m^!>e)- zFWL&U0ZA8XomR?trZ2YkLbMKa;o;$LMToF4M%dsP|I{Yvkzjz?wR98VzW6Zgi8_Ir z;=MeAcX|2U(W?Sx=or*^Bhp8{bhE4>=r(Jk%;z^N)7Gjh8_$&vAIjHuTE;97@68+c z>ptkAjX5iz=R5c9vQMIMEt}Mhzlh*`L)?2r=XU2qFJryPdC)I;w)g)9GigA%{10AV z2EorfF)T6nP)lC=urMDfY>9@Jo4I%d^t7Cw4t^DM|FTECKQNbs@qKcZeX3I$!DNM$ z98I$1wp(~e0Ug^yS06*u{=L~x(G*N?~?I5;v^KUxw}hG7poB zZh>|qYm&?A2h81#jg3x;o}sqnq#}bhXmD7tQiZ$y8zCV|3Aaoijka>E4Kq633_+?J zH4f%dwIipePmuuP0(3pe))zCG^+T8q+EH$JCms^l7N-FeBc=3kIzi2X{xWr-E?CrA z7_Zc*5j&af$ML;kT@q$0Nw2?}%|wCSl$Gz|H(rvJjtz4beI^Q<*JT4v<5q8shkMNq z)&TCLb+liSMWpO9MEqh zm80R?XN~eX5i@Fe9m#ZfSm1*-)g1_E8y+6-9vlj9KZ8TU*Ms4xK`&RQ72`hH5_PrQ zoZI43!Gz~y^;98&h=eTGjMW~{OLS+h`-z9|Z0F}mzvDbt@T;sBNvZstNLy196EQfO zc;d5)&~S}??-2GDeIQ%0UiWAPMkNu3`ioAq{O+<(S*FNSyv4eCfP3K5eGeypn|jcP zVU#Ddf0`SMp+M~wv2$ZRpUyt*HBVeRHsh)P{V+OFhg9C<*Lf>WN2#B@*BN&0bLimQ z#nFk+wOin^T`My_>|5EFJZA3QMUC~MSZhzGojs(?iE<;in%3GrbQv<<8yDVVq&y$P zQ5@&4=5wT)tzi?Fz+-NU9DaAL z&z713yoZT~+i`>GWLDO2V#`m$!8iWUgqt2W6yB9qdH+gVlfSK(rAMWpM?j(Qzks4m znwJNTXq~QJUGy=~H`bF}dBfJb{l3em9cFJG8#!n*35!mM5W;NUIBskyNwUvAFY+Wl z6ZLu?`DFBt%n}pPe?Z^bNqFso6({wg+GuxtW<;@YNB-R zWA8XHRDaTp`PHTbq6p79YHr}7=^>KUM->S%CK9Z37xm~Q$$;oHQ4xt(ttWY*cyyAp z!0D8LpHJ??VHtX^Nc^lRR)f_I4=v4pyu`-NoZ6?6{so;hCVR3u;lvk5;mT%&2G0wP zr87#>sm0n24D7GT*|o5s39-yC$tMHP?VrqTtjIpm=;OS1qc?e24`x8zYc1ZEr|n8u zdNARb*b_@NxvPxFKpQOfSX?R3g;{Q_9lNZ$BoY@XMV!Wh*5M-dzViyO|Da#Jj;NC z#{sRGaz)23A|CreWmbc0TcuKP18KFSfGTx+KOHdh#VEx`N2{@$`xzye@+Foanqq&Ru}&U1X<0#Pq60>pnY!CTM%OReYt6K4yEr4s2_j-+<=lBs`6& zQL!r%#s*>i(S0NXFgGNJG~F4<3Wd}BPVn82yMswel*^VTuQlP3n%B~9cuq_yU^@RB z{^;iw6}G_~K-z1AhbE0bCw-XI%rtH_viIElhO*z6-5z^r4NyxRwMV*x%jEhE!2tt98V_<8@r1Wx3{Rh$n2x zjo&UR$AtS$QVLhurIaT*6|S5kV*Nm5+o6y5;nuBzL@~kcC(?n5S%h+SK2?p06L|BXpxg%(+ZujI+C2g zEQYzvGHAjPtzSn=;qAG4da`6&gei=w*wAACqa~dcgCrP^41vH2L=Xtqk8&W)1B38o+PMU;N8U)Xknx{=2&=9tgM>`i~f7FI3DulQI;;uSc0;kJbiS61$lD)Wa8gEwsN*Qe^JfB01h)2=*x znrU^x2YJKo&E<);?hm!h7x=bkG;_d!&V^APDfY5|GsT>Co+LExg$Y%RJQIGw2EJe& z>L!#X{U@fAV>Az(vYxrGe~|xUnXiF3zWyNY@h-%_xp5|0(UH{8I*i@f9a+}An9+AI`u1A>#5>HK@7ME=`n||$Xh<+SVm!896g`X}N zutAkG^1Z$#P_js+JA)Zx$+jECMLlfMb)$luGEsTYiO*xevnB54v(|LKt5z%v?J!A6 z91+keTWo9_BJz@2FjB)q8`FLT9axBzAyK9r^kn3cVwi5(#oe3r3BFj#xw&?ky4Z;p zUjz?>qRGdrcDEEQf43Zmei319yE)r#Tg}x~WZ0&2#?w&ElcIPJlD_sp!o-508D7%U zf>|a<>8O)`r&fMud=nDgNx9K6dr7j%)n=2^D7s= z%1$pOt0;tidj(F6GQ28UmvK+XWCM?=r?l+ql2#<3d|7-0gXJuHT(cAG6j!6WjiBdB>lam5 z>m9`+2KvDEii2Z&O&u1u?yDl+#01B#1bH9V9HEFio_7!#cm{T%zO#LgCZf)QN;;2a; zkZq?NYl>p_Te_O?G>bmMJ!BjaQ3$ywEKy(d@j@8T9bcNg(bkcyk3agk#6vjShH7)K zEBAMfcezE8tp@A>z|k%b0u!3T@+EngCp~W6sXZkq?7enu-OdGD5tc;(Kv9}&$bCX^O?->tH-+v zZ1gddOltGb6_7aHVa5+tGidcnsjC8%>`8*Cr|-$o5OUa?*5cp|i4HN}S?D zn7W>qAMCrEq9r5$e(Xb0;3_C827PHQ4c-@VKk;EX@ZKuXu9Gr0yu5t>i)%lRb6of1 z*2`(5+aviHy&vGoOkgjx^kKq^_up9*N&Xu3iZK zI@nM=MWru_l-}S(9oKc-FFYBS6n}fq1IzztLXRF7CGs8LV+`{R94LDuK+YZB)dTr3 z>!veX(e37Pc4&vZnb`;1>C0s@(x|r)=J<#8X%ewr@2e{tq}ow#&)jso(N??k*GJ#Z z>}K8ssj1-e)Ete%9}ZgEABQV%xA_b1CW>-StRr7h3VuT1!Jd}b%U7`Jme{QK&MMt} z-{2@K%b;*?!?K>APHf2Uh8ghPsa$eo`YSfcOiyiS*EiiJIl zMu46na}|RccI0hAnyYW5YVT5+^JV+_!DGqKVNaJ^$f*cw?yISRx^E~lrlD3K$qWQ? z69zcpn%^k$Q85n}Q4lGv`|P~E{q|J^E(3&*=ICE>_%gW>0U7H5ir#+YCzYBMo6Jt$!nBS=vu90`XuVP4iwke>^W4h5X%?hFOQmo>BJa{kGd5=W`%+n&g((*8O)#@s`J5h?BAyTEf^z~8D zO_dg6ig>Xn($xepKU$J^E;3rsI~?iF`RL>0h6++MI+*_K?B}@}kLS+A(Oelg9*Y=? z?p!gCDp|(9xx0TMOF4Ui!7wkf$m=0Q7(5q_sKO6J^eAurmgIo_s7MqKkSS&U*J;|4 zb0-vE59*@~Z%W_wNh+Hbcr}isWw8%Kvud|k_v>6bIWcn2P(gD2KRtysLfJCdp@}HK z*~~A`^#xJHTp)JUv4(uSOnIKYpAoc;@J|=RX6_s4(0lJZHdZ=b*CD$30B%tyy3Y^y zqQ&Ps3m59D(X@F%DGmNI%5%NZ$ly%SNCP#|M5@z??-V5^jd&?VtCr)bb7vH}l@J=E zS5U)5eTQ*N?37e}+2VMaK`Z5}%$Bx=v%EQfdPN=l>~2oh-s&-EC$s6VEFZ6^9(h=6 zA_?BvA*d4}+oF{X9}@obeJTxn?%TZCh>6xo*NhFcs1a|362WoB{b#0!hK4$+p$cdA zI@dSU?1(bxI3+ZqsMADo9DqD9K2qE~^ljI2Chm|y-M3$XUu?ZdkxoTb+wRfSgY{BB zbEp6}G06}|LY9q1F3Jxnrn0pLcbw#hhg36kw@`Ql3gy$>?ti=tV3mQl(~i-;Ttvz0 z`1Wh-l0IMM)3&BUc1*rbvmPkQ>s~R%kn--<(+Js+zUBPbI)4L)N*w*+%?FHB?~9#| z1$N;Qr?t)GbxqIReVn>O#5K{D;|`5iJ*J-rS2^hU-9w0y$baYGQUbvB12KL3m?u{V zKNoPzAPMj9DA)gZ>@De^nb##Qzz|~HyBN(lFtAz*fnkZJ{#^Rd@>QicSziojzG#&^ zL|XN)AWiXDT&sOm?g40)^C8T_ZmFGfv-}})XSRpe)?Z@R5pFlNd?pEQY`@>Q&>tgt ziSF1oH^=Kl3_d6#oIm65$poKsL zjg`0|#-oJ5Fyo}F1g ze^Cz+`(z{Q3_Dq)jw5!7(8kTd@>dZ>ljj-BHoX$GHvYys9?frA zY;pTdb4(u>cS+-sHFmB1m)`(Jf!BRnxOHxv@BQ9<_)o`glVup2jR;Pnx!4{lHpE=} z)TZD43!Xb2TSK)dNw3mg_z0X1m)yh5&bgQ$2iwS5@%e^OHlKr)AJCol{s58d#0$6j zX-Xi|dU`A?b|q;4mcMxRjT>6*g*n}O0MJ|*#xH7Jpaj?KI4RV^#-P27eh@x!D`CrU11HUjRA zhz(<8$hRLQv&gu#c!%EnKAGXs;b*GW_$1_5ZZ=Hi53j)vDyZ^ZysFcIridf1lE7LK z1>t>e`lK2z+IRSAMa!1<5sR?V!xf2`Z%$sFdV3p24-D^N9{;{cm z-q_-qpiutqiU}4$eNjf*fD=o{$UW@M<`{>$9v9%6ns6tqQIit+6gb(kEvg(AlO7nY ze{txFslg(J*U-r6!DzgU({R)|V5Hsb5pdWdjxH&+K$VG67Gy&QB^6jqu>hrpp`j6_ za-Fs-Y_7yTQZB6N%WVebF1NN7dwY9Lly1$>1sJ8DhTq(8WqA>ry(tL=cCrze=V~6X zmIkjBpT5sTst~jKo$Q>rpDD4PDUx%te;z8PV@#6ftX>+vWpj>p^ zuVW}lN;2s9o}(5kh<;nIjVi*t;Ioqp1|i`+2mvDXk4_*5uucC^q~ungNlVI2>ICxMU^{Bbnr`tMdKuh><$vdllAebU{ACoJei z>tubmKRxz}i#`Q!s#}r)cOCNx(^*DJ0hPeX+)7_jS5F4S&L+jQT(8BhJdiJgN=O2# z`%NWsFVXkI|F-A><%nqYa&2=!AM;Z!YKBI8=U1(_{$b}OrkBkK zZv7GDYs{~ZqNc(paStAPb~3>8iLtu^4sQZOj6Kik^I#z#o_*|F%??5gUL*UNxcmb zkE%5Sz4f&_*&lL2@e2Wf{&f?raqwrpeE95f5;%Q8uM)x!uG}m3YGn&{wz5u%j#`#M zP?Ou6InoP8Ak0LfC!O)Tj4p?IE&f-(~bg~+jmut>KuUC3IYl?*9W?F2n;iCI&cvPjC>|@(&MAbEQdB0(aMXp!e#2C zogJG|6xMsj3rxj4ua8jH>H4ZazB}C99VVv}8EG+ws$8u1(BG`w1Zg4QFGxKRpn5y@ z1Xer&Uccsw}Ab|U(l#s&{UdBlvJ zb+IwRN04_$Kys`Nv)g$*xB`owO=lmNMm|fv9JJJSoQLmG$qXC&BE53o-t3un^>kJvc=BG+X>(py(4Q5L zM`w>;S?3-~>%p~QhT5w20JeSjWyM)3oU+W0K?YgtHXr{arAB}@Ldn?hr7M^LwTp7i z_ye%KyeARLr&D9Y)>9@t)9x#m$rg{y53T}!A*SywvAjF0s1ygh<|=F0@DWy-~UfJ7Jp^YEdlb`AlT za_4dKuGb7nmLG-9WP#1p2VZC~v^HOPYsO8tHOu0z6(|N4%}ucp>ruoY*+hIyRk^8$ zv#uXGsJ!5D?s3T*JJ9>0-|61Bs1l$_71jjL^G>!p0{qm#uZ}5yAWnP3DSmug?ULYG z=ASX+k`%aDBjir}V+%XE|J>V?uhz&R{w31O#(q&`!FxhZm^J%?CUsY)9v)jp7v)me z7(U?)h|2c*e82**O(Q>h-g5{s`+SxH4AyV>lce0wv8hlBSdGe=Xe4k#ji>TJ;1_UA`#*B3FzV^eg&XnJ?1$5&y&C*Q zXD0nxk?%@V8rL?_U9WY8lmj!z42tYkwtgzPn2vH@NHgh?svQ>1#U*dq$Tl~mN9_yb zb<&CpgAKb@46r{zJck!ePO?qAf*=$QG;~oRd7eL?#7My!sb-{Lsq>tYmT}2cfZ6wo zwUVfBi86U~j<}s3a?*URJc%x~E~pDfoNjSK()q5(xIJ1Q?fH4Z8J0USf97A!dIWKP z!j0w;UiY(Sutlq51f`&gvzvYIMa9d;@QZMzhp@1V4TsL^owT2GJyHmErbZ}S-_|5| zs^c>kAE*fZ4!Fp2(WIEQ1PbU5S~D_S&zuMf910MlyhbJNJI2t$uSDL zy42`yvJ0AcCG7(Q;Gq@_^@YlpUb0N-DvM9EKK?r6INYM2=ylCikFJG zx5V?ec8qG_HA<^2e=&Sx(^vF=gN@=~ew`!%bmFaO&5zG-DDyNw6O_q5GD#m-l05fq zKgayn5~}^%5(3y9%iU=)MzAP2f&HAZ5gJL6;w%H>y+-cOGzo}RV`ovymq#RQYQ$*2 zt#N6_R+soI9cMJ<+@qIQZo9<2#>*Fd57_$Z8#x7}7@VxiB7cC4{T$EeCJS}NtQY2w z=JY7PO8&9+=TdElSV_Q8BYPW9=es}eZPm1r@)J*O&h62C_g^?d{;SWGZ?-Xv%IrT8 zbGdZU;$`(%qhhOxCvVqw%fVHJnTStz6Sq0Gj)sE&CD4<%RBtmLZW!Mo|PDF5bq-DAz8N~gAOnT z6KrR{;l|qY5$Q^<1@zk&%io|PU|K+aACCT-x1i1RfQ^85CTeO=#k@8_#Rj#Mj-C7a zpCo}wHci%%L!(c>gyG3V5qxd6E5LnUUQz0MUGTb@XMSvK2i^80>t=a9O=h#BmEzsO z_{Z9({?@uo21-gR5tr-ZwoV?cuW-BP#S0U0`Dt<_gKbooQidZxDnJ&IM|QyqPFyCK z3PR5e8nD&JN{{T){xBiuzk?RLE|ODHa9WF}2l^+=G_ZshY+i33V_r)Ft95XpjJr(1m_2Zpu1DVdM{EX^at{)UZGL6x!#B@{jP^CbCF&_IR}uU^${a z5=Xi(;zf+mu6Z00^RT?>!JOU-3~l2D;&W^w6{Xq)*l`RrW1|FHCi~PPSB%~S0|Nu0 z=oQ>t*(&mC!PE;2Dde>Hb&XR*$k?R*%bETe`%MJ7&<>!ihnJQxQ71qfU%dAAutj-I zuy;XFXDqjhz5pRRADo_YV`0c%l!ww z@7F!!&Aawa9szSp89`yO$EpzcJ)@LYwL7r-iJMC!F=5FEe=#o~ZwalkImE~hIvZiY zOai;v$8D4iT|?p)^HrvB|3T{|#fgm0f|2;QQot?vp2Tc@o6$YoK4y%=nQX0%VN7MO zR5ILt{SBF2+y_yMA#)BX=0fL#qH}jzE+13ok`R*>S8wUjc(=~01#T-BkXd(#23x`g6qwgb(!`j zLbN{caYxRwRU_nC#RVyfpvT!n%6v<)OxyuER(Hv1N0tcAp-;|0 zQCqoB1KS5ofFGOM(?M>~>QFrZei1HrR(Rr^Zf1(8svG;s{T;$RuEvKoykC81b1Un= zF>Wb{mM%p#3-X*yrWWa)ma`IXjjmkOlp!PUvp5Y~&^U~gHn%R*k&CH95$k*zlL?SH z=Ig?UQLWztqI-xKGpSs%AJDdp2+eZo;gP6Gb4`EMH2W$a5%ozvh&Zfmq~EdF0P?gR zV2^~JSO~fu>dlEeftcn%b12G2gcXE>!38u+~)=4|PkNv_*PsFJ^8#v|(swa+kG z@*Wu%(3K=vTv6+tzGZZjI#&S8fV6wB7ybURmwgUWydMea!H_aw6YE>8JX8UA^gfEs zXGWdURAyovoF*=4qAHdH#y!gav;dINcWd_oKeN4UVh#0Z!lN$8BPo6gYFFo4yo);E;dh+1R!9Y6I{ihT8eFO-F_&!5lP_^pC)eR>k6 zV+C$dDlkLk?F<@K#@;TVR#a3(c&>{3b|>J++dh;-@%Pae;!+c+Ad(e&h+VN#p-`EM`h-Jwa+CPNUmhxg7y?rLwhL0*&}ETqMFIQ zy=s)ov2vY531$nax9-u8sWj7P60h5xHKxj9Q^7v=;o4CIGtm@ek>mAA5k^&nvZ!v^ zX6!a=YhPMdhj<-(29KHbYRb*`R^kan0J&zEe>Dw|%mUewXgK4emEWC^BrH!Q>mO?J z=DcnjfnT6lMYFWD=xma;r4bnZp()E2FwYSFndtxH>#T#S?3@1&heLOZNFynYbR0@h zI;2xtx;qt61Oe$1P`VD%ol19iNavwDei!I{KhHD2neRUiGY-tT&S$Uv?7nyRwYG)_ zoNJCzQE-wf9Zx!hrqJMfSTA<5>s*!D{aJCOS`$9Foo-RGifM{}z_=jMY_c2Bf#0rq zB_&S_+)n`%zS_S&68)aqI>;SBjDka?e>4mi#QR|YK?0^kP;a3e=mhRbU+wxJChVfM z_}jyo76|hot93XG>7;(n>k&;8)TU(@pThi(h5S*MY2Ktry0o6Zx9EysY92P-t=pe5w1 z<$>9Ruc}j(;PoiKF-u0x`yQEocoQg7^!~tPA>mjAUqwG;*vN=|Gdx~XSDlo@Xw40M z5t{1th_P!e3eIohE9nu@T`Jcb`HYjHw}1h>=b$AM&qMEll9@gdsV{$it7 zbsz{2J#b@;z{MY+)$R)Xn$UE6^TNXULDR(ny}i%lW43$3O!-T!&5JKNu-1KaI26G? zC#yPGgqrO@Msw7lFDYsH$X5}&i2Bvn>FHx7ECsyj`#J(}N&frocNt}Rd7EUwGi(g|)ghF{A&8+8vyLXtps zevR>jJpzx)o{Pr*c=F}BeY*x4_^zWBd2|GYV*hOKW`C@=<`w@eTZg1Hq` ze7Cfe6?^6WjgC5u73rM%U!Q@_UvKey#3Ubg>ctfU^NOh=d?{j6!5QV(0;xy1 zXJKD(OX}yn#*Wk|zh=0N(inC+mGS{8RL<;?7nRo?XD5FH!r@5&fi05MQ%K(1BC2u+ z1C%^#D8mS8NQ%L%B*>fGwwu>>20=?p{nytG2`wTbxHiroo&R->IyiU`5% zO7v=23WnVmqoV~vq+Q^ua$Bsi0=j0#HF1Zl&vR%W;bzkKZlweR;BNIE0V-YZ^2d|2 z?{h3HivdgTVx)EJW59NbiN%_9OGh02)M(sTTrhZs9h|P$*T49Wh}z7E`r+~Ms3RX` zDEL{=V>uB&Th)?rx0tHuD4eN&{So(KbQv469DFkR`qhdq&^e=`RLqOxu}dTglKm8A zXepE+PPzfV9&+(_e5)Co9uD*4gFwM14G0ucH}}mmGXr~FL38vh_EckU84WlDaFQla z-tYB^ryCI#@QQrjr*t5Xy-d)4UVvPbJmIEwl4CH@7Q0e#O?nxHdlPdQAFZj=q&3rO zAK+*K$)XhGcu3%yPy6;<#(Z9xlVcBkq73HwdE{sf^(QA}kNM3j`fP+2&+vwuj=q`w z<3oO=P4}lo#V{9SjE;g~=Ti?4X@(@CicQ5)f#83u#q_oWEOl#eJVkm)s>PIm-zI|)nn3fLmdIBV>)8ZY0U z-n`{5A8^yF2iw``L&t`Qx1(%ejHl> zM?+fSOi9~$GFaDghV0f7u+n3Hncr6;&$?bT@#!*xVW{|Tdp8*XcK*}e9fH!?Z8bGb z9`Yq zXtd!e^WgBA`Z#n03f|kIs6M)SWX$`fR~$pse~B>VDZwj4J|qGZ!wdH8bmutxwt!Wx zNiHQS1Ci{)VyWOV*U)W!tWQS_tvr;r#qFxPH|egZ@XvvLiC+UEL~f`1^QC<#28KNE z#^UdO2_Z@LRGmNn0+;P`{4{wX{yEIp%sYtB{a~sCQmF}1L}dG%nmJma&jQ~rbeHKE zPH*1-)qK})sXRi4+THM6xVGu&(ZGRUTL16etsn*&^RH;^VPa-+He|SDVxYG39|Piy zM3-5a(SJv2SqT19R(UE+B6RNkPgK}KED`ZAeC-cV9RExiH)7NX0@cH1mhJ{tCg!H= zTjJZv%A&_0&!>a0HgMrr@iv}w1a@&MnfZSu0ldL`e;Uxm#Ra?hJl;;j&vnN>6V*%R2bV=o>mS}CwA-lDcB;0>Qd z!L4hrEPOBoLgCJlk+r1j`8fS7z(<4ia1ikYg;foC0Rbk8(cuAvX!wJNIzwkwR~kZK zBCb9=`iTw>3L-zQl6?^fO0$LZ-lX)f1?N#LikK;W;MD#RhiB`g&{<3L; zwjhuGY>A8gQ*p0fp;~w$VF*kY2MuqUM!OiIAg2nrxI}PlCG3x)i6$>U`aGHXs=JYY z@UT0M5^MtgqN-wa+iFl96j&(P5s56Zx0xeLjbpRAvchh4n`U&^;zs}jxnuKQTKp2V z?$nb*wVMh1=;^Loe(a{%;EGRtEqu^vZ!z0B#EITOpPu{^pI&hWm8d&DA^=#M(MBdL zSdd&UC~dUT18rzS1wE=Xq;?w0mG&3s{E6{`4^n^;6$w7@Qxwf4Ty~ZS#n$t{X{!_q`wc^&u`?s73@L`*h7aV@7WB zT;&Ed=WS2YGxbHyk+^p&sT9O4?|hK4n7^X_(!-GEyQfGN;0hQKAGx0cGo#lvK;9l8 zc;!qy7DMypswu4w1?!2>n+efp{!19avvUJ2vfpy$fZq1^+so%;er=80$hySbTCHDj z5dxNa)1m%By%><^O$Ta`6rgARtg1g}#J3(pZPID2L`Ab6Q^GfYF+(p1c+M<|2?ib;Bx37&Q=ueJ0N)8@{X%{r6&{u^V8J!}L9$`au)JjWD07%Do=|7MT zK5BmlbT)dufZ^VJ`buy9H8Dw@3)ubFsE$U=svjKMi)loQ9&Jc#YHIFe1r|nZs>Lk# zt!@{}HZgo`S4(%!Jl z|7IT0{siZd|42eWS2g(`Ob$7*U42rM31+5VMKFi88Wf4!N|%(n=Y5&54AT>SUm~nq zr!OJTB&#;Dv9_1PCDKK3LB0WSj|p@ey%Cwz3)8KZU~ki_BSi1vi}WgAyReU2F+aFE zIy!oM0Bc;i(;}wpQg6OOgC*CMq8{irEceyI{8rCW_Z9oagf(aT2V|`=F5>OnzZu3| zSY$-RT?XLF@j#98>}s?>GM^~7KotT^zqqG1Cyd}Ib-Befh?!}1D(1Jn1Uq^h zKc4&U!Om?Q{9)^T?UPY48~zmRi83-&T-*%!!E#T^pRrO~5^(gC)}r}(L|4!-Djbd) zxaRst5L><#gK*>$%?5pKPOV4EFI??4*fRJ0jQW2)^!OyM1GT?DOcQKe`|Nt6w%FK) z;#*1qRnH#KZiiQFV1SM6d|%02~wqbj(bP`@(Cz#)T@1kXYP>Wp}Vljr>rwH)diGqg%L3`6&esP4Pn<8g6F z1r-aeN;UE{WEBKn(G8nH28D0yruqi+>0UZl`p1aKd=c z02#A1QCyh~v2;IJPoVPs^mDx9P$iK+?ONdwhhi(c!bxneQrDWF1J)Mr>bZ)z2~W={ zX_3LPf-Qx|ERkut_=8^XO#M=5CY7N?(y784wa8NX@BKfRv}GW${{&U0y48IB?E}|< z^)m+5CDmwX%9Lwr{82Qzf}FHQyV_Kf0x+U6Y7aeCx+$aA67?v8IojK zE7RT0N9kY)V@$52EF-5|IbBiseT~vx(^+=^GX6I)=g)0Cq4kfn3Jim?DNyoWJ-eUM z0}x`f;Kclg;sFGu`ktb6Pj+yn&-)hmz&*UN5>1hnd$ZJ08hcH-cFQTigy-q}R-Ouz zK<#1L*!BfD)JgBkv4{Ws zngCunOB8EDPxkyziyA4WO}lXxKeH@WG$q06Jl5{d3$2n9isV*Zca^~&H#ecuW&<1+ z5uKDW?leJjA>r2w*^ZEtS;6h(qd77;8rpVJX1FgJU$VQhT z9;Z4FCvvU_ef4=@$(J7;BIi@>thNShD0CQ@P9GzlRTJ3=(6CfnmxIwaJjm^XQw8T@ z3Ae=~p&>bf0}OIxQ(S?waqa_-jq?=+r-RW!_xPst5bD*xh?H|Y&{y4w6&NybUk}SM zPB(`BVH*a1`}I}(f#~dyWB(WA^_ZFIVOSq%bG|_#IIHEcJ|*h>ETnG&ku)0(u?wkS zEImDbEdKrVv8^{<7wBq0lg|Mj6->6}HGkx=ikIMhZ%sWa|!V1cmPcrdq(;Spx^;+EFeYUp}mM(#)4(l>fIyesQ5G4#kJ$Ru86 zH;&`v!SV^M;-nuCBf)5#)6VjLeAVKodwyYb)4~6sWB3AQcgp@j$Kadf-!B*fj&l+C z((j>MGdLH_SFbY|)H&Yp|#87jOdrQ9K1{38UKzaAHw41OG-q5SJjyl-7b-~g`=fVTJn7Y;xT z)4W_pjs89=COFhfug6>&M1F3IZPLCo=3e`}hark`>#b~phab(H>qan)68KX|4sf1@{ZsVGuk zW=RT;6*X#n$NP50pcp;6wkmk-dEtECob3lDPsD%VjqLv_L{gB-Kn?T=)2C2n>Hzg* z3q7cM{Z&#$^0P2$D0rd_Ek?^|ROg+F*!s$!5#w>zM(i*El=Tvy9dK2~XXH{%vp#8_ zyDaXEPjHOy@nB+<^8aBy0UXJs>s{aqGWg0LwEgF_xkwM! z>3jb(s>M8)U4XN(bTsEDp)`v-Lb+mK4R<$D%%AQ+`}7WSUwQ@xGHHN~bbqqu9F%lU z?@qPk8Q&*sr4G2><)tq5ooc)Jzxp%%=f;*`nf+WUn%kE^<@_Vli8;) zC6v?7>*sw*Pc%#THS(rw9N6m}tFD$8Jo&Kc?qV=&dT}KRw8i#eOXC+I*f{s3LxSpu z5t94pF$DMF^;}T4K%n@_7qnCR*QYYjPO7E;HDK;P25h;J3;Juo#MDYE+uBo4tPi54gfS#iZBiKgBG4e zL5TE$r6oi`)wPN*`g2(Nf?sl331NhW_knr#4i=d(8as7%D(*y3*GMXbi{;fZa7N1kOJ`wV) z&&aW#d-dy-ok$jSsyoZS)o&{U8kew#2X2xAj`{1k$e|97rQu(r)_(_AWTk(^WSjr_ z4|W?Ewf@@*9htEwR@nD{3KZvF0p8laR4oWtYj#pSs3{(BV zheHxMrSQLKIhDk0KL2|%*(3kndXEACNElf?Hb6^%|I}|f8od_>^*Ck;g$9qXw|o`t zaytydZhD0@nd}@zY@^BnuWvW=>-F=hJy9VV1lG*ydc<^6U*`^km`zW0c#Om(qlrwY zr$Y(pd(sE?Zy@QSGU4BM4*JhKH_{WSQ9*-?T5s!0U=Z?mu2}4#0r_p>ALE0N1|Uce zAQX#+Z>a_P!#UOzhU2aNC8eE%K#102g7(}|MdsDTuUUVv;zyX(p zn&`Hk00wx@c(0uSxT}lEs3`c8t?@vhQP0IHlW2{_V&+uO{yfdteq{r-I?k62*pq^B zvON|&&XO#?`szSoM!xAQd=rZSIx-e{0CN}P{Zb@g_Y#To)}%t!eBOw;(ZTTQ_3ds| zMUeUq|9qrSP4On~Lz~`)muSWy(mXqr&?qtousm;(s(F*+ukmK%@Hrmht*oqx6}@#( z(*Epbk^hwGp=^Bb@nfEW5}&!k4o2cL)MVI4i%Ux$7&V- z6ypDT->~~3zfH$M@fNls-r90)bFL~^izz=7ROD?1pPSRT(|u5gbJ^coa}Y z3%DXrNzev&a1c*5nYcpX`@p`DC1)|RM`<^SAY5Ej0*31~$p^`>k2x#gPfV_XVq&t| z{EVlxh*~mx!^5p@)yxi3s8)d`>4K&yPokO8+1Zi#dMaVK#nXXCf4mElz7l3$M;j5I);q`!7kh@ zU_k<}MG)4%xUMK907~MqZ5}x2XlavP^6NzaWn=B?v;o|yLnpfnW!>$h@$)dC31Ba` zaO@R6unj7GKN&#k0xvr+GzRGbp6S0pWq+%}bo45+MNdp4k3fP7>v|7!#Q#rRZ3m8& zv_BQ+L?4UBUQOT)eD!oE-2VgkR(PTOg}K=R^tAz7#0RivC!qV-<5QP7x{-VDmsLJ> zx$+caH?l~uRAbH7Ud$j#eANI))Mt46Ns4%U@pge|(t{>fnFmQhzk>1Y4OM*rXkOlv znyC33u)dq02Vt1)nNz5R$*)GG;!}$p({fuhYO$>IL!j*u3rmW9r$w=;ION(J{e2u- zK-Af(D}w~dgWHNB00CIQkhJ(B6>h2D2ZNDR{C=m;m zJ{-+4@Wuw#MXwEb19g=9(WdUB0}}wb%D_m?JwETI#jvy~E^aEPphaZOFZ)jb= zb13`$ppBCWZO^@vl>heQm*zJ~8#%ubDx3^f4P}{p0|{4?{di*?|bx%!qhq@B%bZC_*Fi|Ontg?{q^!fNr%NR`D@|X$a{Lzd z$TNYK{x#CklTPMHOwy`Xu6yuDr?%*p(ev5>OmnHeVM&eXH*|QI^WwA)W2%g8V)Mg@ ze~7J~Ts})$?YrGthaOk@RH-#yX*-h@(x-bfuoQ{- z{@qOTDg~;uE?zSK8MnQt)I=}2^+mClR;j;JqRre&QeTBHyCqk4=|>}qZ@-r4yB*Av zSWO<(&e2ET{h$`|d3OdZ+&jLj)y~|p8TLe|q{@KAK(R<#-qRIETcnbYweY1*RFTK0 zsm)`?b0b~kw|-l%@YL|o4zIV2sO8YNAPv7bt){*wI?x}*b~D)(7q-VZJ_UlKnd>*Z zNDYnrDsQOM>mDC9Hq`MipfA8Q-b9YRwe>o7M?E+gZq!RMR-Zc%uXuMd#9Y#ALVNB# zg|<1^n2I4%-(<1he8PLv&rdZ234~5~Ge-zt)R)1Q5U`^SZm);a*&C-2x$TWEcX`ia z>(*~WOgsAJ_}~1*so5$;Pqq2=>#5^NksJTfdYV^ln5a=0*Bvy+AcnA@(P7QcXZiVX zfw`Nx$d}vv?S+c1{%}a(mUGes&zYArrPxvJUJ45cg%SstYv6K{GYhP@uokd+0S6Dp zu~-8|MSe_AGzc{Fx#T&!;ZXwPOD$ea`~*7zZ|YoHAU8l1wAj+ ztgDb4R@IhS=W!vHDuzcWaMK8jC=5vxuuqWN6qMnX4S*eACXRR$Cq{6>pCOm9f>2w# zByl>8lM^XZAb}~fLLL|45h)U>+2EQd5EsxAwE_L0}P zV4A=#`fP40Z2GqO^KJdLxW{q>BHeROQyx6Gh4DN_$J<2uOP7T0N~k(Cejpy|^2sC3 zQ(^ft*%Fw*o!Khk;_aBHR^_1%J%q9(m;7#)tKGwnLGS9b@-wM$ukLcJzMg>7W)NNOPv=FLXe67{ znh&ej>Dr~u1mX$bZGsVJt{;?XrgFFQ%bAF-%If9T%w&$-6BawalEJC6= zRaaMR3*UgqU8wiL>Z_x>=N}#KgsTMa^olM$i-ZnFF>)G{{ah-JH^(FzuisV(-OS3F z&t-n>=$TSga9E?+g-+iV`!qJnO;>%65;3~oitfN4C|rDWX2rPc z5ctzBi3XWiWT%jZMl91ub*oZ%@9Z-qu+}Au2aE%O3%JDXWP28uG7F*?448)^)&v!$ zA*eC~b_n=PB2W^$bXr|j!ZYw@Q8X=o=O;m;u`x^KV4hsn{@mQ&wZ?_D_kVq2A7t?( zcIaw&)>B{eX%3bbUmHZG?DUM;OxD)Bo;#UeJYW9!(p|5+DPZkYZ=7&s}> zpHTpDmZDh#la^t+>4j@?eT_OwYKSN$iz+s@)q*_;^)#_+#lUA9Kc`WZF3fe_@C=i7 zu>XzEcY_7+1n;J-98tih{?wJ2yJ6=@HXY?Ckgi5%S&#uy27-&($j7o z7@PCf*riU6`ZaHn80Ow+js|fe_a1|r@^SbAvBA|KI`yE!9?xb`FX^F&ikjL^%*e8V zd;iOMk?B2i15b@(d7o77PRK&$#18oB)2#m5Tc5g~j~%bGS&;pJ^{@3b>HxbftGWeuw}7%6O?(TEQLygD%6484BOQWRDZhqI8J12)v}>ak&U?X{ z0C4S&zVXS>_AH(7Yq~V|@{xApJKl+|Z;Npwlp)`KzZrtVbQ?C};*M-f`Cg{1G}Q|ZmwMBOvE+jN`dysdrVqhkvK-`+_0`y=5WZ%@do z`{^Cry}Q)A+iq}sWnZjL_e$kDGk}#+`b6mH)hbUI8+H|rO3U{Z5-4-|X4FY% z7Dg5TKEaSb`Ez|g+~Jh|5HJdk3=TYTMnJNm(}LXyHwe|boZ%CM3kQX#zU2qPvdQJe zY2L5x=;ylR|Q3rX$)Xp$CY|^!GZ~s-@hFV=yb`AqEw6e zhdh=kIjfU4x$B>*5U@)w1TTT{yl=;}hpN_GYOm>Y68kGOo5H}g`dsK39GftooIVmk z(|-Ci!GdzG>*JTkS*AUqM!3f;rxOc_b^iTn(nb*y-4kKW{!6Ni0n5$&r6-JiJonb~@C=ognt^ zv9rL|2Qf}ZO+WM7E1SBNn}|4pqogGW7g_bl7t@8#ZaXFc!jnEc>TLU4|D@T zFdIjQo8TRqd`YX{9dE}b9BioK`}Ibq@oave@7wGkbAy!KmWz2D{Y_W-o@wC627 z-RbZIWum&)?J*16Y7VEC^zIUnb0j>Aj$6y<&$0bvGqoX(BJs(vU&L!y86!q?i*K$c zX(SOCorlx?HRi7;6R|Pc&j)(X>aF}PyE-lrNi2xK!j*y-NO&8ABru=ypHrh<FKzXaFhiJ6CnA!Xt5RCq{)`y?`(I#ilWmxt;45RADC{0M_YCID;jB z*4dpLuNw06yfw+uUkC&HcqaA2Ei-c=R3m>CcKb1cTbyb>(l1!kJ#(a0S7th1mnQJ5 z!q`Bt-9@{>HTv15cLkT<=S^KZyZQ68)bcj>@g2ofp3M?8VAj%U-giR5JC*J$d$-nl zT||GAh*#qdkKLtJwtw1nB!|%fu|ZG%bJEmr@e0rLF6E``V3{NcwQjqMF7?}$Ir{E1 z9!J8H9_G7UuBD{sjXp3PgGKKj9#_7pUF?HDBx;?v78hPN8BdV2H8df;aNZtnnbLa) z!b&iD1S(_RXg8NL3`9cSIH-u$%YlZki!bNF6M4=jJ#TdzJ_KNG!t{fNkS1~kc7NOZ zivvl08hOTbCr-HyS#9ciD>*IUK>SQljG8#*`Owr}^3t2*+&0snk!|@qX9iB6 z_muD(1HiDPbmSX_Eq+~#{$H5X_RRZzo#`a_o+leSw!h0rP)B(p7uRO?Tub9KD->eA zZqJk7{t_{$6#weA^g5?EXg!UwBSN_L)dh^JvWwShJbCfG@bF!U2j`qSX6}LZ*&GPJS87%9Gi~0Qx&{K4 zh!>JVmzQ%3-1heN$ucAlQ6_#(dJ5A2+8-Q91OxKSL9Q>tgldI--X6m4-0?D?E>lG5-`z@2(fgYG(s^h!MGrZk> zY@V9bt46Yg`;aZUX@SvZM5o6?wH~8JvWS8XCvaEuX{&i+Q z&tTQ|IYr`QcVlVn6EDGeMuPo`BWOLW{-l`hF&u}ry=XK)6>Iuv2FqJ@B(m0KGNRwr zLv1Ge&GQObjd?e0obZor4gFn9tfcD{8r!6LQ_q5|FMUIzEg@W3;AHMAvG!BBCeB8l z_@o^qp7q=*T5cti{%f`rqi4rgStNMQjtEktuzZSQ3B%-B&f0n2$mWWP^dK7P^CtMc z@eGOA8~Z3@u?{_lQ{0Gv=UUvGsF0~O1{i)1s4(Vcjd4S*4m-|AJe|fZQAW|Rfat82Q8#sUb)?1uG-WAdQNd}5U(Z@1|Tu(dbJJZ?~LK6%@ z$(6j$Q-Va^lvbzene-FJitKGfvxdQJ_Vg7^mh;wb$^uD+*otxjGdi|gTrgX0wxcSW zFI^3nq{$-6ezkkphUJKOYRFJKpR~v9YW{YVVkHL~vOV1^iFfMW&<-*|aU}9_t_`X+ zHf^eH9&Z?ik^N?nsAIQhcRI%=lbt|^`|om{wC0$J3If}6%d295XbiH)yMfk6(oh(41}<(^|O*B}+cY}eWDtrCx^DWR~B zz;Vk{I<9vLjq4X>pX3c?pGPBc6zVlexx)G!ic^vB&J_SZVrwX&@}akfm`3Y$9s4Sdj1K#fRsmG#vEzb)2h+5Aqr3 zyQ> zced-TmRjiL^=hjyc}U%opkKP!Qehha_#Y`sF_&+BcF9)_G?D2SdS3mH{$o4v;G{IT z0B|2H>A#If9L2hKiW!^bO0JT;6H}S`daRN0vTdQ@B1X5tD_+ikZvyt7;)$PjEL@n= ze9Dr>+6hbJz_4eu~=(s@Y!QRZ~v{qqi zOB>RC-in1!$RtfZbp@tN@SQ7cIktBh7d*1& zu{&quZlkW=Jo7ml${?b9BFb4<6~>#e7!o0mBe|GKw%V2bT@QiD`4Dh-rf1&K(RilQ z5sIz?3~4+8q|*T~L7{-So3k*tloJ7ik<0)j4PCXUA*vJzr~-(ON}aIO^0arIhcocK z5m4v7@3^L7Yc!@av$`V&goYUL&nM=6Y7U#K*7*zOAfN@9n&E|EPpUw96qlc~cZqzV z)$jYbKEZdwz;vPUiRBch7X{b{A@TDNRYcPCA-x{f}t@BWgv$I)&m zm8P#_i{ksp&m))Gx1ooD81Q?R?cvNOFDhBmKX>d8@*9y_nUyt!TJzYHg^Nr1`dYM*DMb?ykN zUdL(WHZ4P(T@|AD06IEpMi%+E}?{Ut@ z=wY34vpYCC1;yiP*Lq)6Q>m~IWo7f7%jax3@iA-`y6mKVdVFtrqF;E=5OKiZdK~n; zx-JlcUxjv=45nl^TZ75IsH}8F7nqS&Kjf&LM;3vJo}|g0a)xwB!bRW_kDLAXj0)<( z7Q*sp$oonNsHeVXA9fbB67yQyX)2B^hbs+EENkX20Zr07gvh??^_i9`Wk91x0omlG z$Ig(1=|=kE6rISmbE5TZy`J}if*+u<$mM8%J>HwrQXn^QnLRMv9i~Ee-T>{Eh!h0( z8}DW+Di&O}Ly>T;7k=n)R_=ZY*Kz%T#g-l&*K~fZD!2Z|J67UexL8Pj21hc(X}bOS z8Cx`jZ;F5$zvam69Qo`~5`2c+0Bip~XwM$;&a?5&htOsS!1<}{2|0@AztXoKmz*-6 zH~VTF%s$w~Dn+vi0sOC#FC>+uNpsEJYakn7CDQv+$YdPR!;4wCZ}nMI-dZ z%v}qHlak486NH{D=~v%c)VRQFU$+iuN;;CcG0pAjZSfd^412Cu;jE{t>}CwPs*M$! zUna!WRKtvAh!TWJm&-~MKq?biwa?ha>*risbuOl*Bho5J6aXgwMb&qG5>9R28QOm8 z+~fwvdosLgV*c-K_t)a6RhsYR4)9;Og9_a5cO}K8Z?lS^TQ#}SKbOk8T2baD7f&uG zcvEq7)*s|V+m!ipu8;BT6K;o$c8{c1DUC$jPH$xIb+>{;l_7F;=^fHhyNBUmKwSf) zul{+z93vC+iNfxRe#l2{La3rb0j2UJ9~5jYvJW`1ln{Akn$;&b2a9?l<@1uw%nLA zLIWUGDOlHrf?LU#k250;RSxJA`eE{P68_n}6AE|CtO9+Tk?56aeYIm&Jl)jME)e=% ze+odL<)YYve*1>!anTo%SyD1-mm93K>La){kRYU9{(Zqsh4^HMkv$SJFxLlR2lTeC zeqqWPIm&lPl)BFIU5#TOw)0x>*VFi0>~vhv8+Xy4m$%%9UMY6DwF`-5GL^8|U1Ax) zm)4&x;jIs@r-&#_UzxPp&m1+9WQ!qi1F;jT^E}z9ID#rSBnUOY@Ij$i6J_fuT`fpq z`m3&<8IB2VlY5>sUf3=Zncpfl-Bo1fRAFhUzeCt-Jfrwh;T3VT(5g3L7pKPM-4Ym- z)*}n8-`sIKAtdf9$#`e7^xO0y)ZX^>9aA*jhzy|Gw#miZgH0DfGha3-u+Va3a4J#G z(~>i?3Nx&Szl=0SQZu2-%hRhX#qM5>Sh*tfTB|kDI=0CZx)7663bIXka+W0b=_*H+ z^)w7QlcA`Ic29>UtIW=291+Na$(|!}@ChDj$iOdHNl=Q((DD3tW(cH*qd(vzNJlv= z2-Ma^?9kQ`LCGWkx;*#OZMM~L*f^ig2p-;QJ-md;n}|j+1mwWi2g>a)Jlrq7878-C z^Jc*)Yu;=`8O4ULi3cbgtnJRmD>kujFg83SiyA{78Hm|fPw0rTo{*PYt7?*1cOoww zg|3BR{4uj!X`52KNfVku<56?Ume~t~PP!wrCI#~}*TAFfhO+%O1ArMDrAQ2Qj&nvq zAnS(YxR5r+Uwl&MJ6i4_U&`EaBl11Ba%xvdJnCBSA4W9}?n%FG=p}7~4-@rk5tebAP74cXE!s``n2WgI=Bc}ld#*QmD!?1+Y+fXdp zf&EICp=K`zyWEA@}=fzIeWVPZUCHtw|%dKG=>wI>aS6DXb9bRj{Laj-Q!WU}V zm8mtlDp{mTjWl=ZDK4 z=&OEZ^Dc(YlkjA|l#|YsYzDSz>XjGli z5jI!FKXcNwd{?)M-S5X6P4|`3Tru%UAu48VF{|IiZ1BRRcShl~${K68*7xPC*WWtB zE@A`n%{y+S`#*a1GvX^y1_(+9YA|w*gUaIK+*_W2@idQqApCEN2w_1)q0N1&O8{FF zv7?Tp3}vI1x0?o$I-Ls8Px2Po6e)0*M9)^@^}Vuh=u#LQGGRnXar}h-v@Tc4Gy8=b z@?eAPde?BOPQ!>`8(2w~gxa5aP_;~AR>ZTu%1$-82FL=2c8K;ewb;EwTtBQ8f`Oo4 z4~&v*+YJk7! zB2YZxSM@qBiQp`$SYLJ4zgDv(l)@auc)rdXT?Le-1n?HcEHtgX!F{U`dZQvbwV zS_gL_o+)BxP1V(!UDMIKV2qt>qvXaesNEcl3myzjavFZAdSOKr#Iu?AO+t7B2Q!UD zYc)kR=d;afuj*%~?x0KAnJl}>?a@35Qv6Q)m}q6lJ8E^`GBHGzyQlxK02;L$T4tVW zQU+8y0HR6*rvR`JT{NE){7$CA9@{!{7IrD{cQ-|{%vMJVxwSByika!mh1hU@{`WxGgGwLY} zsSsAV zue99df9tavY@oYWbhj+*=Tu4@M&^{M%U!W$FQearl$5u<@Z9F~n~SOA88cy9$A;sp zH(@El0<0#KVtf*$I5O#9LU=5*QTkq`;|G94%(~|PM_Id<*Ko9(edZ-8#VlwlDRE9f z)41MOf!Nn7XLaLn8-^etw_#ZKu5<)3*;ccg=hEm=TmP4( zIs@Z@I#GWYLYee+d<8Smj2yUF)d$cnIY0}nZV}tQ?d_G3=>16yMJiurU-z4f8AbJa z-_WevxVgP+T!q?g*Q%B*A(b2J2~N&+x%E2e<#Y(19Umwt`LkM0@y_clYCr)gqN7}J zGZI1I*k7>kYuzNti)KA6q2N8gBo9GR`&>{}JuJrzG}!O$b|_p4^Dcpa<~qo;W@f#irid6Q-D9)r*Cw`i3v~09~-kysM6ab$l-MB{WK5&&4qU_mNDx zsW%tvMk&ns=in_}vCU#0lld31?tTC8e)op8`sxHNSR%U@I(e4H4IU=6*g>OOq zRSW%arF>F~fJY!#uYb=`>nCW>?<@m>Pjhu{Q98GJL;nx*k|E(L4MT}5q6|Cp>lB4_~Ai^JMqep!M zz; zsZuj2NwOfT{tMR~Cga*u`#==$8E9(9WpE=*XT5PoqR-0HPyUDk(5FZzx*X#M)VB7|xPDu-ns#@n&4jwb-)zQg5i|vYLJ!`Yw&kzN!gRtHW;f&Ce zB-75Av~Hx$_w(zPUa(rROWV-h7j6+y%gLm!CS>&2LR1pU#9yH?&(}sM?mYWwNkf~p z{BoG{WPh5wNdy6vLJ#Gv1|sqf=Q zRL-Sp<>3Y^{+x&A!kY9k3FFa`ll$eCO4w|%_< z?<2fi)=0>m-%{n~Sz;Ld1y(nQGzAs0f%8}7a%QKhS*N=;1?k3OYvVx77Zfhc1Cg|Ip$irCA`Ef7a!fZ$(RP&Z5~S}{&>DdJ zAc3Q4l6g>o|HZ8ki}I!G+ohtTRFC~W>cqOz!@CYt+Wj#j@_#brKcZc_2;!sZbP*St zGTSo`z*k0j_*f8v!l~2kHm&FnJ4gtPeM3e*(2itWL8Avg*Yb`asGfz4F#4XPX!!;Z zB}JuIrcNzQ@~D&ajixUky4Bho^U?3qvY(5GGz>n&I^oznSeUO?P=`&en!H1C3FD3) zzD)lqGoWtyZGt^zd+8Q#+=Wssm*>TZ=Wg!6oWYRC1khgc(lqUn`cXxh<~ua!tw9mJ z^0Mmemm?QeaN=TOQPEolArylImt*o5h-R9ETuXHKY16c_ran9LiFdvXgxeB^_qetphyz0OInN?*^{BE)hT&Ujqv3genb?RN?N z6kg;K+n9*OZ5)JT0ZztBSYkUCpm-)~F^^{V)Dm8dy5-bJZ-f{)|MX7pJG;grN0bD8 z;X2@AzpkNp)jqy^xF~wN8sE|e_17At4E)3UYNXxS9Q?@-7<8bu4SFcydygZP#N394T-N87BD#X&UZIwmywY+-;D>Of3rX z8m2CiSFLWzdrng{h~Luo{vUT=9Tnx;zPo_|2|=V3kWflmVQ4AoM!G?zVF0O-c0f@P zkw!pLQW}PC5$WzmDQW2#2F^R+{yx~7-#KfY^WRyE<-(=weV^yf>%Q*$d0t6c7;8P# zKLD8*9-*x2)YlO0T13@bG2iA&UN|;P`i4#+w?zEOJnM*SB3B&L<$W)z$4;xq*wO3I zF|O;~kz=QWQ92!$&=Hcir%@B(iEMsq1{4iz^NbsrL&r6#Th&gB!QppQV#Kb;`Ql%B zG*nOG4l&QwXI5~v+rcycO`*}y-n|=Vy7c04azYXie}ct)RUc-{h?#278y)Ny%`q;2 zwPXsu-7U#|+fw=^fQ-t4<|w9}IXTQ4b6m_fNdl|2EAP-Mq7eAvNxbL&hK2H99X#4b z^b%Otveg)E_Ke&%=J-te=GT$vxTD23bWcABs3{A$c}94Rlg8{!^FfbBa0t5}Lhws9-lP}?~Vg>AQ1H7sNIJ@Nq|*; zE~%7-yUJPdU5G_qUhNCsQuYC_im6Hm>bn|&(i+!6Nhip~LM%i?44V|W(5~R?A5&%n zRz>(1-S01$KWTpXda0GJ;xjqjIU6FLl@^Rw6fcGY#a`lqT)(A%WBSO~*A)D0<6dTXk`$GWHwOx9Ho{t}Tb_C9RCyxBQg_JsUHb-f!%hVZkbh z0HDVu;r7jcWqMCo*?iD$#GdPm^ZH<8OWBXgoZR_qACt&-*Cv=&$BH9nO;403D+Hw> z%b8tM#i)ip@7AtoehXi4;?BsPLR-Ukg~_k!^ixMYi<3XEm_ZJ(?S~K?%Hcn%trKt> zvohi>j<>Co*bJ6w9wbGh+kNWY3?8Lnc|%*CD(h_)_`=Dx?|Wk#{8@x9G#8-_Gsg0( zTisD4g1evgxm2mO?x3dr&Xv=I1E@9^FOxhi>^+&;^*2vol%mn>u}*t#7KBRn3pTvy z`2G&*4rA2&CEjId*lW-3Ah|yU0+Ungp^JD6?!eb~#p&JI(>OoPK$WU6j_!rUbgRK7 ziXcxy>0^I@ofEQsTWxOY)KtugQi;@$C;}w7ysga|`k1RJ3P|0zfA1f34PvEMp&~F> zmPn2lQ%SS%K}-U-jL#Jn60G*MqhI*eEv`il$##9j?_AnXXb<)!GjERevPp5?&FQQd zQs9ixO^te9DJ21n79BKlJ@tM&G+!5O!^qUE`+42%*izY6KT*BRnWf+AL3iO-PSZhHe$cEWg)BR=&9UrWTTX$W7n~x z^MYMXES>vt&U>4=#eude-a`VL=^QXOOq?EL6dv`6s`8NRnSWz*yC^NPcdSJhNpPcs zkkGbwISGbC@r{swaf9;~*dXZs6g$2SHgC>UsmwfNjDC67yv2VdpueoX^&l5uhqe9O zKo9Xu*Cv^abN97eV;&R8%d-lV{hXOe@rWXD{JBBL&{=iA^W|UY?^&lOhX=H2>w(rq zvi&!NGJA?ayj*tse7FfZ&ZZ4Eec7n<*960N%Fm}}1{XZ@2@obtLT-|u!s2L$OH7ta z)_J^DNM#?_iMou_qEE4@{(a~k6Le#%-W-rp8ryeQ&) zbPy3Z8%lqx1E3Pqs{ah}-6g}`-E}Xc+I;Ue`Z^}YXS9-2!CP)F*7{nIXop;Ep8ZnS zk!!@S^z{^~UjRwNL1B6Q3-@@b=hMzB=GJ9juUg$}yb2-Y$24aE$U$2-Ae?gz@b6=h zyu`ip#=hqv2lWH4Uj=>xtGRuL;F~|663?nl0QHcIpsfULnOLqIrLmqKqg9T6wDT6b z?~NzG2qHM(g~wBEV;IO?t;@@RjaxM9XivpcG4sK|Cds;IU%Cj(hOo5Uk0q$-i3e0@ z8H1Zh@}Z!2UcIV-?uwql}BDPDuVdGTEkg6~~szDDV7Uppo28Vd0J%qxr&mCo^O6XgS}c~q;h z?S$80XdojPjXC(u^jBDeslnc4ui)(-PM(vrPt}DFoL-ZJN6J>YRhEu3MeN6;b2Bumu%yvEGtj2NLnm$4gZB?9X}8;Z@raf^#iW!G z$y0cwYgVxp{HkGGweNmIcG~wR0MX+GE$bg9#664Ds#nnQ4=PJ~Kt#Xv_X~=AZUcke z)q_p3N%*+!-B`?X0&3eo8#@mzap=1Ve5l;(_$b9qc0p8=KY&D!^rv=E@g6M$^=#It zXVCg`K%UG_)hh0?FY(b>i?XLkP>uUMOC}zlE>#E4icbll<4`Q3JLp_s`V-MmI2o;g zZdMhQER-0}`b(1KV&>lQZVf(>Q@R>^WR=GCgm|OkIrc|B7T+t4^S$0}eRq$Ilyg+; z^6vcomsjuT%i*HK0loDdnp$>5`xtVK1dvmu@UR6x)vs#((h#!y_Y3KKYDxC5`VnT= zNa*sVDO_6|5H$2JUT32q`5|O0R<>hJSRaSCu#Z2Kh!DBIxI(eqHk?4Gl5N0}Iyc9a zVR%I@@ckA+mM#exPYf6pvIRF~SP3?mx|a1`P3aQR|0w2rbQkCX0!4)VKKhg`sAfo6=pfHKTWojkz=E-xYqUiac_az6QRtF<(R}eO zruA!u@(?FKThLota~>#LsIOOxDmgAe+jw@*LR~=~s7dDBga8_7$@qns?;&3hoDSu$ z@HjDaO7_+}-5}7C^>Yk->h4lx)Jk)PmXuJN3qP8dhv92HY-mM2=(=T7sSra`Q(IVC z(RdmGbP6GoU@@vIPz9^>maPmj-}n77sft74oTy8=t>P_=MN-zZhwK;gpDlYXP~ima zd4Yj%_ZuJVfWdoQ?XDZ~0~4!wm3EI>bfmOGB4+3@4Vd!VkhuTD?q!F$?$44%Y~cRc zeKX0fG*PxZew3sDYXt_DKe2DUR{po07C zDcdIHrqQ-U^=a3sDw=76;%?gZ-OlTK;j2BE7s=yMIGcE2e6sDjnf0jY0F(dLruf&4 zIwTr>Fzr>gfKy+VtP*>AglY=smw3J$*FQ>J&{n@vt(}i%@wG#ma5x2p2-l+C(dT8% z`_v9HzM=j7Jfv&|HF5IhTb4xZKRdqs;8Tgw{h5=Cc_9XQ&DX6wSIcQ^**mpBQ}{50 z4Kt?XRsg zvZD*8Refm&ih}0 zZ5+OdYO|5;C@NSoOPQI4Y7#zZ6XR!cZS1CtyG{3%nR3-^oJI^CCmAW<>wUUpQdFP- zI>aELnQsgL&3vN*$CJj8>#~HlvVJKqZyt2v%MD6kTe|u(iQbKTU)fsCY3iBXJjcY) zJo0&_+C>TS{dCf?KbLLc;-sSnDQ$4#7dds~r@&zDQ}HttZg~g&FcP>y-6`vnlDwzy zww%pO_E0;<9N_8gM;Mx|ivc&c7MhhOW|PI~s=UzgDkMNh&<fpt?hg>NFAi)Spx6XB1lE5Af0}>H$$PSHqHMt2F~ZxoLcI5%XQ;v0T|)t4#;yrdC+%H?IE!!DM)x zTJh&U@H!^AjtWmCn8%~Y+C_Td7Ozg{vZy5ZH|_Z1gwj;&W;WI4L1)h6)nr{FFr>EQ z{?{-30k~FVel7^twm}R5t`vw2`DBt)(YAxnUpVw{k~uk*q)=fPn^`q>syJ2zC~q8D z{kx{p{?I+@8jWT%Cs9*%jA5#w*2o*b|&(}Q3C4Zs<_A}3sCV5P@b(0 zozp0iNbZBf?}CcRI5@+{xyZS9DrP@+*O4G__vTtb*w@a{@SUOi-UucmZf$~F%~9c- zx0u~Gp4gA2zM^s8668j7lGK{TVs_B}2F7$ZCpsO;`>S7#BZ(^?6HV&q-BI~?8yh{H z`1Q9I`%WwJvY0sv&}m)7BUV6uVQ-e`sImyekvzwYN@N;Jf6Vp?dd$O<#k|^Z-`*!J z>>Qy-p`nQu8CK4D6t1Rm&@~&?`t-4qkELrxraG0%TyU=i^N2#xyS%Jf*q%j?D?dKs zHU0hAke*Tc%7DqkQyJ0x=UhpS~>H zAs2@$=P2jTQJ;5-P1lOmimp7cM8_t}VclZoN`_{SBl>>(;(%X>Vc?*r7fCm@@q{&W zy&*00aWX1#OH4dj3#Iw`en%*)ZEkK(O;3vh#aRS`p7So)6E6gvFPK9(0C<{WoK#_- zfP#QMf9uwOmRnSXYwH@nML7eXzU%CIRG9lV9s*Lz*x9hi6IyrJ5v^vR#^UAS8k`bY zOoLY*64Ukg%ng2na0BE`XZCbM32B&+9?(I`=t<$x>hZD%$A59ql4xF!e6A!FVHz0#@1w_H`)w)skv z6*5z-k)^d66p{|WOt$0Z8~(go+^*=n*GPcDjiOZWg@OzS_wU(Hj|pg<9TPz9zk3>W z{>s!?IUa7`CofoRKQZ03@Zv0g_ea#_PLvmVOragHK%=tTyTXmB?@PO zd%=^2XfOuM{7!cuD2WmOPPd7#YTw^!CRSbVdowbMUe7}Mch*bH0=GmlS~TOE7m^EL zKFJEF!zt~5hEssWiuvKq-XLpB3!LbD)*|0MeRPZP6yF4a#%)1*6U4E#;eo!l(&v|D zs9A|Uws(Z&^KC(P<#m5yOg!2fT1{e{GC^Yxd){Fn;6Q7vrminnKSNwSv6&iSpug{5 zn$4Xz9?Hi2Hll%QA9D2gM={W*=^y_RO$;V{jNEl(X3MH zgY26R5o?B{T;Ie$8(fR>EU1lg#zEBp194yEC0Zd>VG`V}0t3_s#{CKQB)e;jwacsa zPR2V*MO8yybf^rw(}IPQnbVpGG-69219GMOS^u-%`vQ&jUM95Sul311#xP2~c-Pe3 zdYz9e)iZ*8CUP6d$B_Xis-TMF@67CTv)7*qvi_N65!yP8GUw}Ny8`R;vnOjAkBC6S zK~|Oo*BXbA=mgH`;SN7g1yXus^NRoZz=2vS9S$m5f`L#wKS%)|tS7Irr8)J&n|vlab}nFIVjWieX4tlh*B3L<89`G%r8waV*O; zv=07hWtc7jJgAL&Babyd5V$h07`Vt8@Fwxqz!AI)As;vt_nqjJtff0+8Bp=r(iwL2 z^+`)7PaHm@khq*xrpAL6yKVEHzs_9o2-Mnft$&iJ4;CNA-sa>gFD)K)^?t)O)P#ej zg%40Wj`OcmwQy!CBG$F*ui@FH`I?N0v<%aq=+vklRc^A%E3fou=iYQramoh3*EgH_ zRv5-XXw0ZQE_K2$?P4tQ@v}J&fhuwSdNjQjGh*Ud-+~SAoyCVr4V3L%5;Xhf;=ewU z(RCRa^Vo<-1n6EbdC`G^2^{M*Po=$Rh9N*oBMga3HKH^_9g!mZZ|p;vBFfu}$?kHn zhLP$D%>k2b)`l_?>t*hH90%(aq@jj7cO}N4;U#ZLsm3M7TpVKx>FjIizkL^6C^of_ z?yh?Q6dMOEiPyP+v7_2~8!ed7jZU134`eH+Jaln5BX4YqTH(ZVWm09&~!ABF6F7Ce0TLjOky~=9_QraJ%(9tSVVR4vmD^C zjafwE%cqsw;cW}Z(Y)s_5|m|Q=&$Lz#nAEZVqfLz4rsdiCSuA^mE3X~nomQ<;lXdr z1<-|<<4JhF1ADFPEt>vn*jh}>UvHe5;(l)U`8j)(Rniijo;)8_IKv(1(IiZe49FE8 zk)C%vaJS-Op0-c<@bA(Cc(7<71Rf7`1?Xd)kVV9|ihZhq%Rq(GbN8v~7`&FA8dbv@ zsLNm=C#~>S342nvIlAcYW!WKj{u{ghqXl7{s*MSXo+J`y zY|t1jda0ZnL!)DpufQhq*cKWAzbD-AAk`WXo0n7lPD2e~B9Qf@zM{slklW2mF0?QWG8^x*3(CxdeM6qJ%9Snwiv~a$c(XE?We%MkrEJiXV=I>vAl%+}}LmkP8Kl!Fii~)y?2&KpVmSdOh2V{7ep$(Zc6*{An<~dRi{* z{wd|pSNgQLAm`_PHtoN$*7|elwbv%L4I+~8<)_Nazl))l2372Tx?ihf-p;v^#ln1B zn!38ewI0Wt6qC)fnn~RpvM=rU?p=zEbxh#exS@Ng9UWDeI=Z}nZP`>mDGep-+kzk0 z774vqceHy?#j^vY%J>J|$42w#wZxul7W796sqGKw{o8_3k|Jb4@0;|}-Be%^T0JTG zAt$%YtMfz!@$MFXFlT0FPD&C6PPp9?#zA52bYl8`o4S7MqRgODQx%qKRrRwR&+vjr zoASQbJ_i#en4shKGB9%(34ToUovGM$9OX(el*v;P{EV=<_Z4Wc6uNhD=mO^-N~^up z3a{Ev>304Sl08f*-WZfw3OtSNcXn8MIWB-f+6QPr$ak`qPemCS@b#R38~LL<4gg5_ z6y#7^&S&qX?>RY#bNmc7&)%BDg#nwb?k zAjn37tF?I-*0Nj-izgmo;G}(g;fo`DI9L+kKGk(5RBr+P|5()D-sQrAg4s?$n+0_m z_rgC*zOAd(=5(6ugvNS^52ia>XML2uM(;58bgMl5o^hHF?+|$!twtJJ?BUX9TVL`` z6Nj-N$F@gJ@63hYq_mvAGQ@e#67NEe1K!Jn2SAV^1AQ|bbQ~7;j}oU<*57}`1lB1m zYqhq!WL0fN7g}U~iZvMjB|-TdAJ<9xHQ9bg`nsHzo7+bZ4HAW*4^V%ayUd(nb~$=& zP{ybAj9~?J(6TF8xD9OMT)fJi0=D_&yCx>zKqRMlh_)S1>HbBXJVe3Thn$MSyltq) z5BXW+=K|<>Lj)VBgth=gNcAAW-C@SkwzLf3>W>u+cLEAU!Zq->t5f$1EJUMkKFL7M z9qF3*Kiv0R(CRtVXM%$h7{p&o{Q?p!>XgILqNV?n>d*+NvkzJMs=VV|(kz>t z@D6mc0-%-U<-R-G3wSMkCYpL0UOGO^z2_w|rQ$!u{XwEgvRsO!^U20Q%pm7k4R2riVufcw8FK8>1lmx<*LETJ0dyTZYjw{miC zBFu0bV=~0~sIio>ql>jkcYq#My7o|XW*P*Ght1Tv!Y;tKTjkKliQ3MP$=X63VMLF*= zrtSkaBzhgc#?Cj`t}wrP3``UpP#ptTFbuWiV|qsn_W4q({$480N^P(DsX{9*EUu2a zd*p9-1%4AF1p>*JVDJGcK#m?LwBuY%W-hG1_dhMnB7OPudK1#Zo86cU=h+w7J>@q$ zXrS`E4b=MtUemeu%_@jDq1t_ad+({`Cd*DAly|k*0OQP{1;(h>#xRbZ&N{x} z>7qfux#C>n)CVQ0Tk}2usiKy!K!nGn?f?5*&;z( z-O;n^fmPx4{-KR344xlnnG5`b6FvPOl?|X2R9yY*vg9d+z9s4=P2HMv6`TJ-je(u$ z@vXm$=l0eUL2{hkZ>5n_yXBIt42&y9%K-58FIlEv4GU$+mCD|>j^h9(4K{bXfF{q> z+)4-sbB>uw>~8WL&rK7c^I=3D*K-vF3@fyRQju@A3@WJ^^@OcPlml~E0%=ay?4!y5 z;ErKL;gt)TB$PwJ{r^4ol?cSFAamSEQ3(V)9G>{=_Vlcb0@=o4gCas zZk~O)8;d-lmaTLz^VVA3*l;tq70%nuuCTOwDdJQHSI!^=8o%aw(?t0}_lr}Q*>M@n zB*C#vtW$w99Te}sQt#RmTyR0e+SCL`34NN5SWK8y<{*F2t3Mb${_~D*DW`&bTiaZ$ zux_U+$QyIX;WjWs+C6sF?|0>W;wsm{$2%Q`ET@YAx8-3oz5j;`Hl8jbUG6d{N7O9_ ztK`~kEtQ+7(h_xOrZJa#T{}@av51;&-;UK3^@Mfhg2pB;ix2*FFn^plYCpm*wJ+x?^D6MRbl4=o60f zxhKO#ZZ2aIfy~*SKj|G&Zu0huPs1WNjZXAk%e2~YySa2MewI%>As4gBFESvTROA^$ z^z4Cmsf+%%kp9n_l4WT<=8HG=ynU+%?BGL7Kx}S#h4EUb&A8n|Z>_~@5n?m-Gx2CS zFu}d89gKg5s=@DVI(7eH3t$=)nxrJXbU$MGV!+gKKBjie4?KWvd)?KF=SC`V{nsWA zd)sW9I!BLg8YBH##lYzNLxA)`;{FR}ej9~bFdqI73iciF;F^Q2Ex6~@d^y1;kC^Ns zADy4ESM~@V!zh>L8bh=zImDz_8C`VW#H6_em?QX4hLvCKk=&Sg^gy}jy{z-b`%L|hgmFV3wJrt{Y_RdE zN*OLw>04B{`^agRc+<_+qn0dTqPkXbtykY1V#rCeGQ3g>vDHm85S??E3w*bw-}TTL z?+ley2Dx5oC7O61N^&N}mj=L7xf~t_3disX6FtRlOV~x9S^Dlnt z{nA>K{YLqZTo!oJ1}>zo7p!8y)Mk&T2#Uwlxa{#i&=I(Jv%8oy&ACSy#dcQfgNu&q z8|lH(iG#i&#h=gM{qkrJ#d&?AoW~l)P32{BOs#^5_O0)IxDb*g%j%7PbVOzsyihx3Vh&hAFSpUcxcF#5EtjK6Po3s3lc*|eVaSsqFXyD<```!` zk%8y_b=2$t&!7Sf_+r^9w4F7Q(Ypv~UeW>5#3 z=4uvKy7uL;GBiYAGvrkXKk_n zLcT-em#3_aE%mPb4CGEoVfR(|1*x*o{Dpc;W8h>v+Ww=EcH38nI*e{39$l>S~)A) zG3-%^>WU{|oaggQlh z3TygDNwblWnpO~i^rZ?7oh|7hPO;aEWkD3)5j>-DFUbtKz}*qKl3NFG!2KWnIS6|m z4v2+gd)7WKcyQdvRLEE^Gt5pMUn-X?Y+mTRCM3Axb@zV`Ex;yzqeis%Ci2qU&~dDZ zo(Ns=YQk6O4CKc0yY0r!$%B5TMu+!CJ`M}a>Rttkbtdz?(9gShQ2>o1@A=`;?Y6?( zhkrEbH55hm&*Wx*n%tN#GmN({fLmX9q4r$`g-=&@LT#mmeuV_ziG4>PE9Z%~csMe} zu!@kfyN{0Z;B6ZB(^H}|&1ph__`Gs0<54Z^qufeVUM9FKFH6z_15Pzfvc&YiKY~P5 zo8#Sb!cE!sI)SUIsHMW9PrHobVdX2Iu+NJCtPZO~9GkaxXDg2Z6akk1W!3i`LY83K z`~wgXC;(h-c7~j*m%GSOqc!IO8W?ga1Av@t&VdJ``?l};*VSX#G-IJ%57%C|T?PtN|z>||-{er+^Pyz$z*|=B$ z4H08QVb~ZpJvPbXe^7(y=x%rkp`Ke!aiL8{49xQ?(-@fkybiBo*3wV2b|&f|7EWzw3LPgv)W7||1a6YFs5J#NsLmzNg00MNp5;z#jPN_>bO>++ zAUx3Io{WRKl^)d@BNO^R*n}AEZ`i{O$48DaU~Yi?MG@pL(d4h6*Mb;;HPF`)bY+>~ zoS@U#L~v7i6 z7A^kAQ9;3)7xo62t7QJ^@T=9I8;;J~Agw&;Atp8`jsL19hrDu_x&I#oeou_~B3UJw zFE;Jv1LBKF8wfdl+U?6JWyDmq0&Z>mYBBGQOdrFuUyDThK#LsxLq<#Inbo#<i!yEijGjYsT3E`*1QJr`a2#o;vW7vf9i%`47VE@u?QTxS-g- zVDk*9GK%if`sO+|sVw2gpZS00t=6;uT%hOH)-G9lrr+cfcPFg#+Uc%BnM!P_^cKGd zD#>2IRLlRTI0ADg0ovEp&*y`e{U|K%Pvl2ZI6OK3 z=x#+2O5810e9L{P%nQ4WbqU8dMY;qUD+rAj4%?3y0>X^2tVlSEXBATzomVe3XCSU^C<+C_8-xnwiN^~4~nYwXb7jh zHdqz9oRU(AR*u@IA{SM5S`&~ z4MRPOi|r2$po&Svl?yX|40wp&zwy!-*u&Jy3eoN0MCsfNma~mzRKUR(aTx%?3INspxJ-2<*tgh5IfW)4D9BeZ>Xq_(+rXUT z4hwd?R|w1hlw#w{vTf&ego32ljDYlMY)@2|fpp2x;C{jBY2`6p^Y;B_sdOmdI|Y!g zJ%8T2ZQe|l(SsA6VZ7COS1aB}^f3KFk(D*@3wMM8P|U;Sjmto9J}AtL(OFgaD42r&dcM^fmz>fX}X836;X0Joc{*w9sDyRwK`5Z){Yvz?f zTAXRq6lCbQUVTl@&8=K}^(78dv)h8wMx={0ji6$JcOD5TX$z;1Tf{Bz{l98g+0H>_ z;F@s{J`olKw93#zNoCm^ma@nr$_$<+(pQ;JP5frg689R1Rkf+lKqCO_5vOZkt&(-{=%LZe@ z0vi|P+;qi@(}~u)vGn9@A9^f$Z~OeC8hbzSb#y%IwYAeFi_Rbfij(<0B@{I1IV&Fq zfDhH$h9TBZD%IzkL`Bq!UrehPO1Dm zGWJ<}A4JjCK`U#K>15R_#~-g2S~r?LJPSH#ywNr{VqqK(5WSmCqLUoORE|lb#3pp- zA{RcJDsWEUHK(Tf`{z**k)@fT^pOOS9+lR`YBlg>Og5qd|{BU|cHZM%X%l)u8 z4D)Z>2CO_;lNO4gEVS<gZ6hLGP!ycGpS*S#YhIh4I{^>N zAZwo7{4{GDr@OGwowi5XTQPQGvHoB>i>0^rgdQ!F&^=Erg*ovF=Ck?${AZ*Ed%MsH zO=CmW08A+ZO4i(pT_du}VKKBv1-E_Q+^yatKno4t6sawbj&-uPi**PaZ$ox0gpI44 z&$l0ReiB%ScAIw#9ir0N=wuI#Hxykn2xXRtLc?SsqF3+G^3r8x$$HIVCAF12P7}cR zA>=Qd;B!AITxd7Sr(O}0;uu)ox6?r{FCUv5)L*~9K;t$m($b!-$+6ZRUE9XpRmFx+ z(I16atE?V(^Du#Kx^Hzr&0520FgZvlc&zDd2D5p_=%lZPWvZv+8Bl@k#%0$kmd$4l z>x{UmYhT&S%l4!(sC_n5X~~%4qSod5AkU~8TC0RR)ESkWla*>Zq?|eO<#oU1U}|Vy z>xx{WJ2nYKm!WZV5Xv5#<~6`IQtVlgGGN6LO?4>ij?@Z$l$Y9XJC@~+tL?6N!d?FC zt*pDhDcJIJmnoB6Teg1AT);vjM3^KuHVfHhz^t=bl(GO0Z4dH_I1wK(y0THFJS- zi#T18XGb>dQOCa%UPS(^ZMjFufq|<*kBt%X+6-#CW8zsErtQ*-tlz8mBBDk6?~kk` zx-%sBO|e?JnPUjTQ2wD5`VGB6%E-FSIo3JYm179wg3JeRTGOgjg{U^aYe7Lbui!wL z@_zn&;X*~$V zEJN)pJ2r^E@Reak2BFe-{TV+L!XoE|(uX)ED|*6jv+MVnF1(p`KV*7^DVS9Du-DpL z&fQOJ?uz2`@Y(h58Fu;{EeP{Sji%&@{H7~*ZYnABq6=k!X@4*rOG(PwY{_MC>A;}c zTb*5hq7Z!GR*|!pV#Z}<-M^jA+%iGiDC8WW6DRGif`7E<_daaWwJs%`bLbP7;;24wA3(q z9_wE5f?|weWw=F2Ig`h&y(dfG8v5h8cXHSy*F~$9$@_@HMYRuTm8c9Ow7L5jH;P$> zKez|B!r{p9S;&BgUf!O%cAq6>z9%m9U?~H%sxcN5Ie`^U4v~f9rwpl!l*D~Og#Cnw zufoBPo~Jd|lo-BMgp6^Flo$m-?RHAlPqql_G<27p?EKucKHnd3m(7}kq{kM=S&tET z@8YX(->@7zytOPDir@I0m%Z<>RU?6%m`xo?delgP)T;|~0N6A66cO-a_9)qbwxRgL8won=n;%J`B##-uUk zpUKxstTvr?MvSu{rQ0KWB)K|>cA`}wZi-?aWWs8cB29LeW4VPf!ltjJIPSaNwZ#rS z1vxDxFRhZSP#JD^eJT|kaIDKa27E8Y&%9_&&k`6c)7=xwjP36sGY2K4XT+jJ7{>VI zH+DPp?D63cD?~w8L8)jlpdB_3nIF~uyy;45(Rpl*lu--CZ{zx|v zK=aDyD)zcYaD}_rMI&(UOC%K%y$0_I0l7O>-xV9-L_39qk)It|fog{C=EBS)`JH<~ zZ-cE&gdn-A;PjPhnmUbI((SQtljWG|a z`}9Ml7w+A`x$9oPi_q4EjD7S5l{?B`9D{!&@TOQSuT6>!PnGaljSVjFe=ZO~eEBtN zKX$vO_Q>jL--8y*VR>@X$ce1dxS!;`M~e5Ra4pjh2{;`y)aeIz!y*m!arNh9y~BQa zeaX5bu4ROmSs*nvP)^BET~ZP&7{8#yX?@;-VajM)NWVX9TLT2t!fH@tJf$gi}kz>u}HdeEEk@%>Lv@-*rn-g zkhK+Rx+hRnKnGnrf*nDwGFsRCi-p`YqsD1GuZ=UE3!bzvNd_?~U&);4R@SI@-Uvv^1LU?sXqdYG@lIZ)#P>0{Rnb*S*II$SU!Unxv~mhz?)JXV=P;+< z@;I9i`Wf#{on&O|6-#5`3qHcS%HQfyUS^x;0sjz`c!)LjGxRq1?ei~2lR_co6ApXNT;_~sNE7sqf-82rGrYG;|Rc>;RU_Q_+V zAf!Sz-FcOR2d1oIB& z&$ravGI&o)Hgg_VXaJvGyTTV98k0I`_0u5&UUjD>ey!+;@b!usFCGg~itWJqBR*;s zUEz2)G)K*5WC>TMtcl$3D3I)nb3b)NiFaV3)2*PfTl&&asRZ#Vcgr+#T}sHi-6?vF{m_a2Z6)qw+y-JRFbs<)m#OB+)CMb0cC}Uwn+G zhO)QhMq|$VnP}$B)GnoX5s7_=p;aQU$le_aQXI=HshxhR>+#}81#w!S8M{=RHBLoy z2hq<+Q}>#ZI0GbJVL)+~A!KCWOFN{~j#P|z$e={snnOG4+Q6;fL3KiHRkhZKlTUw4 z>X)pN4GbM?joo{wmn7nJSkpGFXX(v)XrMuYL5jm7AGApHR_uY<&hvRqO~=|CKv_CO zM+_GXl_(#SA)82_A!`zg;p2xhJ2%(%o{xb0wM0lZl+pQr)F}R zWJaf&{hqLqqcbK~*z8v+O~^c4XUAt~Y~|HP?hmTfPUylQN%TIcheeZVBANP`K3f&M za?I*xQ6X~{)+&)CclC3aGW*o}!Vea()WwCTsg)1~%npdiJ*IYoBer_!-m?WDE%!A_18%Sh&)dImA60Hiq1{UaH3-)gG{(mvhnF!!lF z^Q}H2NP3}R^q^|mNKM67I&=4eX?kw<)q1$(L5kVkzR^`B=dlvxs)m`} zW~&C1M3LZf4_8{@hKihe!pz(l^G6PF2RMgdQw=le=4hs+5c>vP-G?Hl6mF1Ht2d%H zo}a@WeV{az=#rl6B)`NrRASsU#TU6hmMMaWuJ5WTcHZ znfLdK3`41$?i=K(j_tZu^YtY}4#d^`rAVP8z%rCTW*uFOPg=T~)|IlL+q35-clh-xH}DmwZ@&rCcPC5Oi+>f2pQfV z+sjc+4>{=EC`}+jdf!vzMk=lfr`iaS+6xs!loPzRykHi!+f;KtjL21zDO^2{Sn2RZ zS9a)IN3KyGgH%;n|yS5%Z7$t z;1}luD|rC^`}CER3Pev4ZLQc;2;cY&oX1&m%Cyjqg~G?jzb0zlF&f&3d}2gGg=oxGkwB7EMY`mt zhtpCQR+wG?P<3}tKjxpQRMrfg!?6}G9qwybFou_Q2ZlG=|IP;Uxz4S!tyGuA52AEV^X*ad9kFr%7&rSK zI2HH~<1Sx+=FA2Sb#Q>tMa6sqZI&K$#70$fxW!sXR>M~OU(5SdcZTV?2+F)~!)`g% zPXMSzvvlB*p0;kBqmN5JQJ&mCbR&Pd8;-Nx+`s;j7vf)aa?FGd#o`r{`-=?sp4&RU zl$4a?km0qDW$AIeszCy2348Fe*;g;O=GnuWs1bRl78WhPf0QoTyNY=Wxvr>2T~TTI zqG{8<5yNBCJQrnr7r09o?@bfce_1Dhff^3Op0!6vxZ3U;ZI*UKey!3}QwwLZA|FxX z&MGz?9MiVu6ZwP-@=$wqW#V1i3v^N(-|1(3^k_Fw8 zalmg5y%jSuinkpv)73uV^viBLB`&U^7{AW37 zl%oWIJa@E8;;-Q)x@BaP#;LTG7 z>YOR?A8SMXHP{qnfJKra8*CcU_VeG*PkDf1bTP?J8Qp&`4-f&M6HVKhyhmI#n2xV$!MUs$^G$%_bq)5MyDcqY}eX4A%d;JER z4*jcFQoX5dlcAB3WIJ4#n3eFOcS==^N)!q+-`^*vJ$~8BWHP1+XC27WR?#c5rDl&2 zs5NW*U+leQSXA%YH%zC5gmg$thqSaP%_u3|sC0wW&;nA@(g=cdhjdGeGz<)l)X)qt z47>~Xe?P}@-~0XeJm2<5IEKZnbzRpPzc`n!4}7Wmbw_}dIPxq=pq?n>cx%+qYV=F} zH~-u$j0kbJt-ZXXam}7^f`T`--?|2yau_i@4>*&6zx?@`RkhG&^vmydq{;6R9eia? zP0e_cs4}Bwg9e91Hiw0}l+4Tp^Wl1b1Yx?UQy#Zzdw1PzEZw5&>6X2(d63QtuA!56 zW9Y7AYpQ9LS#^7dr*ey@11lHTurKH1hMw~f)fDc;*4EZy>oUW}3ZIJn7giXyXvJFWJhCCH+j(i{aD&BKLp; zl)#w1kxqfj!izeDj8@+S!89{Pc9G$c+MGkkgg-|{Wf&ar0hOp@BU})SkNHJ&$0x;B zU?#ZQ5HbnjfB*n#hcEg8-<62*S^FOckug_U4rnxAZM9^=u2T#v5*r*0GX@(2k$VDJ zex;AUzF0a;dfCdXnSS!M75EU_A~r+oOYHdCuO=2FY4FXx$_~-vYxp6TLU<;%Fafi+ zG^*NezOf=c0=B3QB+K7#Cq}M_q%WVh-?-Myw_hx9>C6{ssqLJcoNTru=pU)&(*<1S zxx$)lF$$tLuf#XvO}jFIZI%q2PfCGxJx7IDN4Z zTAb8{>DRfS9}Lnr4Ifn)XH8|a**)+#zt~kIRTx|D<#0BhSvSAj#f~6oF%@xGFnT0D zqPsmtxA|kQ0?#ca!Ycv{&!Xbm{x@P{)Znp~;=1TCd#Le{lgFXXN%Cy{@&aIJa)y#u zS3-OT!zi+oK`Q2(cyA)H|3(Z@BzadEAala$WopErNOcY5e+U~$1jA|AUbiP9m?u`7 z-vaCRlDYS^MHTECNY$mkIZ;CfiAw(ak8OvL)xXu3y@85l*!cCoqMK|KaVN{{pNVk{ z2oGBsK&d*$3Og;U)zqTvy)^MV7Ps*z^pDgjVnWsZV#(yZ)>|{!sZWOM97rTBwh#!_ zW;yy=d_k~S0U|CVB%-)jYAnrk|LwA>flWIwG(5l%*k1-}U5^cXpAlR37I;rCi~i%A zAucB>Ry3ubK+GPcIg}!9)|E;err<^MWz6d2pR@GSa2n?Jh zPHND+_2N3SWAFZz;?#P~Ag~=YxVSTE`$bvsY!GLa4A;c}Jn&>aZc;6??czN%kHOPK zXg~&!q}R1>lva9Q?)Q^GPgzuoSP_&jAEPj;&q6BOE*i>A+Ss@aTkR$S@@P?6aluWkAwJu=a1+F!H6bhOIEAkG~up+!rHQUMxR{+@w8phAWWM90&X}-2(Ctf z576``lFfi2S85gt|$G>L1gS;orJV0+0FvH=tp^@1B&evB*#0+xqGI+x!JWb?=ici3;U5rhWkzP zPCYyDR!8VvNSs*s1|te@Ps7?yhN25>$NiBoUeKN8Kme@K?D!`${JU_F0eO3M z6bDHs0K=LFD{v?VD@LabF~{8uJa5~t!Jo2_)2xk=ON^7D=UeYr=SL_+EXz)wbjfo0 zKqYg*s>aS;Z_w}`=E>(jA!#}b$%A1JxVkkC|H^|?D+VjU>3OB%23~X`#-2x6#_m+& zf!HI|jr8?7M3>x)s=+}@k>8Yv_ZsPvFdbVQnwm8^n!3?~2!w2JdB>lf*31K?zG424 zN7XwQ1^+@*_mzdmeIKKWq9q}gyahb{aJ@UsfdH1u<97Nm7c!m#A_vw(3sxEBx#e%W z_8|$O2>h6k%b6`@5`v+`h!zw@$YB;t&nI%z#qJ(K=$m|cZts6RRs2e8rAI^z*dV$M z_VX5gLoZKH5zD>|!=g~XqL7tx_ddAkMi_;O=)9s93#ClJXJBz``+uY9KGpq&_Bo-b1ch_Nvo%$YPN`;!>U<%)>to?*feipf%EjhO_+2D}z5vFG|p3SWP zF8ZlIf}T_B+l>`jj{FmnXNY~SV7pKfCVr|qO*QqyI!l5J)Uur^krzW;ZSTx90qD1IXGYM6s0-!>Q{CY z^?qgQ%6^^LN<;z#Y2a+7^0~#Sbs`89nq>sJvdbxfTt~j%ukCn$HX-(}VP1Bk71eEr zY6XRmLuRGsz(Uk&z2O(16A~QzgZQ=eMNHDZElTV1-o5)LM&gkc{{(mI=oxcrK0D5Q zvb1vY9>44V0MXKPzCDkD6kb`KzT#yC%B!2@XfBy!DUAlO9GePt{WZ>(tO11?R3aB03T%{S!*99Zdd zL}MI{ej?v)^JQQHux}P^S9(=hG))=gX8|M;YhuS8(zS?0BkMZ4^>pl|jq7p-F|XO} zaU55HaZAHiRU@76x;c%%W*j{NgMqL`#_v)AP$vCwtspo##ox%eYwaoMdF~K`b>6ep zMXICOd7WU`O#y#g<0rrMa^_C(Hbh{ zGGsg9zktWag-u6RjAG3vZqdtJ^M0DTOO|Lk8HnK)4qiWJIp4~Qmjb#eRMm%94(Zs$FVGLD2t3ed_BQnc z3LK|cpF5ofrmo^wnmbWriZ&!fi9SGriUlQf8lq2kI4t6*tO4t+3aznr6KV#NFWuKV z^-J^ac>&Doxm`EUMt=1$z0lBzt$1x}QPaud0*5WhS3D#1AfPWbK%4oDQL!sH_|$gn znTPmM*%R*TXP5q(s;a3ncbRrc#Yb|$vVtr}(Ma9XJ}UT{{BUocc+`+W@XO?jsMDiU z^$0B%{c4NkPqgAg9K^B-C|uycJO5bjH#OQTwskM#{6|aNl9KawapzFOEaMKG*gWz^ zLiykRiWD^Ke1(dMSER)M?ziX(ti@8@h@;ef=eP1BK9l!sV3(@EyPoWtZATO z`&~fEEB&UcEj#2u^(#=-FbB140_?Zycp^FxL}taWAWI2pR_t!s-|EEe;;bXjA#p5a z15JO+0GhkJ-aC|^k*Ro(cwm2bUdcX)&EQ83R3`OHZxqqaf-b{DbA zsXEUC;;^_PyLa)+upb+_jgl`gc!?}tHaf48_?%6!kKA_LdNfvRZ^)!G(P*RF~_7GHokE=35*1qB7s*me#g zB-g?X4jfJ&%);c2d+4K|26+N){m*a$8iy&@jx&4{LS=bcSq4$R%Md`WWTQpTk$DF5 zuj)+3)ZI==2jg+W{!C~NLz?kNb{8@nuOq(14Dmk%>SOod3yoU3XL9(_OgVF#tCT1E}5yPX^i7H*3e+ zpHk3EoMFA2E(z-(25O1iGptQfjLX&t1Rl-5>x$aF=^N7;tMo7Rfe_jO-!abPRWO`R z?EMr@AVN6d>rM0&5f=N>504C&??LMn#_q8$k4b1F5Xa1BP$x=I(`L%vr)ky=Y5O_# zlB%hvEAr0oP*PEns|(>KTt!Nt1W#LXT<7ZbSjpEKQs*pg#vJ9c4{c61p4bF# z{FIEzPo9rl&4K$q)lWbfl)3W@1~^Z#MAGacK-Tr1tR%NJ%=wobf@WCXhQ03=Xn~TF zP-3sxS$~B1PZ{U^fW2uLg2zm@xs{SJ|6F7Znqpizu(i}-$%W)lJACDY{SN3^F#r(E zVDDYy5ZA!nX&(=WzkZzX7H4kNf{t9#C%k;BjDncep!k=i%B=0l-6u zICJz0<9jyw9%FRvrwX~*=G0190qTtS#^n#=f#pEk`rp_}oHZ54c-_ zh#)nB;WnNc%3z@l63N2sX*X06ms0w@`y#2cnOSFq3Xdj$ zk{u%fJ67s)S&^PoF6nohxs~2v{O-r(eRu%lPLxR5FSKgHeP1B zG^E{ovrZtl)l!dcxZT%y6jqF~?uI-;;MPlBs!whj7AsOEJY4q+N3AM!p5mCG9>(>? zs4$x$SWA___<3!e-59zEdXFhntD_aIk#mJ7B%L)V3sz!q8fWX{IZI8N+5>*5BYGKq z=QS$C)~t%5%T5?w1s9~@j5`680Tg7#xj(_q$9>yT9^2;Qr=qtQ`-o9Oj*&D0)ofoF zxlqt8&~o4|`{Jb8zm$?+{S$-@`%EQdHl5$97#vk6S*k=lb}|HD=kfO#x^-$6U)zTR z3L%U`_}eNb)a=Ji_(3gL7#!OxG(^anda_Vkvp>J~(3i&rOrH%hzfNEr~ii1i(tPKn>ecV{`)vm5Bs)}-~ z0XS?xB4|rJ#6h2}bJsF7f}vfnrbcj7GprQM9t7Jm0 zxHzAM4yOqmX5cT9F92b?qU}QWtF!az=qz;(yo+_I+A;#-ce=Dy<@K4Iv>~lYv1vPd zQ9J#6o{KLk1r23En2*mav7O9Y==Zu8D=JNE#|QU|W)@60fydqi~R{OAmt?BlCsf+;Wj;8@Pby{ z?&n&aUapUS*)9S~N7t?NqO0-3p>P0H<{>FiDP8gZEbD`|93b*YG1$3=Z1eWS-iJj3 z6+sY^mW23vYVqk3XzmzfQbv?VyoLI+p1^B`wb@V+V+9b+X6WJ=Ky5hvc)O_0^6|yT zZDlaVgP>hn5TJQZ-Drf`3`erlbFt?v8QnwEC`I<&DNfpD(rniDb9A>|-e(X64ky0JK>KKHtj3OCy^okFIrf5b0Ot?y+! zkM))egiZnW<*Q9QpMc9%<$Ih^Etbyd1MxCK25G-y$cMe9{`@}SS)(V$E!Sl7Wv*QW zqBq78p4?7yW`J`3$HKLVn~=UwcKVy)Kub>@aU=JY@h>f2{*4O{EMKu4aq@R&J%msT z00l*l3&lQaf+Ah>~!gHTM0TfDA=$1PchV*{n5;|-@)YA61< z6LAk=mv%m?Xrbq4duPlp*=l{kN#Z@qJ@C44b>yV~bBfEFLT3Q&7GxR3~V@?!-J0_jnt3X2&wfjj|6E)3Rs8u0bmeXTJJ2(D8BTtImD$(t&(gkv|N zKzJAGdDL~^?i~VldM+#yTd#}icGw7U&En*QSZXZ!9)c{u788~qK6C9CUwXJkpHUup3{F9M7vnWp-|gE#e7={^)h+QFp^pCEq*}ye;Q?jMt zF`KTRNZHX6u*jSvcP3ZA-cEx{eR%#2z&(GrP!~C~9`l0n=taQ2`D85f3SgEI!-c8Y z+fs#5YM2W$OYe5uHFFd;5Qjz7a2)4EPy&E$0B-0PZ$NC}C6CRZ>C32?MpuLEIjQrt z+mv=AXMD%*#*B20)u5oy?stltfI$WID8&*Ir}VZ* zxJ-pz;(O!ir5;}sN`9OI%cFO{JW1nt4=&A`H$I;h7&eZ**dv08XZvhfKgSgxwADB= zt$*l!GDzVbe4r^LAnAR?7)0byT8?|VKQ4`k+DQa;`ofxZ{6|Fbs`!HfN`anI{VLBL z9DqSuj{^h^fOi#Y|KS3IwKydJ1diq8ljpBljx=6a${!r{5D5)&mFiVa?@2R**uXN2 z3CxF|%gWS>_5@F0537(00Cpm>O=03~9B{R%*TQ9@h*oJMd;`e|xRx#N;hucNu93;j z5cq7l0DoJ8RqXI|Oj6w13GkAENxuGtE`UY7%3)8n<9F=Cne(!# zT6w@qdWI^}DS^qYI7h6Jkjr#XAwdR|FivG^nV0JCWCEi0I|7L;3D9|EY(~;p4_i<3 zOcS=i;I=8Upc`Cy6S-vLuF^` zJ9GX38PgLIM)VfJC7bYeGNc$*`z zOa5F%RG30QBVsWb>Rejw;tGRc3Vt}7WTRi`x^DtTMhtAA=cX)*!7((V-!sA!*i;Re zompED$AIA6TNYIu8i4SBk&d(2<-nTBgu3>lp=B4u(y1~F&=0yPe5OH68S&}qRKFrb z0bT>zrKb!uqxMNjR~~;;+0aw`We(gVAmDY-lF%2+qXAhgwE$uowxadtHP8_h*OVUX z0yH!84cU)6f7{nE3cA^Rh*L&;G{kAL_e51OSf4|H5H}v&nM$b^$lRGJh-IOGxd$gs z)Xh_C)C80W{8zu~?bvIFfEl9Xt)_m*$raydw{wi_paFcA@_xSyDr1_r6E*40l5p+6 zyzN*PY`N_A|Hqm$YW0|nfT|=1?4ZY?T!xP4$t3KZ-@6<$Dr96>e=Lub-@zQ>1CU&{ z?M$I2BeF8Hf%lNBQ;MraAvT^5XLAGkkX#ZuaVuOG6d1}c?A0qcmRggD)ACf4*gQ~# zEo-3_g7r-4m;tClYDH`Ti|uW-#KkWKq9lC2XOb(=$TZAcFdZ<>f8~-|cY?p7tvz38 zhA&501H7o~)h5LdD)t!%1-UVHXpZ-ffIkPZG#R~Mb( z)IQAd#H{{;T+fJ-(?D&2={#hnhA7G9Z44t@rb~^9K@)ZZ3E=yMl z5~#Qo7wX=XR~S`r>9M7H!U3hjJ)-n}*;milL%F#%|J;0&B#Hjxg+qk&RU2Gd7aybJ zikvN;>~IBnvFDh?{vNQD@gk(IoBqlhF8+M$%wP`s2=s^Co3|f}y=zEt0PM(0y}5$~ zMMzZv>?%VeZ%vvDF`W-hmjS{9+vaWgEtXufX|Ey-9ujRH5``fkYe7cB7*xWF(lO+* zJ0U9%99orOs@N=_uOjbmh!Klio_Q1wR2W8ec5_TJtChCC* zWwRRX=Z$zYdK-ooZI5$h%NeHNhLt#8F;VmpHE6oK7Wv`}{@Q2MYI;%_RqvgrOQyfY z=uXwho+oAMsoS6p{)Pd7uNCr|;C=nqJQvi@BO~jtJpWQwy&+m>g7ApAED{5K5#Hw*kX3I4CZ2>kfp8sNVr5Fp|CZw2`O zz5wP_S{XLQ-yHB!6m-%_D1+)U_4T!X`aP-mWlBA9j7MmrYK+Qt|5ljOJM3sMrCguO zje3)lQXBwqSa^7N>=&HbIbWw_NqP;n!I!ym{7xbPb(jG#{^fb|aX(Gr%Q*T? z-jJqL(|~6C`5Hx7(>mb}AhK^3i*z?zs|h4AfUyJd%!k)%dWPjV-e#BaA5)~VNP`%yk5YPfY0Ys=G$Tty$bZVxa-N39KFe&uCUFXar!o+F3#Y9E*0M(}A)oKL81|Y8$VRy*+6d=sS#lUCM+9HyWe|2FbU&r*L zHkiSO2j2^!i!`MxzBEt*OX*B2+36A;1r3?zz>!}8nIeXdc#N&r;8Jx(bq-71TXm7d zE6t<^SxQ3j}cjb7W=2n-Ib>DtXw`Y3P_Rq z>01!5Mn3JO{6J&C@8j}ju4pR-$LUxnAF48wmRIdx1ea)cm&-%WAndoUW$+J>*cgsQ@Cdl zfT$-t!Iv?@VYzjFW4cI_q4{zxy3o8QJnwV5OR3bcIDt>?KNg6pfqxkY01eQ+fdI^m z%0b+E;Sp4}^qNF#$mV=<<0hbf?HlL_IrT4l)mnfHeS%#Doler5_=;K8aGFT#-EA<18e4Og1NOli7EMh{K*FuZNw`O3ZQcU z_!zHOdsP*vqIrw@>M-!m5JpP~2+wqEUUM-sGjCjhu(=E#LD*rlG=L9;ZL&xcn2lrL zLzL0=ErR~TPspMd)Sq4WeXr?5j+J0?NEdj^FmNo%L$YxoNnvuIR=i~~z(tG0Oooiq z^TmP!4xl6I;0!5W z&!5Gh&mXq4yhd^xM7seY8`ew@2gxCJJG=&4=WUvIp=!B z@L@%|CJ?T1>qp{`e!|Q~d$1v$w3HVQBM8AF5F||kywnZH1R+l8&gO@0@DyjLrwD=7 zOi}iSA=prV3{6ZXWhS9Dov5P`c>g0p{N|`9W(_?F7m(ljK%l*zgLDr-*nn5#6!h=1eqd3W+>>mcr_c7NZywm3?GZjQA}q9jMN$AcZW z=X}iv4U55=SMch1OhHxd$1*Zd?i25W`dRrGP+$>8y{Alk56GPZH2pNt9pnFT89jOV z*VplHTMHpZHnkq3Wf9C(>D8n2B!%}w(AY{H&s;Ra#EuMe?uU#|LQCkEBveAKJ*<|l zM{C@#sORgfGh}9k?mpB_Rc5S1D@$VF(pLr|_K^H23p*51)>JPJG;>WN^VlKFc~!6hFgF=dr!^`db|Rt9TF$LzRVB< zFt~~pBGiSAO9j~gKrf#*AA3=mZ~dm#yZVhz^v&JPsph-+n!@y|9z2q=F(d+d2kUsM z3zyeg?gyr$mEIXKIXpuwj-Tx0i<5KyR;K$gL@q^C0W!$=h>U0Lf@(9O?6DaCaDS-J z0!I6dghQQlf182vbd8q*Wn0K9AWalTH#T9bq6SY3;(W|VPv4O`fc8fW)|+*PyZD#%KF`gv zR)Dye3U~#+=t$|aMu5p>s;cfax@ps1<5KWU@v%Ta78a@cFGo?NVI23HwTH!HhX-bg z!Qtn7LsTKLpYV1XWgZO?$=t!>QthKKfbCuUrp?KTF^LJ4n~TS^9rEG{9N!L9^(Dgj z_G){$w6fiRmynP#TZgja_IgjjphV%BA9^=Q4nf+l)|FuV8@%%>GLJub5nm2_O#_kB zKl?>^*$mBB34H)zg+fhj?ZNlZEB{?LI_Pz?#kygLyWd{P5-k)DE68br0?MHk-gVWH zeM#|dfyISK90S^u-6Z3@B5S!cv1|w|^-rp*n~%;L2``7H^-Os{b6sf<$kNI`gN|w~ zP6=+2i_qIG)3o4Le#fwF97_XGc=(!7QbR(A*R%JUz8WFT&N+WEKgM&M`wrXvAEb@( z1zOA3=VpA>EkhW5yLchp-AwO(H??PazLv=-zw?^@LI4m&Q2eJs=2);Jg`o^b_{)j{ z0!|Wbk~uM}=tved4$KIEzSDn*#)`^;Z}xe~uHs>cAVBcs4ekOaJrOoKhxRmQyXDsA z`LHKSYE^Ge=ig@N8M%a|PsxW0+s&j6if4#GoD_%A3USj4LT4oFpbyO+-TYSN6aIEo z6;tK0r(26hfv(kshs7oze6yG(r|yg2QmWP&@bmMA6DKiPmFz+G$Jqa%ut@9%P z!4>eg>0LF-iENmewJE0j=5f+CUcq|lcp=VGz84RE67u5YW`ls4Dx+Ko_Uc>!r4@PYU1U;B%S8Ql^zz7Z&+JC%VM(5SCxGK3nIvPXB zalt#>#w;MdA*LYFWu$z=;m=bobv8w`Cj38h6Sm#-Q1vv%2Zc&29nJi}YkGhwCzGRZ zINZbC=;~cJRe^?7C-y>I&NxArNbW(T#=)~s0p7P z$<}5m-Fd!@>|B1?nvAL3M*DaXPcQzFMAIex#BbA}F%b{W;pTaGtTzGu|#t z@v$J8K+Bm+w?a!5)5H4cN&ED)eiq6BEM=5NwU#Z<|0B=rQyLM6ga^jybId=9mbQ4B zYh2Gi$WgtYDSI44Gn2^c+bGLKRI!)>4-hi9F>gfZx572z`aBPO_Y@o-xH{dC#83QTj- zfb$e?L!OqYOhzMacU`S`Po~8b(cgS0{lX5-2@J7ahkgSW4krnU5DI{hwg zH@EdMYUGf7Dsv!=Z?lc0TZ4594qnQPlSmb6`lP%pQ4jI*u$d8-vXl zIte4XNDah3CfAFLOWRTDEBX%eG+s`IFU)1t%yqHoKletS&#GVOQeM#4a(Tu{!o=M8 zJi{D|Pqb$R()9fOuHi1tH^Ob#+CN9-JT4TxXLKu;bI0LW2jeOQ0d2ICMAo*+zC9#_;9gXSKt+WeLC_4XhM%{+~K}2ozvlmf51~8MhgC5dI7<}Ro6GA{<=cyji&H6^kt&z3*Tk5)%NYNmp%)X~rI{xwO*JORJ&K8S;^oi;+Mq!+Yq;|&K!lPR;iE!9G1S6%6v8V_^*^@j zpJU>CRXwwgyY~wcN?)33#p<)Eq4R(qY_eY>PvA+yN!~+J*3H)qW)mbQs7Y}GHX++suJXWE8pOD zar)X0kSDmm*~^tU(U8B0&>C!c4xva4Y?wfH6wyLw)z;dO6D(QooM#LJSSJ$xW-?zP z#Li43V_cT~$^ijEXOPCPuShxz(nV#d)~870;u!+dd4vK@SEQ^Ph#-~Gv~_{A;PpjU zueZ%b)LmjLp|F+qSh2Dq_dUp1AYK%)S=_JsNt54|J>n6CUrYO0YcG(}| zlaBWgxPBX>+x~4{{A9!>Fy>J?u(C%-71H zmbb3)YCxZLmarweBl8U2_Q5j+E`#iE@;=V)5qi2(tWe-kYO~z)u+jELMDyEdrXfs1 zDYTs$Nu7j7%(*bmeBh^}o%RWFJSw;vFC&}q9o~h&IzwHSZa&PD+FWF?y7EtwuJ#bg zJms?G=eN;2^__f4{jq)Pi`}Q18KALyZ#3jR+2_01QUilS11T;a)T45p=4xAGH?_G4 z%*6xm--;N4TNP&S3#gm6cnE4uH^-j4kguQP_p5yP$BATDWg@ zz~-or|J<=U1t2IGLUkqTdjVUC^ z{1yut<$@dKGXS&6T6U-ApP52FAB}zwQl7~OzA1kOyUrN_TW#?7w#YCSBP?w#v zmBz;&e+HVsfwJ!YUJf>;^8G0C-=L51ilNwZiDbIN{0T{`rJ1=y$=5!d67A%f+heVM zJ_iTKTm1c6xlJb%+gc;i{Smo!4(OZo43XZ$QYn?l`U*^bHjF|`jz56%u<9KXa=|4H zw658;(|Uquq#f=mIS-h7nTr71AXoq9$5Bg7AB_X#|C#u8KTX2m-={WA_F4JEIaQrr zPPu?vULWgEP9$7fdi8{~zg|)cbC8}mEawH7(-YdP5%W^IwqjJSoK=|padYcK;=wZUPD%+y#Vv&jYm}Yb=^7G%Cc$$);CQ z#*rnPvv!LpcEk+<{PCw-Ev8?ld&S}gH6Ju=P>@}|SrZ$Ia9sco3O1F>ifJWF?xudJ zg;cpjcZOl0>CV$HcC-R>Qm8iXr7X2$5~}^5s4Q<5I*?m%o;Q^yQkKDl zI|pVO&L8Z^Q4--3Y5|8DZ}6r$F+<0~@F}R>()m@T9U)>`v}x&~N4V;qX(J&P7$Zll z79Y2FIeY`jt5raB$auX-l<`2z`pzI}oAs^oEnVk*?gPFm*LFd~<4UHW1DaphDa9Tb z`gm2Sq&I)qC!BI~^ee}?t{-BQee5_IS??i4TYPpTsi}7vSeS?qv6?A)a$W~rtdcwB zqC0vHb-Nx!swX)GT9Q0-1&XlDmh(0zoDAibHlljW{{cQ5M?u8k? zuL5luNp6-xih@|+PZVauxjtS>J?a7#UJ(!sSG%tALG!?#1j;&lymhR^ZZRGg3Agc& zsZSK_Xkhn%?Y*`Ep22{RXrXgOltN|OVx@<^oAs(7D2|34#G zz^p*!zWB8I22k5SQu(BSCO|@YtkJG^CFC6D`$@Uy#ol6hI3(ajx;U)rVTgt|Ihr$G z;+THla)pE2UCC4~iwyw;;YV*2 zHcAVj6Yw9$=^Tp4ny)1CwTrfNp;M==^gs8issO(au?O_*_#mx;r#iW^OmcJusbhQNrQc1Pe%}|MF90hHG96UfqV(FqbCB#rqrm2G zKJYN)_c^iJnH|^LTCp(i3#YTf-MsCj>BzUP_Az_y@GDoYzm+9c&S!O}C`W|LbY%@y zg&+i*=uw%P^3>7FROKc@XL!w^RhnmUXfz_UB1eg$WGDbOGEMmqitM z>5Zn?H+!>M!E4~yqYhz~VmNyQujur5OJB?AD_1A>LXl5Z19EC{iqtx=MR^m@$S_Sl zoNBo_febopos7S&(CY44PD`Wd7Rg28`J-K9VK~XWCH&I?LO#>IZM|Af-I4%lQ@ZZH zx=pt6#`cp~#qJQCH`Tn3hL)>3=lK1u_AgMZl})Vrlgjn`(43K0<&9YcJXWt6FXf%H z15GQ?(3?k0d*h7ObAv`|kla{fGB-Ddwbz8m%`00%{tk@bos>^BDl+v41VDI5U+I4xpvPIT3p1XL1p{(i&5+ro5k z@USWeF%gw}lK7^BFU5{nvW{~eM620VGa#V7nihAHn!65&mKYR@Xxxv2J_|#bW&6S0 z!M0c`qM(}U8E*A{^IO1A-vW5QY}0Bf8=H^1@jV_?e3KnSUDw9ZZ?f2Abjv+6t&u5O z_FWbEXG+dJrc?KCOb0K>`-gB!M%m4XG&o!I`IpWRR&=$S$F#^)bZaNz1?#lScV~8Q zD!Cl1fp@o0#t9d-CF;JUZOGZ5EXSacYpGgSyvYg|C5NIY_m=LvTNh&_ia>fkNXEMBpLjzb%Q&Hy3>p3 z>71{<%J&YxjR_9KPU^H*{Q(a?4PB9=cl)(^pQM4QPc(8wq%eSIu%0t2KMw-fop~J3 zw7SEo?}?EN_9lxNxVnyJ!n|l~HTzbXqOnUAZ{OH|K;Yx!5nGuDkT~>K{O*%|IJ8vv zZe!3mL(}7?f3iG?Cs1*TM%!8@v_=}fFksWooOB)oP+ABCudnH4`KN%Nfa|H134gY3 zT%aMOJlc#Oel_dQHT=OYXF>}R`xdoyc&j)p$VQze4b{-e&*|<#7CK}*B3-Cok}Ab$Zf<@-wF}($LpvC02vlT6{J1?j_vx=j zCsU!TIP#~IRxiM~5a4h@9%L@oRo@tBWiK~@9)M}kOFP%3A{;mZ^A5uhj~*G|@_WO!T4X36~Jg`9qF;jdXb z8*z=+<>r@vVAftS-r_s?y>D-B!#fs>bE}M{a^lA8cAaj%&N|;+T>ljOZK?69=|+C% zM#*?O4yA9%GFH6bzQuqAj4AOmIqj?$ZxaAte{PWOFeHr#Ond|%HYI9E402>>etD{V z94$DSsS9A?OvVW_Ght6%i1-wYOjtub0u=4{OMK6vxs z%(-=SP$s=;45;-xJ|BO9py#SEf5;@(`2~ZU!i=@Ng5gv%vwyebv6xH?gK|PACr&F6 zb6f{mQ|DMV0}fa^&fAaxR&nX?W_TLENwO21W1TYvj!e4Z=g`SgTic!Q zL$5uBRhqi>UdU|du>A2&`;v0-TYBYWrq`zFc9d|JJ{Ru%(IEW$TQCh~6F-ji){NbP zOiIA*@Sx0aeqrgSLe#UkJhUgI^sLuJ9f`Y(?c-12|K0p`Y7Q^p1!WLq~x}4@l-CoSJG* z#Q@29+`mZLx%Wzpf4)`SK7urNmD54NaVz2K zCVhiw5x@HOy%>UShpO)#gi>njE$!g^iUo`ab{prBnE@+ueti)Wr5yQTtv7OOzF|hj zUc9x#SqqqPwxscG`{};=5yszKC96VmKgA8@-&PkgH1?%!($8O?yGbK==*ab0 zj!Yh~We9u^k-^ay@lHl_e!w+vs+%~0gYY`E@?*2`y(!4CiZq}oe#NZ7E56M_dlG?b zs+kz3s(TF=IG$7TckStTT87ri?&~IF1TtKHl+*22)_z-wT|CnF%Ydl_ zMY;!iaar5@oRy5T)5c34$VC9vWok2)`OeP~>UTQ&m@nkSwpiH%L#^1n6O-$fM))LM z3>edRSm<@wd0j=-<$z}Nh_O@DhGo)|oF}?X_lR%EA5akBKm>pZjn+161Vazfrb6yI zun4Hre5s`Unl?6ix5Wu~L-uapF|@(Huzb5bB$D9!<~_lrV^re=`;T3WxDT1u|FE@3cql)X#EdZ_RCp3!`h62P@o|40oj+RTrHyoA_m; z`ug&L2M-4`Ff$P$K=c}WJE;AEwA@6_vge|M4L`k$g}~092Vcl7kt5|TK>6XTeat_U zd98=DCOx5dKUoqOjRxc==yv@f4UIq5#Y7z0dzlXV=@)K^OOgnq3l4_i8BgD>X>R2!p=@gS^)SZimp{DZBLkfJ zxGSl2s47IOy3f{c04nkmK8BiSH^wuyE(I#o6lDALE|(?KZCUNu$#%rkX>!mcyI%L@ zqxM#r`IuuKE_OL(Oy0@X)zox1>#>`{tzT~fr55!2dI>k_bBt&;o3WATR$xFO(|=>Z z#88t=z#D}jLIBb4W~F(Q{fS;`fmZr_N-IW^n1+3d57KzPKd)7Fgs!WQ9eC>_)PTXo z2$~7n52>aJg)jSR0?L#+(EMc_>!jN*-&4_lsywz{421=V|<*oh!nI2kId@l^vrd94*>Pa4Z}$f1(4b z6&sXoX7!bMWltyRgocBtySItDkrhfPo(z81G1Z*JejT6{S+HFsKpBcTsl&}BlQuDF zz3$IiS@X-cUJApK+JI^%B=Fb3p5Y>12H*|NW6S}e>Y^~pGGSHNR<+*$|G3mMMwbYRZ3{mRiyWpP?ZizkP;w}aCg-Az3=z@ z2X~D73j;ZhoSbv^*=w!2=9~-hItx)n)7?DESjnaquF<<~9Q|@c;1XPosHkvisx-)4 z&bse?dgKL*!5qW)P0oH-Y%-AHb%PNt_SfjEj|)G(*JR3hRHk)QKn2)p+StV#^=y87 zTfzGLs-StZtx83x*Y4HlOpi*~EGIfkty;S-i|4*oR-jGXQUqKEpgO0t8qfb;=w=tV zm`;?OG|sqn;ho?#hGO$kvERsc<&1vB*2)!zt);69n;Y|$Rc$HO?kRLT#*Bo0u`z&q zB#56sQX_c-YBeNW_(G3=-DE-4fA=K7cGdqHx{5upsu6@dyNetg$%%oLu4g_^>x+rxh?uPlGI8j>f7HG) zTw87H6dS#-)q3&V)z)!nO@l42%KUuke$T>UWGPSc}lS0tk zYwIcsExt&)@38|2j@6FOn}mSo0nF%(Xb^|A*Tx+LTHecHxfOLgi9+aC+gk5a#F zH#z^>Zi2h&ua`GzU>9+F|ptE;#?HcX< z)!S4ew}8ze-soxwL}T|<1WKNhMf^QIBE*NieL5+hv!XQSa$Dd9x!}~W3 zRu9w#-RnGTrY*=n3~od8<05HGZ>_JKnr3F%dY&p@5l;xHl)}+@IN2xd2NDbrmZJd0 zd-z@%5zbzO;N6_PWu1(&-TZd@dKW+QCL0M=+4KV&(_#$dt&KZBua(;_;8{R2Ma$h5 z5Dehf4$t03!l#%1ePr{j@UlqGN57C4Pnv%&7zDCHlb=5&2fQ;@j3uNQfIG5K`qZ@{pTvNQSwFP$v$^8=Q@n0rsDTl};vZ?J^kibkG)46>PQvST{N~ zuuS{ja0)|UhU)n7=Cn3njZ#bR66vsqhBpFAj>FEz#8x`(JY+slHEE_f{54|l?zDaSM#(Gdmka2bpTDM=uDi(NRJH=E>om2u{r8P^yWeyq)=GpZ!`agbG{`{sz5 zaeB;?#KbTN_90CdUxR{A*-P@_cpck~y!_3>pKNObDPG4pm38#LL}uiMWIS@~AIrQa zmHg#PA|dMbret=?MsF{F_9EpjyYV!j6&}`l6KpKIO!^ zy0R2e?N{)x3)Ox?k_z8c`e){`J4!#xZ!a0mYv)<9i%BaSo=9rH&ob*NXs{>S@Qbyv9Z12~%8$>*T)F1=s@5O=Yb*jb zn~YAi%W^J|A@pWyy^)_M4jlu75SwxEt(vXg@P)ynSz_q)qSJTZxop0H5ZQyvWdmj4 z2GHkd#kekLm`!$)88$G{HMcOL3>{%$Utd_G1J-u++qj$qav9wTe*E>dx$J+K_0Bm!(3bb*2xHbH zy)V}>OKx1-axwELjH@I`GdrWvl#?+{TNj}dx?*c<>(j5sJ+90Et4TPHGV%$hId-F| z(ZDB62~K=wuv|jKXr4~v{3ogF%V>Ro?{u%hfgujHDBx=3oKp*vIY^CE{;=#yg8 zgqSHdRBe-yvd-qxWTWn zHtQR~hx?Yi$U;Z4;GMc@+eyt0d*#p$=7+_Ff@fRi+G9vGg2^5drn;zis%)ByNd0le z0u_>6H^I;N1!ewh-&4BBMACJ2+7n+Kbh$&%Q8#`LPSrg47-({ME@jS4(F^*?d^_u; z-0EeKXH>kRXW<`HMEboeBs%G3g9($a?vAMe$p+dD2)~Z^Nd^bd2Kp^&_M)M|l|Y`- z-Xj>_67u|t)A`yRC1O|aGW|TjVyV9xXN}y?zh0`MnHB`5C&m zK7I$``zKpLj+eLO70&LGB1Z4HVDct{Ot1Mcr$lzrOV2-vAnDMDoO42?LuH*?emPNI zxWg5r#+|w0~t~iX1LW#ik&e;lQ57~M2h&Y2= zS(qzMaebFXY(7Zx>+E=huYTyb_fMJKaNpY-6LeDkAf<4j&0VmCi!&I1}Gk}YhYf{qPx;9d(qig6%Y zOx_)Qz2z3PnL-$CBuf{n2W$4Q=BMDDFb1(=UVzhmE#blyOxe~OP^(jK-{xC*0p>z) zFO)sGxUG+D0Q6jAzRK zS5orbqwx&`pXtn>BzSnSIjTJ7t=!dA9_3))RB!ZMS*)S3wV?+huKv8F-K*{-$(*ub zGX6u``GBrN^NfZR;xqeHZ^IfPWbAdQ@q*NMO9PoO;FFZRl5d%E6<7*a@NVg6AJNo! zcMfV05}KX%;7~`~!k&eo|L9<;Ka->+fk-^2?JZKE(wnA8vT7|ue}~2$oE!EdvG@kB z&YLtedN1L=`pi2%*{SlvwJY^rzjN$59B(U9>$Z&u`1X zYH=MJvqyeE^jA&2;;P|k98ayER(m= zRt0my&R1A$UbKtfW6_v6hvw)MRXTjtAA}UFSx;rl9$R$_{=vPyJlP7_&Ob}*f5MQb z;T_24`cI))2f3F>rK*Hq+5=8dfur=xFBg_27xz}qFhZWLr;T*6es^fV`%WPq^J=Ey zM!kKsGo0A(T^>amz}fiwI8gorhH9P#__6Xj-ZhhIhrHLPAwsDaB_!X?M9HyW^PZFt zu|(YGa2~%gGTGbCUAZeHak_aSIG>qchf6K!aLpdFSt%`^C15WNZwATE90M{|7i!xc zeOXBq6yx~FlPx_Z=z9R37tCUGiD`Y)k52N^MFHw${|R@_822i zd-8`ULQ#)>qNJp!QUm)V_OeTY4=iNiTYF`6^3OaclPwV`(%r6413Hg5!OrcM!P!uk ze69v_Tptap@=^G>RiyqiKcjg|_tLQ~y|ATkdGs9uTK?1a50|HkVp4B7b?TwL`;Wo8 zq12TT{w)@2n1o`G zv@<;Aqre`+8XD6$(zMS~^7$uCYsFi*S?TyAZm;a<0!_oz6;wbn8mf0Lcj-zEx?#js zIPB}?PL~%cBNvUMLurW?etmR`f}2__I|}x5v-|rwaa%!Yb#mmc&61p8$dxJ$+%=5z zB;#2Ln|~~`&Kf(lM$;U$!vMY2tXOmiTEBoZ(DgU14EL|SVx!iNY>ZqO82*qcOxbU- zfcCvJPQ@8p3HIjwdD#i~a7TGMuF2BD25D(!K;S2RXoBpuYu_KN%yp;@dw=N;akM>H zCEuJ*RS=^t$UNdSE+KscnKEDNc%Hh!E8N^sRfv&K2SWGQRgnFz4y5FQy+JVTO6N4j zfbN7~pFaGTj#O%Bw)EY2aI;KG1RA|dpuv_r!CTGQWE4GmNH(}fGx!ueyCe-04sP=~ zh1ofa*9EdV^q%ZCU@KxcUXOFT8h0m+V*Br}<@1ClIrlKMqYlrc{;(@~NHL!NkE* zW8&&GnIH@KC$BLn)(@!~A!=Ol=H|xT!>Y+i-)R`ym$65GL4Z!?85!npZ@TyOA=po} zE8)Sbw|s-0b)IYqFbz6#a&zywBpYC7`mbLbKX|SY2$^rW<)cAVtQ^JXby%(rS?UI> zQqiqo_&Y(`Nz!NN=u5|YlO`Ni?kYZd@ZiCZ;OtmAO*MFdk;S-&+a-)5-}c+B@{baM zyYBnlZb3isi<~ui%JyA}R>6SPuGx$hPL9Tc4ZSir^&sb6uvQEreDu#e@h@BZ))kEW z|MX{wQTs6tEo{*bCynrZ_)*8JrJ3W!(#fgME>E&bN?U*oux98Ry6)ponN}%n)2cqr z=PNJHXut=F$4&AT>g5>8o>l38)O}juwcyU2J?hPew6I|gWV%C$#?aZ1`;-y?v-L3@%1py3G{H}J1?m1a~h&f>bB`uT4bJ}b0o zY8)rzZSTdKh0?AZ6@HCM`}W;%NLhc*4<&{1@3_U&_Et%qmC??%#B2P_+Ji?bf}IK1 zuK9A@mNl1J%6<^z*&kD@u9@el3vB@ecb;R*jaR~t0v*sAg46J0{Y6Y%+Rf3Jws{}J z2sbCmNhj}YX+~a{GfGu{A*Q!sCFc=STd&KttxeCu&aL!{;`E_EfqzRbmI)fZm;TI0 z1s_vVPIn?#E71g6!sYVu)s^wcg$@I8Wkwaf)H(9Dh4MM4)z;U&X0S38CCX#TXFhQAcHgs($oQLm5|YE>GQBS*LL7r6D7aL;fnJ&Mj%o1muv)@jqSw z$oB0E-=WxAS6m+4um->{STN&H({NrIWaF3qX5*PGZFxhcp-~fFkE5I%E>&*@L zLc<_&-D0sWNpvDC{5r^NY8ln`gMe$FwdqgrBTgC7tMXinwb5y1+^I5v?8q9zVkysv z8&}pTmMuV*48Ii9HVU;rWd{7l%SqEJR`rB*=w8Qyg^?m%zcV^_eaB|Zkfds>s&g7( z9K3T!SGNq5x6oA`fVF;~iuH_HcNcVC#3eJ>$40I!Z@y0a#Ozx4}+GG(=;ZkY&qUOm2ga zbuaYQT{!q)NJuh%^Ezn+t0ZXmG; z8|pq@WK=(QyW4m!j(cmhy}7R_mk-ao>Z`5c@b12vp16bX z3$uAt0D>^6YLg<*CwC)TKmv_&G;sA*XA&yuI>O58t|&RBczl&wDq5}00eF+aZ~DEc zbeQVuIoxn)^dCsU-F};5qN0|><1=Y{=TQD&GdLgW$NTR*Sd6g79Fw_t_IvPd;Ma&C!0rp}#bDJQT4Jy|#n7;Kbjqg<#cr%7x}RAt zxxfWO3DFP4ow&ATj5vL0;_nnws!nB=X=WGm&Um5pLbwa`aLUS?SRm2y3=Bd;`@xW4 z#+x)$!dGc9WrKbtC$kzwXSjmCK&N{2 zTwj|>?X>4CQ*{@V8YXK!a`TXsF>TqNv08>llI192vwwB2DQKa#YX_8Y)7Z1qySHn; zCjWqrQ=bQzoY&cW9~~j@;VB_e*D~O-*-gG(p60G6^US6+Ze^M2CLK$zD2v+uV2nJ_ zrl>tn8PCtm3GwksVwG52XT_|pcEpLm^K~oh(#-;}mE@OA>uDt*FdowW35`XJvTOo=OivGL(%ABVU0HmpxBi&3>aE-_^9k(kqWLn-(>eUGQe) z*9q1e)UZ9dZOU~DnX$am66>F|&3P3#HH$Ys3{4?oM9Kvj^_M4NlruYaKUQFw>F*NM zT2U7^)5y37NM%%pz{lWy%yhPq(2TNjYMgDQy3vICHSjJqa}9UhUMDIPm;8`;kT1xQ zC1Im)umyh_wO`XW3LuGOB2_vlmQ#bY*9+I2!S@Jx)6iDVrKpqP&0MBisx4UC=+Sk( zZTD3|5`@8El4c-i%QO3a{A^k@AuqyMYW|)oS&r2wQ0)j6EjyGidzv>>jZgX2N$=y| z^=7{1jAE=y+`gCl5S#>#y4oeYaY}>R&JApfiOzytA<#a!jsPptSUhH|P&@9UFdOHK z)sq#>$&*ULXs$JHP<+mZwrrq<*n zx(HyeHPbJ-!q;1#a0T{ds6`2{IxxpC59aL4I~i^688hyetQ4Rvu|~$$kI{Sigm!sa z_FM%@Fv0bnGkQSfM@+ec-&V*TVm;ZDZ2CjnqnB(dp*B2eTy9UhQU!(Y2h@pGsK<-# z1RJg5FVUe#N2ZT^KPi?T&&hUsAnuRa8;;pGfMyX3;KZ$VW7!&WgA&>5t}x!Gh=iwna-obGXUNrIHvLTRs?45{&{Ag?sjR-V4a{-lE|pD4gG zaqv&=ld&9MHrcmc*rS4mH`rO&p-3%SClAkZnQ%s@jai2Xr;O3ks?^SwUG z)1YW@J4!v?n8TM=(-}Fm@4o`|w6ND;vd9r=={XKXexp{e^Y0bFkGI@hbRRxfWPj|G z&7HNes&8$@?ZN}m4U#7T@36w$2j|$G%v~pRegPBP+fdqT-?Po$ zz87$|;V6O~ylCIW{#?)6i>qo#2`W-OylOunKsS_BZ$7?gB}Y9@E7jf1bFHxIdFLgZ z8>{C|6+H~IZ#u4|aX~b5TJNq=l;@up_7R4ea-BV~(6CdYD;IS%spvTGCqJ;$TZkXe z;7Xa`Am{Paj8hkC)Lj{Ayz`!CsL>&XfqkiPYpY~I{eHZQ=anm?n`fwKR~kcH-5ajs zSyE~%zML#E$1*(f9y#+2J5g4-jVX@dDTSB7&O?!&89dR{mlK-SYAD5LOh@-*N{wdJ zLigG;T~*Q$OVaAow;(5wy7DJ2lFG&(RdR+gFX6GHvWNBN4|)%$io1Ke8_pzzP%~SA ztGd!FRQ^?Db%#{+!ozlHM=DmNeev%Dbo~w5*{l57j2vjGSCBXN)(XfmD96DLA1tQx z*qA-^((YW~E%54Gqpncho>w0_+HQFIXkt)smodj(_DnT% z+A}Yqj>buy$))Ydb)lyK6w6mCO6w4TdhTz<>$w+cU}$1u$Ahk_%($4a5%C*=cz5#8 zDUx4P&PX|f0_6<2Xm^#r|7Q7p2ByDfVE=RFzt=DL!F>M@L`3KFM9v)S&Hwp3_$~DI zHTFUL+vbb!_-;ql{`s)qXZZbtGZEUwN=MDay!ON6-v?h?P`3E+zgztOekNFzg5rOk z8|T>9c`xwVQ6j>Bew?X?-fx7^NBvo6l&krFPspe9i2AxLCnLXLX;kO(#s7Oy%AazP zM^FBF5&!dXe?J)6^fy>P;!YU+v!eg|KODBGuan59u2M5SuE>r0zb6cVhBAGb(BXTB zY!Va8`Pad|rQb{E;h&83e=mY^>!>;YJe5#$GcE4_dl1?Gd($ZWThsmT6@qJ``@08G z*HwQI`#+Z-0?p(GSX0}henbTOeuGsK12{-Z?pFZL-^JMs@%3imO>x9FOl0?HnOE(@&l(AE+^+j1Icx_uo zMMaj4SYMzvU^4TYk0StQ6$68>z_EdIA3fS&nBH^6*Ov&?OBI0LHeTMVv^om>JO(JZ zhysA#3xQ^u3)NmZ1CEpfz;hC4)#w5?yJcaAq@60@s4?!hm}(DdSdEeH(L!TuU?Y;M z`0EP?a4x;6u#jlI#sJw3Wj%MJR0TdvB91n?cE*dABgk7hGB)4eF?+9I!s1xcDy1*S zxR5%83~PhlJNwFHYkj(>C*nHwHMt7wRwU131FL&o7^la(Il*sQ>tg#H&c!8N335-9 z-t*@0y1_EFO=jEY~WWeBO90=Z{WIe9dI@&(ncux0AiXAE^-HSY>xZ^xB8AWQtjUT*L%onLfOJ- zl>Y>Ve>ioHG_NEa+S+z5&R5#%?qiF#FK`dvKq3oWGA9E^Ipp5vQ8j=zj4Rlj+l>>L z8Tsj?Za~1K$+-;XlK-?DJ4LUFidJ@t)pe1{JB5&Uu@B6|FUnNbM#nPVlFiz+_ssw0ZKYq=d+c>pnp%6&ZyYLIx69+21L%x%xo@< z>4ovW4=sm&h>fx#6|2+p&@DV1A7G4_8GTWQt1X~R!kQ=in#2c-IlP|6<7U!1IZTx_-SZPDdeLgwr3xf@<}HazoG-y0GfC=;?^?x zo|)+GT#R-hFcI=uNU}%kX)DgtoNm}Ia?4uPN)&Hq5Pnu$heetCo5KTiC9t^mNL(qV>Un`P@^$@f^Gb`Z2NB=cfNo0M*Yj;_C4oT$0fIK z?bYEMR`nc=3?PMr$RIEti)5<^? zrWev>j|v0Ca7P;#1a1%)_0hoR{#)9bVT>(px%U8y$KN+3)W!?HJ7!BP$X0y1{*wDX zR*yyYYsa4D`BaNGaF-*YFqCI<^86dn{DsDd0tqR-5^?Dg?^E~h7xEC0$|`vTutCbE zDJFy6i})zqqTYWT*c3nFk@w0i4L(V^v7CQGdh5aY8NGksSTo9veFa)=zbh0rDoy*+ z$6eljLtW-slS>5!(%s5Rp|tWu4r|L#a+@cO!Q5)>=fOLB93~BqF2NiHbF;3-_n3 z_QjMuRmz1?BBG+@?TBuV(_HZ>Y58j_J$IDZVVH`I#WXB0tIoBD6<-#5EL|>Z7(PrH z5iM#Xq{4F2@~E&b7>6c3F|^j=V2$;PB3L~bl2k%N&oVE+R zK8;%K8zB;=n$eZ8)TvwA&e{m+-m^Z-W6ebTKxcmPouKr(ljVz7x3;~tQYZGXz$_kX zQ)!2lhd3x8gYjFxTB1%Y-f-4hc}Ys09GvCZ=u*G#IKWToc1(Bw_!?EDm!oBsU=TD6 zB_AI29`4E)7#5X{6jhyam|YnzDAG*Pw|g~xuppZayqhBl>G!GCdr4q{bOde0AoO#| ztCojoFwI<@*FoGDH?c+L^=GYv?pw2jgGwNjSnRidKbhuq>=BTc&@{=%1AnO$dHIM#oAbmFOlyhH*@U+89Gf& zU!Ju>m8Q`&fj>Vsz&KULeml9cxZBue^W;?@Fq9ZF`3kLT>-&#rR`KNC+UB_74>T9n z2$og`@xq&s7xhO~u({`Iy_XZW#VxCSZl88ZuF1Pe7=tZ(ct@wzpnr}{i|nDEv~vtB zrrk7X7plD)k$cO!N^rQ zcH9CZ=J{vxa^k5z@Q8BqUSXy}iw=bX$&GIc5e7n3b{+pDK!Tpps{ zHc8O3J0Sn$@shaE|->%FWM zxek+UG4`>hC9;~yQlC`m*$TziIfV^T=6Y3=$0P6v>G?f!=$p58-wy*oul|V@c_6psFF|*W;yH@GL+l*67-}U*(Y-ttSXswF!`wrXjA**)45S4|r_aPT>~M*OA8 z-r6vyXvnn)*3)z7xSdHUaI7SHkWYWaXU@qp-w8rM*Oxd$2!-o@2{p+42*lHVgyn)d zYs2b+Bm>bJa}K-nw|^b&$9O0Sr*KM|3YkSjjMsbi_13y~t{6GE>6^o*^4fTD;nZ8? zkvc>fYgX3CCsl?0XlIsku1f1#B{ZQ^fcJgzgE)H>;i0nT-hstS*v}TG?zFnTZ?97H zXLrJ>`EK((K`N5FIvZB*wVgA$;E+*<7pmMN@>H8PRwMS&u8S@9Lq?hf4*&~-I+K$x z>;5(75OupZ!0qR?+t1j%ne9=_DqzyKPXM%ar5b08OCiup?0@$COS>;-F8#ag6#N}f z8U7Pc*>k&HXlHeX+tuH>@ik*y`<7q(KA?GMsjzqhf;>kb=oQG?;|SFbxAm7O|LKEW zTbd0g<<-yA7fc2247w+inF17#=jZsS_IojPoO*Zl%#uHR^SX4%Mo-*yBM_CKg`^5mI&$4KU73rko3VaTO0#f$}wISHidXV;`z?ed!{!E7t7AE;}*DaTmFEb_YWE47u;X3)XphcmGaf+Q;dcprBqQ?~f&x zlQIJ1K@NvlOqPU|VD5!jrTT!e@2zZ%ZZP2C@3RyBb3mDvc-p|UatK!LYMx*8!0^4K zc>ue*H~Pa|Z+ei7g73;qu?v-hz9-Ek+)za5Wz#O-jskIpQYUvXOrLAZgK z78!Q@=@m#9IC1!Wcgucg=M7rVHeT1XB;-itbK#^=+IzupH4EOyZ^Dmo&IgZ3MUXBx)DN$Mw5KmH{yMv&>>C86)qZRaTt1(05wte^*tJ@tY`@Z-S|FTz^|l>ZB`{K0mRO~26+ z-nc&nz&q7Pdzp|=-Z5>9xm;DXUyCmll3q5xK?_bp!x#{WGl&;P=ylHquUN=!kES~` z;%#qkj-l`)c@w|lUIZ5gcvz~@=(WAR`31O!+6wh?WU4nhN9JZejCkYG{aUA_rFcH9Z#eUgMIeHT4SIt9 z(atO$ZAZQh5<8+2et1C;>a(MmOl;^p`bNip_j<49fS3z!0+rRe63qeMGGM-98K!D| z#(T7s7Q`Esrh|W%y{xhmI*#6SRAB5LpJ>tQ@WyR*yQ?c5w!?%&P9 z^vIBu%Wz;s+3$j#l~-xv+uM?ZMb|I?9M6`bc#l?+4i+KWc$H=bfwZR?2qQBV@2TW~ z1Bz-z@0?)nY{j6Kr0t{JUfWrL#){!6fsqv<6z=9w?XhZMCj>g9N7=|wQ8+= zxxBua&i?#Q$r1f3#h%3-b#F{HhOBUfw0|4x!}xJvQRgHrk3y^spK=*&4Hwk5yrb)& z$2F7XBE#%Hh|dM)FzA%$Bz;1q7`kTe6NUFw?_5$pLIw>-+4`5+HoE&+uS7xoZnPwS zJL~q*GDl>Cnu_+!a|%RCcPw!)_+a{*zc!z8=B~`F>c3(LXD+2QUbuAP53J__I35-B zAciDO@gbmLbI8{NQ6idE>K;uwWdg$pKFP*YANKm#1yh{i&jP;{QL3R;Vx%B zK48KKL6vFr&`QQ$YYCQzP07`VQcWcSHjsn4%^?X{q;GtHgt4}eKos>6*E-)a_RxNw zfLi6IOC4;~Q-@2ND4TKSMn{S8kdsSSu#Nb@mXgk+A$>7T<%?ovBzo-1sK6o9{@P3$ zRO#o(OVI^uLfkItH9gXT`62ILig_O_N-h$W%geRSCV9Tu^-%D1liDqIq}KP}UaqmRhIhi5*)cXgy2)X0fxhR|>ViMYMF3WkiTBD$Lz+jkd%s6?WByXe8V7oAlM z%eBvauJzl73Y(z*z}4Z8MTrC&JZe(hnXu+Ia}S;L=oIA|5uw|SzO3N_2$MV0F|+L! zbSIZS*ZE*gtWt;-NSPdIMnr-9;8{u)uro6#ma9gC>0tLLPSH}mytg@EFOYEh(O7)f zk=Z~M%yG;@;0*e$ky%QHN90*E{ExIEdy zG-hdARa>i64R%J!&He-n_qA;*t@h9-Fg;^qd|JcdknO3Z z5pM-?fj=p=LHw(75RS90OQzlOE){w(ZB0x#yvIi2oEb7{1_;W3X#O8YcXG3?qhe|}&{4cZY>T7R1^J^15FfSd9^@O%h#_IH;^ z>GIzyIHIWqa@3m*A3LARRa5&?4iU>u`@#&Ab_MNXAQ{KnFhm|vT zrom@fAxlM$^s!I)O#25>p=N6YL%mWnWnnLH(^t&hCrfC^M!y?nnlmHzv zJ7-^d_q=H|O{OZF$LXU!lQk1!D(X*IBc0S=c4a`R={TPqrA}In!5e6Yp0yVEJew2O z7t_r=aQ7r!hIJ#qnEvQCZAD~pXtA10k`la@_t9v`Fpvt9CNNgK$qN)`(j7PH?&j(z zKMz(xrhbFxCQ`0JIu44GuQ)SBcwRZS6P>MB>$%J*wkRJ0n0O_GBPMz>y-Ch|5Am$&1lho?qHswE}^ib<>oB z+F{X-4y4f07JaGqLgDryvV9%0lsz{K$;Mhy@JvW>t5yd6vm>a);c#5t0A|L>`F?s- z)-s|C{!HE^?I=GZfw>DEjGvT{-NeUb-5$K8Zy-=(WnSUgPFm!+`>wEL^uKTs!sB+* z<49S1s*b|808ni1{w+3lr`ZBk{#9(gxJ)TF_vZe~zh?=C@ZWj8QiLOh4~1womZkCuM(TxTWt_j@}4%n2Uuhh)Qyj~~B4bWO+i z4wmjf%76*N)a}=2Y^}e241<;p^Cw)!qkqadxbgWm;0*}<(HI(XD^+-9xBPJS5L zi(U5$Qu3Bw+8Hjdx;fjJUNO}BUa?j2ec{l2dj?h6&$sel7*6shtmaMbK$7jyGR9kS zTl^)|%pP%bGiETl6H9@yVesX$IId$Qy%`x&b8+BLdFaFHnlG(0_9(f2k+te%mTb)w zySlaL4lm>~>oGb0xRd5Dgx}uW_y=+R0tOdHH}f$@Yonm0#;zd8_6+;})J}svaPKao znERADp@7_YU%4DYTGsXfJqaTdyj$>o3VhXcdSg%;n9ehZ@eqY6mgcbLFuHk^Zag*o z#kyZd(FDEQ3Rvn5yb1!@?1Ey#8xVZQ10*!9EBe3dM~ksz-1%*TjLo5Dbw1* zLx_-IW1av@5Bt;-5)5jsW!L2Q36uI)FOY&ZP9-~8eM#S6*shlu)*O|XqEogx2}huO zXt2z=IuyMIeD^caJUvf)%hR`<<)q#tO^@1B!$qzEA69oF3FfIXxIb0081PC|*dKV= zTA9L}Wz+5vF!PK1V1xbcyMwg+QssC$(5pKtE>x`n!(0pc#ZpIHDIkeSdq+u>t8USwj`47L3z`MZ%@b7{USheEN{uLYkyLK9V9G(6qH2^>+9m%G5vJAq~ z?5_{@im>uC3Qe`{3B&5rW?=mp#t-$KEv4s`Hy64|WL*7@g#y@JNX~TJg5PJrgog@C z@g#Tu5w`EIY`J5si5aYHn$yTiPmNm=)LUO2u6fD`k#5ehzOnn zb1LmFl+NU4zA2;NWhceVmS|X{c4fdEKd;hT3k@j3K2fGp*+V`i@Tv#tGe71{qRgGP zW7xJH1(@3%*0Udamv@C&q`X7XF)bo+Kw)B2M2$UcKsMso!&BnbEY&tLC-0 zUPmr}IRBQ?)0H!A6>T*j1WtqE{7U`y`}&<(`}wkd2g~;8gTM>#preb^z8|x3eHHXI z5_3yCiDBy-LX?vH?P-p?U^Y89hGIxR$SK)TmXT2??9>Q|j872l^TFiB;5D}3-Ec}z z#0S^~^Rs<*27xhz5*W=Sm(_(CjT$4iEvW3W#8}1(Yc5;Z_mT|`6(^1`?ftvM$q1;# z6zWODfACp$!M(+HLsX!}8J!IKtQV*l*!ymual@JH8~eDGiu5 z!11|OXkySd`^HFC(p#Y{G0Ctr7g0|=12eCFHPD^p5}gX%)C6{_Lp#r@8Hii==u*u5 zm$L|fDGS=At9G7?J=>$QelC+p91y?v9&x8w+q{;YN;ET{-3Bu*ihS`?K{fQvQm5jL zDOE!qu)iVwI4x;6rlnx;AyO4_&zQp^nB-meBU0p`DOsk^2W_!<@Y*e~75@|T2MObh z=RtQ_VLn#xpbSRpU6U0n9q^tnzcRG-A=1>VJdI)EOl69Ar811+#1el#X5kq@b+B5{ zLC~~6hDh{tz-8Zd#Dy^^`JSeZm9V7QuvFY1W1h|#C%ktyc1bCBouseZ>0flgqPLfq zt@7n>dmzcXnQXs8joOJ$QNvdXY`{)d9&wa505{SWFJ|djZq64@&EBJg&7E`2pFA(n zTT+(Cnm_o>kvZb}&ntVLH|MKci!?5B+`jQEXHtrlxlad>*Zg^cc!f@BQ3+QXIMt{ccjA z($*6IDxC?Et_IPym3VAs@PEq#z^#$8`Q0X?`EP-+aVPlk>Xo;>x+1RLQRa6Z?sEk5 zRO*^DoVckl%ep_II9}qh@hM_2$09~xw>|cBcC!ap7Kf3^lQ{dd;7Pl#AshQvhDmrA{hI~Ou=q=9}TMs4{Z4rQV}!gj826!NlQ+h4_UoVL~%YtwNN zfUBj3hIDb_*LHLC?9lKLR&ev3^iDurd^A!xv_0hC-44naeKJt85TUe( zcAJnt;>m2`zF4|;i2#BNMp=p^`;IfA0#wHvO<~tBp3Q9~sp*EO8@rz`Tzn^w< z+^e`l_+8P#e*~5lZ^0~&HrxKY*uxK=J--k?fqT&>;QHPfG+0`gzeYd)MmM4JWYC6& zY5mj3MdvfT7t=?)n+$aK3p=4<0LmfOq^+wvp`%=qbh7IR4u#GM`p3>ne5c>SV}lH3 z#$Y>des#v~SuZJbNu~?-J^G}PRIvFa;z=xG@73h%5DPmSPG7x)@0kFVA45NXvoqY(X z%Aqd={^oVQq`h1Jr_?<{&1y>Fhg|y05BYxKH-+bG;;P3`r0JyV)-Z*yqkDGPo39yA zm?t@iy(#p0((7L9Gm1s{9)(1D@9aRr^ZJDWO=okKoo9Gpe7C&1MB@+{w$IChA9d6* zO=6Z3FAh~;-4)WTRA1D>PKM|>m0Ii{;9Gn5mKmjHG6n8XlxS>Z2jt>&qp447Q3-ok z!gxU=>y&_WF84yu2y>%mW9k94Hv4MdOln$(k#0PV;{0I`gWlS9735bZaSJ!gfRVDV zPMaI%Ge7lg5IL(vv%l{jN74h!-G9YUdpiG|;^R`5+$9|ANih>A>u=f{+G5V;c6`m9 zuI|57eaXU?j!pJ5nC#9_C(y$uiLA>r)aGvkJApNZ8|X7M;tCLc3rXa5QtL5=E-At7 zMabbeU|<~X0!-OAm9&)u5v{_2rvC(GJW}KR(+r%9$c-i%w!|{_Tn9^lV6K<6LeO|H zF&Kx)9)?Z=_R^Y>uX!O;FW7i-tCtV`0Mriy z(vr=nsi!|#54~I;@=_mF@u9U9TN*FV;YD_yTw+II(3VDGPe)E_?^zd}M|mEK6vC?B z|99m(u^g^u-!ZOqdVP4+iG|>fjp#VK6I)BaI{Zy=zx}yAPfU-}yARAZvZFq^ubmCe zTska%x3e;QH{FNMa9ervS0xf%GxN9ZP_+Yy|hwrSDA}xT3?}i_P3`e7hAi zb?{Yb9oG8dL8G5X-5gmsz#M}$yP*ZB3CTD$DvOT9j4q*c0M_=Hpj?)xg`2=McZ-u@ zRr$;n%$Q9sKo+(9Ll%7=T)#*AuNUIA#_tzG^)Ibo6@X~6xjhy1@?UE~_HbPSu{Bg? zBP8s!vWRiT*mVy6G%1N4*H+qhs?ASB4G)&2J3#SY`f-j+Uj`A*BgLD|v{pKIyt(v| zR0tg@cHeLJE)CFxo;ejTmzU6iSFld8VJ5J;zT3qywCxG(v?_Uvby%>gv&fEpw4O^A zsS~4SYDg^a1Jih>G#9zn!tO}C(Mo$w6u0w6zWF?O-~o9UVZyhfSG2 z$QD8(%QBP$yX#ZC43V{9*8L|6OF)Sz$R!nBQ~$u_Esw&8&sh4w=Q@fo8{rS#mfqd2 zEP;#GFN0*3o1*XNo_kU!MIKFzl;dYp9)m#vhmR|fjFzB|R8P-<*rE$odOL$)1G$d2*05E zVi#q&3VgGD8qLeZez%JLGH7SbgO!f|3oiszCBSFB%l-%W-T=+hLfYZ>+ep2_dwk79 zz4n;h|A)Qz42QG*`bHBWQKEz(L6i_8f`lN579kSRqxa}N(MA^|NC*bednbDDGZ9Jj z-VH`?gVD>3vaiW~KhGob?)SsqAKtx>uuG%kfch_R-0_L8Oh!Y@<6rHY7BG0>zFNZCtxhy{353U z$rp>7N_eJ%g0M%+WR_2ZaV)I(hse955Ka)BHE3n6qM2(MXj_qZ8R$6f(!WrftrQ`J z9TnqP5!OUnJd-xAunsIY2IxA!*PGpcOwmPMot?rPr0j%jMRW|z(CoOG9wFy1KdUH6 ziUG2YzpK2uao(LoKgZ~bZp6@P=+utWdXCBsLt@u;du1@?G1GgYK>dTG3y|h6;ShET%b|%oqOop5VjKuFCj}d8$KLM0}yo) zSLl_GdzAY$#V6@o12B)Mzwz>zyzeQNDYgbo*(0rE-&bwCB!(I7_GtJ-!B%Tc(%Dup zOuMEoflox0Q7U0xizhN)2T&1T=hSgh516WfSB#l^%!-iWIJeRPnFCwylrb<3}5B(hu!Hso>HJX4AQ`o z-+n{`r(eXl->D3iO^U`5%<7CWDuZemWZDK&{#O~;D(-%5K0h|Asg_|Lt!WP7% zxGJ0jOFm((d4d>r>g}?yykTN|2-FZ7QtNxXt5IQRXD>3>&TIJ@TyIG{*P;W-+tBwY~E$ z=CeaYo2{)5YOT4~R)}n2M%9PPGHG)3p>Hb0^5k#9Ys&j_cUo)Yd98=*T}v2ta;>KX zYp{gC_{(^a5-GvLA<8~T_Q|hpK!v$nZf}M6V0WTY%D|w$A#ymnR-%5$m2^(kiKL=N z-lBuL_Hd9-e59h?*%eP#emEH>)g{5x0 zmiw{V)$haFdDSy63=+|LTIrtF!NHR7RHL8ef;9KlFsW(Dw}`10?-8yjUHBfyhxGXBUBUD+ zRbLg5fiH*8Yz8brSMdZK*GEK;pLwY^w^qty;$Uw-kq-2E@m%^?YNIk?GH4OHEvRM# z5SCtDF-vg#K-$ydOu{j-LtWby&u?2w!qxsP;4@>GHGHltAHZxLA=;{m*oca=@=b#k z71PMCU9nC;5uU?8$%ujRc#(6S24gYb?}YQ>zcmOS$*?>@CcJCUAc}w?ThYMQ5c!cm zQ*8dQ3jKz=zjle6Z0Sbuzs)p)7vNyh zz&|Smdc=R1r!vI;%Wq{*u^>@{9dUDLi*grnVtwfX(wY`6k|$h6=-1c?ArBrMZB2-B)W z#yzT-SYh~R&!RQ^+?^8cXRsEcxx_rH1pVCC&UrAPm# zYRJ?IaLKg<1&o&M^t)zE%+jOTi$b^!`!k>8$1^Ib_>6dYL!0wl85>!tWfW_BO}jWZ zo5#yeNe=1b-Od>Uz_d5x!~&1jVe|neK=h!BW;uSWpQ{xl%Ylkp!^9BGgNzXIfRQ;~ z@-I;};$T5s^0^>+kw3G;7jY}2#L@oWNfPs`??#3(!o+bBnT}5ioDv_CoY(Gy*FLW8 zFS>u$B4D}80iVMmpsIrtnY!;Fr~8;~lgu9?%2NKa2>1iF@3Yts%vW?^K%+Is%Ct0A zFUw1vR%CALv7QHHOTakKKXyKSI=>*hHQ#0c&X8^a7F4sjy||;GE-puKGF+I zPKUnPmk7#%IKM01)8izS_0yHgYhXLWOS5oiZoj{8w`l=GdM5tS5IMCDq7_>dbF< zwgJkl?(!A*w7(=XmStTy9HIR5ySzGLqfjI-+B8EPgB<3?GpM}^OMHMb9?xWpEBnKumKcBYK%V4bbWLy z6PV>+ zZ*vn|)f6yl zx)xgtA`zP_5>)5uGEiB`^H6M2e<4dT2{tHF|ahyg_-Mj2xZ^@+GQm@a25Yi}`f`hp} zitD%YN7XQbfv?)P8!>ml|Gv=AY$8#J{NZ-~^ptVjj=n_>z}&(J?rp=fNoPip)psJtn}*8#2XlUY}{dFyPq3Z3i zv!@vJFMP(0FC)tU6MPlAQ`P-dy^QMI{`*KXLr8A4?0q_ZX>v!#H&__6rcoguZP*Py0w%{`MHOj%v=_47{{BO4hyK4}w`3rHQyWiaC(X@T*dNu8JU z6g19y*3)|sgKhN&6;|-uGNwrXZ)@JN4Mn{;+7f4ZTM;ZGBd&aqn`vG~|bpb)G+xWvmiTbk$p{@mk!|I=Is2bcU& zMqaDg`2zwh&tDHn@dw7@LEbwC@YRE@fA@;|Z}*O|#~ioPNvml^ydPB*LIXd0v4O34 zB<+J9Kq2n=;A-2_SX+J`j_*Eix4x;7na_llaM}v>pb&)7(URvMVeeA_M->5n50&DSw@@irwZ?;E^`HJHR1T-$B#S>W#7k~uVqYmzPf>zo( zKfG`HTc!BCx4ri&zM_YrW_a&bfl1K9CkqmLvpX{K7UD2(S{-qcPv;j$iNm+HuU=vW z`>F+G6tc;`Bk|UAKg_S^;>wxzG{|CfnoUIh+z+f2m0AnWX;L{GBDs0-k>GV(9o(&8}KdeQag=M@m6-tTvWyiOO#VUVAq zmm8^m7vZ_ycW338{@CqHJm_I^M9N=21O5Q?Jr0g&oY3$UvYpYAJU*M1t!r~(k&M5c zmt(8%^yh&=4yVrwfXD>B92q5KEOHW&6-lxqh%s@~bSd zPM1rTW0Zg{4M?8bV*@J!0G12yzr-WY2q&-Zz=awUu>iWOqL8@xygCMY4VD1s5vsl> zj^nK@;e*Q+ZjjzC^T2cOjrS`a@;Oy|IxY3DjpY6vT4ne*C30Sg{l940V?UwzR**nP4LlHV`+wVkr-EEY zaV3jChOg=e1E~8%_y=9`U!e*{#Q^NC0OS!sAOfgA>YhjXikE(q;SB%NmFGY0m40{P zI(Kva(_ZQSukDrobC7>n$^RcVJmVV?2kQfaAk>tV!z&-J7N#4>+igSwPM^6DAd`j%}(81=uu!#fGc>c9*dpJN2Z!J7(4Q=C`CH@nOitl23 zKwVd6lrTNr`9Kj;W*EQ_MLp16go)(Thd$8-{rEWTJYJICkD?t5a!1u6faW#9JIyNq zmDuw%5S8`MM*u@<;YD7D+h6%D9wB*bb{d1?`O1)m4Zq@QiXP6#mUNHtc0bWJjNtIz zGC~gI8u`uN{}ZW!u~ykSqI>u@+HQRlcf#w_e$Fsj+|1Q-?IUuF&bE>V?w7;j~2!I);Kk8_Yk@-B&E1F%<$hZkTKv zcx4H-{tYvLBi&9g=+F$EU-8)eUNqt)cB)xpLcH7=>gAC+;W{j`9LkcXAm$}@4E;(S z3;(*ls@eZ_ETcES-87x_6zICndGCQq1g25gJcoAueOAhp?pBIox;sAPJ-w@g%1Li9TZ;b~LQMs%+ z3GbG3n-u`nw`x>WXT2oxr$EX%dF1}0EZ`xNnUF+L$Q0wT_p|0N_hptf9HR5obabv$ zsiG^&%RBZMp8TNV)Y3^M`M>?FRN%8#_J>b@bqQ^MzSoJ*0`v`Rvx7WQR|CSto%%P# zhS0n4J4GU%n9}yO)BuJ~t!Qy@{{8#U&YY3Y2kb7DXm&;8k{dI%(cNc*7!WCEbw=@- zR*fGi2%~etTBS7gttMeaFt>L@PQY)O7&84K(uy`%QUozjW1z?l+o|7OZ&1nnXMdIj zp8p60#wBq<53Kge@`~DOs{DeeMny678Wtir1otux@yY z{={5dl-E{Dz@6nU1Er~Fh-GgjZbBYW@l%dz`P?3?PJuD>L@cbk*Y&zw0^D(tqFQqJ9L zoX>_{;sbws#Off-3tG3|*?H34&~2ty1QTwLt>H!0oCY{72rsTGKp4}J4(RPZBdWWK zQ}2)az@+u0qK_TGxLTkgp`DX~WJ(h|Pu(|@3fhlFl0v+~*c4{;C}(d8FIh&Z&fZDp zf;{yjjLl15xI*eGPw%?3nX@}d7|+;PX#*ceC`p&|na2lJ-np|~H;zCQok%;cjYTr8 zsjXBxA=UN;veztMorx37;a-e)g9Tra0FxC=HEp>_;1ndha&`FnD(11KTE51$G|hysUXp?!918#RkHI~uKlr7aE75TIxSKQ z&TdXI?mdYqn;$W1zpVZ|3Wl)_)^U6{*kb>dRS9BnxJ9|Owe*n3ZZe?Me()X$)DU7n z-}WLg&#JXzw=j%3^!}|U`N+}YP2#X!*M#@KdKLp@O5RAB%;iLz>~I({OS_Q_^Vzag zRai1f1zvx*KU)1Ry?$rw#!UgQry1k#nj<5&yF{L^uZ`%vjJkhQ(0SxD)bN4V(X&{g zT~5UDpwa6>M}L5q>9mfzlV4f{!`mL;J?MV2n?Yy4#MD=Wh~PQg6}SzfJ}x-f-Phk5 z*7trcKl`zXG&)+EIOzTrGobLCMN*$`U3;QR!EO-*3beaLbmk-&A#phT#DvS_EIq=5 z^FEl&-CI=wlaJyVC8UQI>ub$Fk>8oCco8w~wve67<=m|la5Z12CVYHpfHY!xjeF<& zoBXSy8={I5IG&70Cs(%TA|DpD0jV?yAHtiVrZPf7v^BSEI8uwxiq$%Fq~0~C{^Zy7 zY^dH!Z5^SJM$ti945}azr_rYbPHy-Sk|D z3GzazxrcJB2`u_vzih$1SMPfLWr%@c!4mZGj$p3x{P!tVkS49-dP9-J62C*{iF}e1 zjR1*oes#?l0p7D@3`hF&wr@TP?af3~=(ex=#AYs^l;j_OPgv;iVq0ji^*EN3e_#aF z)PZVMJ|hv?QA7w)oy7`_e0bJ0*ZbIIQb1O}g!|`!lF!ez?^-VtkUaC0N2by63=8xc z$r01)aA;LcAOsE@X0I@~FnnZe1enyBCV9fQNmCk7Bwm&cyQ7T??Z7;xo8xm_-3fx) zT2(gG1RViX_G&A9pJ@a;h!5gTz-uI9QCl7T3T?!4aldR}u7*ow0gX8c@sK=$y{v1d5=B_XNEE5xfPe`&A@cyV$%sV*Uj`y}k50tq2i zWReK|7uyMjy#mzsL3-cZFQg~3-cLe-II0=5vr9G6T~buf0#HiB{=ECfY*;Pa=}N(Z z-%BWZpOlE4MP-zibWODyO!}!#n6z1+j{p088jv2XIIEn8Dv976M5e|7?(Lp5DCSrqCnebXfM2NHT!7hik7Z$0MZ3V*~yjj62pa5!~f_ zG}W{|1zoT&?xWdzpocJcfKYz0zrTQj6{Wv&N80EsHo;B3R$O5MX8yeO;)V_tPkKS` zX|Hb?i2Rq^We{oJ+2E0bCv{msF}Qw#lxN%Wd6Aw{8q!!P{8f4rI?IzQjpfa0H3j z+hr5#Ad*WPlkN<-0(CF!J+~3@;7B^V1~1D@Esg=8gU^!{4=4Bfwg_8Nc?nw2$H(K_ z+y{Xo+dJaD)0E(Ts|dYlVR*%U!O$c{2cbEzBktBcmlLL5r%Uq*E-a-_tYf|>=p{d5 z+VYniX>!?iv82yyzF4NC(e$P2I82YUZi30Jox$UQeqr4-t6lHDYwI0V0ZoQ zGTvjX_3FYR}_TkrJomv169lVgjNP4ok{2~p5qopQOk5@#;m-c2OKkY>R;?Bu~Y*r&EL*#Hq#R%`7cTCZgW@vs5&WhwlSGX$@WBoCBOhjzvbr1hP3`o-JXC2 z^pqarAX#W_EoW__*4a6rafknhm24k>IKu0ca{<*S>|Z(kL2zZyKs#;{hP12J1P~=d z!p>vLdtXRxF7=n1VnVo@g+UYRa+5veYr^Af00(G8tu7gj8Ae12E?1b>MGIQgMMD!B zKm1P?M%>VK-Y z@+H0z`8-^ON`6~g-cL{Og;@hxfQChQ%+}q*tTs(M>^am5!yCIct~N4V>-cr?R_RRI zJ=OH@1UB#^h4O2%0mMB#$(+YJg>}$RsQO*u08)2R9#+$Qhhf4Z=U(-}!-nhkG-RSY z4^1*;n?)6NLM=TsN?m;D-W^O&-l<6zDohzAOK(0pDpO$bJ~@Kg|0$;{gd>mcX1GD7 zEX*_-g@zw}Tv4^{vznb7cjyWk|KTD5?#Ss*bTu_`Ej^_Ob6cx-WvHDvyyE`4rz&d~ z@BMKi;3(|6v{r_FXoxY`lOY=l`c|>K@)GsjUD{3Mb$_os_tkyS`byoG0EQLTs>=GG zx&m+JWcxCazR)$afv)>x``VL)VGGROntb<_VQD{d=&7x0h6ol=1O)Y5LE{loIfho4 z_h$FaEto3pZU)e=u2iC`{m74)m%d7X7dma7>(&K8$6G-^l`~|nIYbKo$h_&+8?8c* znvkW@9sZ%-b(K74_D-~FG=T4ezx2A*lSF9jmdY|Cz0k{MHEVlArE_JOVNQ)`FAeSR z(aAK)SC;N_BO71F`U5IuBRN3%`KP<;u}fEPjv~XFZzD2!8}|~25iz$5;0FOy15>}+ z)BW3Xvy)~jbuEfMUAiJdvHLwRDVjuOM$T}t5Wcf-KjB22`MNc{)Os}9e&!S9L=y8N zbRRlCk`Y@~hdG=f>aM*==`g>f{wr`&#UXGw{exzR>lrOus{9+`B?;b>F}P$D#pjDF z?7Rx;?|R&>-aBw*rh#GEVtuB|DiayVQ4|%KrzTZ7;jAs|S`42II2@b(CVKO0fmmbZZIU2Z<%GaR%}%rwP%J23^muUo%L-&SzJGIK0p3^CDF5EGAl z(;0wAP?)2nYpJ6NuabRB_tM5C$4iP+KX%zpF6<_+*-v8ft4_7;?m5r75nkJ3G0Z0I zQJV$*e#KSDhAM&Y^uMgWd+p^fL%FyraC8nkwmq7M0@nhz7tsEkJqVx6bRE+4a;LC` ztHP=M;dhd2f@v3g%EL^*SC=SFOgD%e-?DH;Lg`r@85~@EiXDb|B#d+y<=Uf*AeMZV zZb9pdDQuV*m$IjS#P86w-SSSWTJqwza*Hs(;74%QneKc3ElYxF&=;3RXjsT)u)Sz! zLfkV)(0xeQzNPU>9dZ_rfW#5Ne>=beI2uz)v*kTGRxXwwrc8h&qKE+F9#!|8Qot9t zas65-uG>TW2@(uIvP)#Tl)CDxqO>^v^p7yBv;*JSF zEuOeL;%le@4~O1Op(m!Dn8MuSl}X`d9{B1RY=?m~`exWB=6NC=CERuEH`3ZYke$&~ z-^aqs13qrehlZ}Eb7$(j8yr+>B(~}94LDuMV7f?56w|*_1Pd&$d1N!GY}%DzW9#g` z_DDagH(02Ce$WZ|+|S3f%SBs0-vwOfJyK&O^GtsOKOXSXIkOYgT8E=RSdUmA(d_xt zcQI$0WGxkZW`})NxeQcLRW(##+!yAt65!%>VzC4<^)@<(S4&}fF7K+J9P~gTKF+BE zyPd76CQWLVG};_Sja74(|tyg%NYgj86M*a;p)$#2BmKbvL~Um?J% zP)Ue5O0k%$5E(b_(y;T+Eu)`Z4>ARG!~pM_?0-n`Ub-|;I=?4+cX!C5I{@upFJETb z9hM~G?jBF>1?7L2f1RVUN|*8AoA7iO0U@AwJL9Wb2-wig$qbK*VUKe3xp(lBg(aU@ z()tT>o?2S4Oc@rE#;d2FT)Hf^`%S=h)x2gYjc8mKfYW+#@sWqVYb08x^IP0=DZYdO zl=}rlwU!WrqiXfJO;Jyi9u;3^lU<)3cL&pF;H!oWk3C9uC^VsOOvV`{U?-OnkqkEk zZHtNTlujdJ4eI>%!bfWQJ=cc}w8MwxDV|6dtIHFA|3Dn{(E328%1qwjG*gzU#^>g( z+Vq(h*|G6IR;Bu?8Z~>8p6)_pB9f|-VDgO)>H&TX-9ZO&7}sr5VeZ@*Nvjp7`xuWG zEIC{IS#tKkAG-gXP_W_ct7K+9tNrTU%QYYtwD8GUQcXnP-@>f8Eca}BA@qdk_46%$ zwnaiWXLi<{J!M57TbQ_H_M4n2XDb&>6fJAGj%oXh>L%7G)H6z??RZ4Q$6>$(C0(sY zqIRNc5QFa@hUW_RP6D>{jKnoeI%u=Glps@|+ZGQd(Zhk0qh>$p({A6W-hi^*mq`Ig zUaYv;27Zr*TwKt?JqTZcSl}|>Hk`3K`PLF=r!GV}P_Oq6VOAU_A;6{e0I^2+V0D}? zBQ;oIGix!)Tf%K;94@mEiE*3fVSk+isXORtYA{|RYO0r82XP)O`N~9xg%NlB0Uuuy zVP#4dBJR5|j2IaZP-~d{5!R#+SsCOGrDb{Cvs*I-UtS31&{*Vm52h9H0+++gP?81? z$r{@W@vDH+D%pGC+(6CJ<4m+>iAX5lhuP1E@Tp5J2-uCT(rzgVbhvw0(z#oY%G^xs z#?^T>BnFi#NBPNqr0UIO6ix^6{#7#cHWIMHtK>vA8AY< z>ctPFDTr=1_@O*Qz1|hCNj5Ri;1I|+8u*U}eb7`35HMd%NEUPjGzj8FeZY?4Mas3t z?T2R7R};aDww3T$gk4v_?xQ!*SE-VrD`Xi9*Z1I$s(7(8lm6X0ap!AT%m_@}CLmvm z0V^C~79?&nu2pufmQLnFuF~z4FCA=Scnc1lRarLkNk3h=>hUtk`$Q^F@)r^L4>#XQ z3|OAjF(O)TY&bHd@N^SnH^W-h;OQGoGf76MU1b~j(kuy?m*O_j*6?KP=9QBE$!WTs z$26BUj#``76)$draSiQ^To%Jt&9X75NMZQoHMAOxng^erLxbsl|wjLb`b^AK>+)2ZypCfUtu9ef)f_1E-US3l(nP?9JN&(}pq}a8v@$Rk;YO~6D zHK`8}k$dcH;#l--xFPuAc(Y*)Ch+{NM_RL}-B**oRPi3Pt zo4*tNI_zQk^O`$g8wS&sZ%>{{;}U!?v|8Gh%utg%C1Y9GzYI^d9LQm1_9w0o0&TmD zk=QFmeudKCg_oZsKk0F`dz|eVfH5AgCJ58Dc0+w${c-ib&-Vh3CJWZo2>zs_V5vs0 zXr&q5Vdcf+;4p=VOXAY7jwH7dUA(VREn{oz7Nj~qg3&|WsHMw4a*b3evfki*-0|M_ z^rTKToJ}Fgpf_heB^bCL;6~e-9pYo4Cr4C!p6)#I4Gdt1_03MNua^M8pwfEuHsw8Z zoy=#UR9p_Bafj&f{*%I2q~rrNSw0@<<(ZbzpDVX}ILP>^vW6iW`o6est7ziFh*0WP z_RZp$Xy<+EL4D+9;nSDs=KH-(6f04d$LdKGY4YETW_0{j-HR8>j)PcI<7 zj|WB6^7XFF+!_(~j{=6o%R3fquFP&iRjTl8>gfp_;qZP$SX9;eTA+Tklh)C4GtZCZ zi;b&q5UUdpR(L$NO2FhnQJ#>d`&Gl*aGa%I9 zhPc{jUKh5<6|?#}Uqh*;e#OLgv*Rkc`Qr>UWras}uE_hPQ`GmYV)}bP2J7x6^lpjJ z{!~emzebEOM)z=SA2C7wuw!eo`09et!Wj-=OCb*bu2;MjqYPOZrH6*?WrCgQV*YzE z{cJ>HUz9Un#^sTBaUUNMOh|2fz;d!+6-#B*xPv7=igk?VMsa=yvhz# z_jbJ8!ofJcQxfPHe3PZ;(oi1au4R2w3$-AxDOz`!4NyH4OOv#_3lAe=t6Xm|SesqFiP_7uGgkGs_gj@Z-rqPxX zU?6EIJ73nd|BmG56PcBvnz1UbUa+&Uw`1(A=g;zjr|wZ#MSDoC6kc3s!NS|#!j-11 zsU}y>?Rn~;OqsCThCe-#fIycU0PrjG^t}(%6HK%KxGqrOq`UHvn9Jl&T9?CkcyZ-V^GK?DuuoArjT3X`;F_m<1pgxt6u!d z<8;zYrQv5|ccmr2aTO0f`3G}6hNyT6Fwlj+=99gHz%2#2W>uni#{;lx9yF>iQ}zWr zn_*Ehkco+~u#<~ctD2aG&*z!Q&hinsr5Gb!z{r zPd0@xav&XYsaO!^W%Rsik2&Lu(D+#vylQ-r6+OZtbXGYRmWcbhnT9(-syo><(dKAbswTg~}<9 zG)5mi)FHJF`8a2(N7HU_CW<0dDvAO)eKX=U!={9K!)u*RlSgyI*)4^M!n$Uj7p37Z zcl_`Y0h@Y-M;=I6 zK*4$MPtXrJ#qUd>nLHWf= zvQAQJynoZ{rhx5Jgi~6Xj7k0Gc!% z_U8vy*#aXnY%q_RCnxqZj547=>-Q@wVEukwz$6a~iS)?nxmh?a5kK<91t5~_PsYZS z?4(WN#O!Z|6GNvB77+slaK;tGt-vBt(8`Yc+>eOvjfwb+#~7JeX<|<#HfC1?fG(v5 zSr;d7&LeY_=o_f+`mHG-lq|b#D&QWp1w;XC>pqWaC)*CB;*=LK$FeIy#6wdrQW2Ma zkWFEjn!{StMrw&of3xcDB$Z+I;7Z)V*9VlY`xn)pB>B1fbGe!Sfck54&0 znDyh?tazbBIuIZ#_Tv^D1>{V^9J=7~8G9rdkubQe75ie6L*>$?1&~=scr(5Cclavi z)peE)!r?-v$S>?F(oj(NAX;4Tu|=QPUdJ-@rFQY>8ak{blv@`)r;lLj7PVVn=n4>l zC|qY5DKiVzS;Q4s@IDAbxwuVMJ+ixJ5+W$A=6PJvk+iM%x>{1itjk5#ez7ZYS%iG4 z)n7H-sX^@vcf;Hp&8idi*hd!j19s2c3t~i&w*=>=d@HI4YwCn?Pg18tw%8KLHR|jh z=D#yVs4bkqA>xdKzw>~CGR3ajRJqfi`)#4Fs}tIQ*+iCp6^#zWCam@6XTB;q!Q1on zSSu3v32s5(wT5@kb>`Z&t_&jF=GM*HsX8;8nrz((5vwNVbh#;mOTySJM|S*uC%_%ne_H0tIUHY3%G@I zdx26jA+0G7AU33Fl6RIM1Pd8zr*#dHOAq<1H&grld4N#A={3+KT^w(jFRu5=VYZIF z=I&hwk$o#5aeYUYj>!SxF6LPMYTJaU0b<-OLO6w>l(V(ua#(;;*Veq7_2)^^PwuhF zKSRx7tRuu;|3aUCuD|O8nUuOGtFQHvy-$8Z8jOmBP~#59K-hpqA?e9F?GB%n{w!^_ z=w4EDH32Iz@D9A2$+OXk2(2I@-8=(Qq|y)@dm5 zQS}4&AxAqUY$PhUs7|R|9WUNu=0i!Cc;LF3!+Hrc8^B`Yh78{;n`xAp^Y0`7IOSbj zY_?Yr$oAUyrYX$FSsmNeAkhX8#=I4W#(-sh$!jZ4KjN?f?CF9%Tu8_DarOPf<$yt` zZqwxLeM)@I$447Yb88kVx0_afy0J4E59g=?$>KEUtNBag%c2%=R*$7NaV5}0^K=P3 zoBfAu$DD~yU584fJx%@@uUKV@t%kX3vhUe z=Jg0XcXWUIZ+eombZo)UqxdNr@OIGiLgkGUYr<{Xb||77&*bktNZ&{QOznOVd5;=h zIg(Ik_uOdOmvo`sNnqSKe^gjITi(Xic|%1Bsrg4a(K0jE9IpfBIL|X_i5m!`uhlg+ zGWytd1fq4mUM3ij1p>;IwUTBO@-(-5sA)q)Dy=hCf%!6tkmuG=6ubB!; zdQSGDyQ*yrCrQRk2a8Zf$~lTmc9EEy)>WS%<# zGKRqm;&q(#g+Shq~QxF)The)w$v%WHM`v^8g-?lSXOg%xvl z@&bc8_rb9t0F8n*fZ&z%bP~zFG)XVajv-gK&eV7`o6$Xj7hv=!b=L#32qGE@CVxZf1Tq$2)MLOvZEcdr?%-C7E(ze6 z{pu*}Rt5R%J?Q2T29ioe0=|4!(CDyqy{O)z&jg-|`I3hfHVy%gEJwsigzmasMZ*Ma z!m0IcuzDsshfif-MCWjEutA3ANU_!`K>%g~tb>V39AT%GdjMM8T62%<=eN&xkT`1;3q53d}IboN$J0h z-CB6Gh|v!jrAQO~2=rpqp8wph5Huz>vUd$>=mBU@8&ws(6LyK+FJRD zPeS}4|FV45?U${Q9O?rg;HE1H(*Q)18ji1=3IVj9#oE;A*USDZlm!H}GW>r-^uRuT z83SL)H4~@&pUK{bnnNe0^3H3M^H0b`l|vlw)d+>?^F)ZU3={6#!A`jVzAT90ZZv1a zc#OxVdx}=Wg%Ng8O-`vmx_ixZ4&~dLEU_wWl_up(07G`S6c`KwT7{)a1+^(Xzs3Ii zF(tCzHNA;ubor@c{&#(^!=JA1Q{1hy30BL>nd9z>-1^W$`t1b~J3r{?A|7#Xn|P(w}Bkn zvUW4hnK%@FM)G?(UmOYWPTi^CS|D)k?BlKs({iRrN+!5_QR)}nMDuhXxjLi~m0kWH zOzLx;3=6^oM}dxF|$qL8RS{l zng#Gc@xZvTjw%OnmsrIiQ}27Tc6^*#AZzlZ_;?9=;=2MoR(o`a-KFB21zHsw1x6Ro zy!!R;(5Mc@AFp=N0+tsQ$R-u)vy`Y@VX0~|@R7PfO7zTY#TkRKU`;S{nv1SBG4hQ38iRg^dn(9SihJ9#ObE!0`)MQm zviXdD-N%BRRI`*>N$5k@v@e|6td7DQf4s8+Yr27V4mWgvQkR4%VRmPl*9XYz1n_j z9Fjc`^tTQi`$c$05XfW{{@LB-L)w-X>QcZPC)VZ)cZ1pO+HMuVr6`Az@X=3Ba)98c z`~bh&nNU6Cd>j%w)^JDqXt zRF?@6UAdbJkR`PRyW#~Dx-Lxzo>_lOBbIiFOJKi2dPk1Sb1$K0tCcN?Sv}opW(YJ+ zuW8Dch7hI z5f8*Bu*g_sO5*<-KtJb#Jw#$EKx{bM&e*Nr&NSrBKi{dmx?q34G)+(s`$k_W$T#Vr z(lb)=d+Rb{{<%HZ>uUa*1|LF=y(0$K0I5m4fA-2@|B{^*zzO0I#-Fx-4X%gG{sz>gNBDMlGOw?c5xaxV2V=s8RPgm=0()3;-r$qOt6Tuc~<_ z$7p?QX+`yEd$L&a;6tza5=l8^xdp9yKe25FC6M>Ku~4MprmE%SFm>*F#CeJ zee%_0{o&kFdgvD%ye;>6T*Pfrv0Hnn;R_1}RdEs`@!y%DG=8(ra zK$e0^kZ;>1EVAqBu9u4MS&9~!%x|a@jE4nRz=FrCUu*%y)>?IsC(e2PP?a% z3*?KSLN7!QrqXk^I^z*Q=2TbE(ld=x-@8Fe&($Q2_9cGQAfrSOmB0%>!e%^yR$){} zl)$75hh;-mntAVS<+?pe`$oJ)m%r8v828`nojd_}+%KrOPjmt)Iqr$Li$VsX*|hcb z%gswZ-+0Kn5~KPxfg9*iUoZ!>3AWVEr@ZNOzbr|w%2uvsCh%(sl&92dvOd(LBj(e( z{q9Qi%Lca!W_ZV}lo}210EYOg=^2P3&S>-7+~Q-+t-Z`B3U;c5-nn_bMhmF=*_ckB z2dX<9_C;25`qtx5In+GXc5ZKE*RB7erET-0PNEfbPK)&;qHb>q!_bHV!M!!8M5+k= z(M~^i*aYpP9A?!#Jvz;yn?({5`|K(UOD&aa@TzuyV%R6BTxx_r%MMNK8Q=%>HFdlW zux%M--cEU6r1_>_wXWVP{;e$%QLP_i4PhKbqmK@W62wn%_eanV8s7ZevL*E%>ra+9 zOLX!F!W$GI(Oxm0Ee$;pU6_jg)uo9#_q3vDdXc1$^%`UxGU5$lOw4#^--m_7Kp^Jo z@3o7Min#ARwv*V2)c2kss~H2FKCz>Xh$klp;vkqmF|y4hTJ_yxMc7=;qI3&zK6ehc z<|Cn=?k|&`xZZ9KhF}-~@L+M=FRNzbbDuoccDYW@mIj^6L*Tg%R>Ec&9s{ zJsdH*^wT{B<*5xY*^QA%q3hoo_MJgZ+d!A@@NqBqZ5dBcR|2W=_YVT&MGZind@jZ) zWJ{iDhnG1tQ-5l(zk!=*XtrT@((J+GYuH^uP|Q;NkAra$*FFvFul@>P^a)lYxr0e0@BFW zb2E0m`k1;=tCWwFEIm(e2{}^ST4C({zu5cBuqwB%4H#BjbeA+N1f?VtC8Y(Hw1A*A zf+F248Wt%ip%T&Zj`z=dJioY9oY$OVjyT6T z#xF7$()ywyR*3S)cs(Ynx)n&^qOfG>w-^_ ziKqv$cv@Q03TZJ?=h?G{u1VLe%?r{5k)WZuMV_GP>(?RBAk{ z-ijj*Z);I2I3Mpldp*g!z0iBntfK6G=j%^^@}h+Ik}BU=!n0Iq9EtC#>=y^RHl7eh zpJhEpubO92_cm0X@pR%Q4vqYgD;lpPC<3NLO}{^JXH)SI6e=#IC3(vApo3et>s?Am zdv#9+j0l_SFd4}1eAY%S)(9+?w_V_l=dnw+aMssIO^p{qjyapvSJwsYXWXuucE#B> zGGbONlkMO4u?+Wi_40f1o07qdzUM~gzOR~VQKYmZLAYdY_>9)=5^R#g-N}yi0VCz| zdLlgP&AaIl{O@0R%4S_14ed_ruq%hVYokihz)MJtn!QubMMyTp_UPePnu04}l{&DV z7;i1Cj@&6W*JlLBLhtbX-dBM2HuC2VZ#4lYw79rDsA$+>hI_jTuXmX9YfEsJda&fX1GPc05-g@N;LB0>9 z=fK0^REPMK4Pxy0SoZzup)Af!$Hh;C+b3`*g0x%1EhQjJgQ9YKx$XjRe^Mluu4{99 zLdDen;-Y*c`)q}#87cGb;Rg3K@OvLU)=nB2Xi~IGWRXTYt0#}AI+D0k=fDv}(^We& z@>$PbjZ|H(8%7G!60yN*9E0)#+Vx}TA&}&xFMWs;fRqn>(>p4 zFb)LL?dGUnrM#$4zI@bC-Y_=tQbpwlbh{?DhN&oAOA+V0cm*-b35vW%er4wcVuoA zpY+2vSAD>CKkd%@!k4Kt{C-C|yPKSU%sn9+Y+kH=^L~xrsRvJ{sAvudcjmP&=B4?en1Wf%WB&cOM*Vxqa?ussooe zuC5Ga4Q|=B3!0Q~=$(`1fxe>ISsG*l5a-!b2C+d-?OZ)hldMlIBYQ`CvPuUOWc~8! ziYF(M=pi_<#{{S)oI9pp+X?q#c-vP)xOq}26hAoTW!-h}*u&GCn#kwG(;>fboZ&mg zb9Dy;bRr%0@4Fss6PAh)jM^)k3$BzJNpUyg&cc_6B;+F5skCG?A5P_OI_rrbaY;a- zSI>2O>0Mkr1>rUZ!{(~$Y`dGj3Wy)sq*qxJgQtvlk+4 zWms$$Eg*$KyR@w}4jS7(fUm%jT-c8J@YNNoH^zA*AN-$y(!v!~6=ixNP#B&6AS#;k zKrR4}Y9;4MKi!-2sH*=45{WE;j}FSQYh;bLyWx`=;^SDIon@G8sNn*a-#u|Xs2gr) zIYki7UrHvN=d&F8ddz=Nhe@GS(lY5P`6D*?ouRM21DxA|nm!ULeJmCQZ0~AI4 z+;#3MV}K9lkQ6IynfYksAA_$?Z4FsbOhWog`krMY z*q7p2v$abeXA#DA%DmWKt|%43e58DK$VfcPbiV7s`r!r>vQ5O*Aqrf;Q-;!7(2v8< zER~f=c;AENG>r_vGN6J{U^%=DejPMIdo3&;ER2#Tl*3!nabtOB&&BXeguHddZEZA~ z4|3je;DxQtrzJJz8NNYo%y*{+-dGbSgb(;H=H_yPbYeBJrr+qbVi;u9Uu|`V`BWwb zqd-K@tb|`#T^(6%F}=rGbFCCw-r#d2%7fYH@SPcMLUDX@g$1b2T9ZVVD>HYF)?0)I zt34{n*ww$#t)s4-js!Ph2|e5kB28;t8eFXqA#hmr%mtr(v8XyteilnH@0T5UVA&|J zHx>NMGXG&^02G><){yBKorP)Cu{@0rxmE4n;FeWcN)Q=qxW0qOShaG66ziNoR+#9JqTRIIq3o?d z`MJJj;vGeZ$fFSI=pa7!M;%zyw0DaaXsCp@uY-?ysfJ3dmqQcg61_LV?uMYd9`8E^ z5)`k2n|MaP2Dyr?g*KfwxeTt_FBln~n9Chws0N~{u|Ab?)#&p`BRz$lbIypfQGH_pyb2WH(|2U&Uj90?55|i)tMG)!Mp z86kZZBMeUzK29!qEsj82(MB(?+%Y_%Yp*{p7@hG;LPe6Z=K@L%5qJH!O6i1(o)tU@ z`$qnan$?{{>U?vApw`fP%ZnhX#Tjg7KZQ`co=o2zz2cjsCn7@0%;R>Y$D`b7 znKeZ&^6}D2vGPY8lAAc6U%nb;I2X|Si(zNGnAhDz*t1%A&uR6jutu0leI4fK~W$YooB66*C^(wi%C@F&ZzrfhS$ZA43J!dV>#$L zxo~{DpHkV!mr!qS3lNQ@T0fw*Z@sNr?Jih$xGp~uE|rJZ@@vlENn8l)dl3R4k7|oS zJF2V3FNcl1w~4}+$lg_3t>o5|n-PNVEGzj6w16w!9vZUiyBB$3u`=cvQ$wl9PJ;V- zP*=Glu66N&soUkT_Rl_=%DFmw*Gvc39~wPr1ct#4SO`v829F4b1&3(sIC#~N+Qjw# zo?wfOP>OqottzYhJTHHpHw$A!v<)8<(|v#nWbe9!;l-6PmAckM5BIckKOpF+8f$23 zK4&q?wca-LsIXNi?NanqOI9w<5jgYTYwqm*EM^!H*pzSRMRBzNmX%9Ud}J@P9OeUQ zXozaT6!9~Ds{4_OPF2++DN+~7F5j&+eZ+PN@B)fXn$4%Y1Mm}q;OjpWx3hnAbMt|> zwX=sjacGLCd}KCaMDna?-v-WLb^O&xj{5a zHfiXp5l=A|Bz^&5s!J%RKILtNg7EQJKnMO=+F`q#xA%_W!A4F(!NHm@^Xk5$UHFDd zzRf2lwcTKWE#n_im6=KIuYBk^X=8JsZBv5bOqABntXP4SQQwXD))9{BVY}D03yu{D zfvflIrx%Y$>Q71v0z`*B&A(geEdtAMOYRGwl%7Hn_VtfcVEOu-X}?vc1oaHMXU(Vj zu^F0HdBviUN-Y|l+FX%R)CnwJ1W6oTAt!g&&$C_r^e&0(BDL$r7gj>+|rLFlw>F*DYnEqAIvN1rXMull==DRQTQ#sp) zxONDaA|EEbA!W8%L6`7Z+VGuHI8FbYK{%tGER8am)5kF{vba;`zO>fPxD*YG33c>X zybJR<>jTN~A}sUCqL|z4LU`d+Ikc^0)u^=pIuHrkf{r85aV$^XM(0THWql;;ITrCv zq=MG-5tm@PcuxANd@*@L)MGy3Fa135L9QJRED{00HW6%ggiN0P^z01U0e7C!vdq0+ z+qV{a+rC?M1cHms8DDZ^hSd;T?MvaD=vXAiEyEvfrMwi+){9eHdMc><(>IORU`Jez zmB*QBi4AN{30^+3T1DjT?2Y9xA8qf?mx!!?cuGg*X=rJ7o(P|mXAt+s;lgO`6$!M4 zP$=Sv@Uh76B55TXD0B>TAN)!+Sa6v3B^RH-l1O7Nym@-+t)b-yzI-lpFqOCCijxtA z31>i^9WF1x2vLl{`^b>K)tUcYx~ss6ktCE3y%KZ$o~`Af7Y9dA;fiole1Y!q z2uY2m4@UbJjADmJzS7`l(kF(Y>BQ%7p(ZG9>!slQ1XXE5s13qtA^qD=o)Z3 zCYn@Fl8x5q;KQKyi`4q84Nf@>8v+(EI@D&_=L&Q$aR8;+t_lL`vLtfVOI|~CB)@D( z-IGY2$IF?bm9Jm<-d}=)UFMm6qWje`jp3bx6bnp6%@=~30PaKGmGI$UpN_<3p9yhf z?PDQ=!VJz3GxMDGDyUY8f|%ORgw@X@!F}9@CMi`Uk5(ZH8Jytd#j6Y^Ng@#N`TfH? z32CWRH#!}yF?{U=e(o0(AKht%gzB1Qg~bpxkcKhWQJ$3DtzoTAneeA~vaUj~@u++t z7#OE}NPu7EBfaY~i(Bx`cbdvcBT)CwtYIn;+DVd$u%6;Y? z5jwvPk`r&nx_n?*qVTfDzNVw3>Ed3B`~1j(M|`~d86U`JBn!;Ifaf=3#WH3>B+wj3 zeY#GsA~cRQ!O8;ov+%`)Cl#4C`4)Eb;WD`ik0A^n-; z^m>h}YiGE;XcLox9apc0DsB$pk0Ao52NKJG5k3-JlcN*wZ!p-ff+ z5@=G-eyCeOtxq#u$i?6I@iPbyv{|l|3TsB(8DN8Fh4f>b&>+}dD^Ye5KLek*7M8{C zB124tMYQ|3qZPk?wG18lvdxG})y-rb>=sq1Adpx9XxTXDdk=yKp8v7AxWiiAg9IqpRs4RQCTUR#qvfjQWNOm^r zfmr#L#Pn(eV`}28pLr`sfh2VHv2_Leu+wqssY#~@AAL|TB|IWU| z-;=P$dOe|y^?GM9a{KP_&}~-j1nu$!JPEYPP?GOPP)mdb4%!hZsmzc3X-Oz^AgHWu z$Ms=)Ad}bM*Y~$bcyktNEJ4_z&2vKw1eK`ljQpQpINdZ__l}q1s(wmV8k0hQa&;LK(6zWJbT_LOAvc@fx)3Eit1U7*uW;MjH z#_%i>PH4~l0;LU>Ts)XqfB`wnA0vON`Lb3O2NXzJ^N%dVMX!lV0H;vSU6B zf+8mV_$rcJqiqV5V=l0-*I#k*N5@`|W@ndv7tbusEy|{y;3k)ZC*c!O?Gb+iO#-Y$ zf;j3|1+L(ocqf`tIFtdL&`~M|g!SN0!b+*_v+i$tZ|xPCP;Mcz!y7f2v?Mx)Z%;_!7GYY~6C;vdhUpY<9=>6y;E;gxr{@5(PsXSruPVys9kl!5w2~+KWO4BQaKN#fu^S~qCDhY&2T$0$hj%6GQhHAB)(f$Qm zw)K-Aon?WAhkun4eMu z@;oREyqpKHO2Ev$8UHa6s5UOp)wjc-m+nRK9yR2uEZD6Xfep@|o&yCXRf@bxnHy!p z4NfkSGJtg6@aBJ)E~qi_6rHUB1uq3KN-R=^>(tTi2s{+>f&O97K}rL`-o=N8KLkI! zmICYqe@y_(*c&DJpF#B>yMVCZ1Y|>ugB#`0zb)Zf4R4WzX8_-TSJOvXFcHch5Udt8 zso(rxHVPVdEi(c&`Qna`7Q+NEiGBRu`M+HS;)sG(s}`GNiV5~VNf&H0<&gK-88lPS zmkDjNVvRoi*$oD8r#wUeo>I16FhD*30}}c`4l#&eyg(UDoutZW|DFKwRpL;jFXROC z%$bvuro~M7&zlsNs_uoW-|62e%Q(xLNr@ADi!5A1`lk4&v*@?UY!m5|COm3FL+2ic z&b6$*<`#bahG~EO$=uv<_3nP^*bbFD{VcJxgbFdabRD*YI6A@yE%>!}=7-S}wI$;R z&toF*fxB}xW~`;}mURdoEKQUsryA#+=$ZHUS0l!B5!-I+_IdlO$KnkX+?M=O>xI9NZqZh5u;XzWC7=n5v0_ZbNE%vmh)GiXHV=g~aqvU6&x zK3#`zm!{^7no(&ihtzxNA5YXA?>y2g@%lE#E>webBalAoNE95r&c|085P-pN7O`=% zC-y8PIP}hx+XIXeIFWJ;YLe{m-?EbIdNiOYXa)mwavSR5Aq zB^JsI!@7nPhk`p}v7b*UaGzRF3hB#hpK-BciAf@q?B>oBkxl51Q0DZMUSqCPLlHd=JR^x#Pt1rwND!k1fai0*7k*6!4CEc| zZ2~S}lsUsF5yHvZjW{*7I35JN`!N=P5Wz$|sAozt#=k@kUYr?wCIg>Di~a%$GbGju z8jg3?57K0lO7VS5z6%b~g{?rntVZ+nQnAE5bD-5(MuedsF#cq$vr=b%OzH2rCTC&; zkvwuC`uEW${UL2w*m5j_4!B@mOnv~oN@Gz18KUNRdbhyboH3v(Mqt`K13p*je$DDE z)<<#F+aLd7CP1OYVYR$x5Y$ZG;mM!RN6e#i?C01}4AjeR{^`Yc6uo;eusI2VWY84( ziC{qFKE?vwxW8mBJ`cGRvYml1^I|C3;ki_aH*l|#-?!D95j>-W^Y>g;dcpLWi*8_H z|I27ZBoXa-Ur=hI`lqb|hN4Qdh9{o<8Koon=nsVcUJqE>V+2Ys{$JG*Rhoa*5&J&H zM=Opj+)wS(xQil2p`269KorRm{~NIYAxrvn{_k`JsLwvvc7=$Er(;dxvIEOOdujEP zb2(+Nnu^1$>@`ai9B~^u>_Xm9n_2WlCJ{)Y6=M9$7WhGKoFhuV0`$ksLL!FXZVRTr+d8Q%@z~y!U&L`svczgeXQzwXZ6u)npgTv=!pd>c zB*&)zeLGCJqizlLmXUvXqaOsQx}=YvcsD-eInZ7xRr@B|DfOj9@S#6ACZ?CQ$|5yoH4G!_>v+e3WrU^oIO#5y zsCD3j*}e<=|J|w)#0ujlg9qipwy!Fts9I@-2am$~b2!QpT&;kgxaaY|uys$gB-)eq zDzD9!%1E4BmPFKd#q9mH`Aj_prix)GN5b>x!GTAXZ1D|;GJbJ5hcE_P0Sn-*I^~L{ zSX5xweD3=}c(vWteadcLY*ZH6x#I^3!2jXpQT`a^9Z&riap0VO=wR59K4#a$&7MqA zcxEok@`wti5sgfRsS(R`7N2D+Gyi*AhxWyV+yPNunm7?Ft(gpt(6IPLyIJmS>DjqWgz6)I)g8*W8Uv%5EKuxUl$T?sU$JR`$p)>vqT+JT-YGv=?g`dBKxSolhWj!Z1S z&T(`ME~Z2T?&Gyv92|-#3ENe3Y&a}9r*|}{f4bpsfw!(cOMWT zbw*aI_S#F!eNw(y*sbhL-UzBVf!9S3HR|nNzNZWGiIP)D2!771S9KxO(}!Ni%EoVAPs(GW z*E}u%!ashF>-5zpjMVIrIMU&BQ3ElU+w>mn!`x9GQ3 za&$y^^6TAsTC_b7C>uKh-<@*dy&#-QNSY)5tSk{q;5X*+o>+ny%p!Bs=RO0?LO(9h zkgbBQR?=VL?FP+4pGcjc}2}=-*%$_f@f8pM~J`<2SH=?p-i7b+7cIRT2S!8ZRDs7Of-OOT9@-7v{@KN*YTmufx4PZ42G#Bp4edz^ z@5JJL6OT7sPHK4K`N}ZA&y^j8A7(?tldlpoRB4ETb@bNAJS954jv%m(a8@fJU-2?* zV;t;bo2>;q_^pEc4%dj|1L61DXl{(s*3DVDtD-IA5)Q6m=)awg`|_l~I*#U6&E z+odn#P~Z^b&){%8a<~0xP5;F0=GSfRV{Pf6rBQp<1+VSarkwozy6e}jmEL|6f6{Rh zWTEbmbz$rPGiZ$hEe2o~W0DEVzhxkvOac+=NOFn`^`O%3Cse8_PVJ`th`}x^1souy zr^+9p?N6KjCuT8#knXNe>FrF$=*uV8fp~)aifu1%m6k{Y@UaHNAJ!v&hZI^2T&mQ~ ze+yWg3HlXGv*iUET+GFFSy2S={s@}F(T=7M!0LFi{#UW^NsYb(L(*;^-HM3kCwwVv z>>MioUgQ;*PVybw*UqSD!273Y0JQc`cvgi8QZ3@~Wm&YUCVB8$sM%vxDjojg1)l{q z(?_T={|zI5*QFjxptaZECoB9gEmTs~LxdPbY^iiIzB$^b?A4~-#f&V9nzk>Du3F7|*@jGSme;V=7V>2f0UrDy!mdXw@8DUrN@^>m%dY^i4Mv(6lR(v`ck^SD?G z4+S*;=NtnUm18ja|DK0~n^En)3iR_@IZ(MJoBqg2#a*z960629B?xIJel{%@0s%k0 z-O*5;i1HFZ7WI$@%Tp;1QMw^OGp%2L55M9uShPtaGwmU!!CI@2tnEoZmy~`Ez<_`I zy1KGccOns)VG`^AgVH3EHRwsdo%6~tf~M5DGht=LF+tblHOA+}Rk)fGUepuwXG2WS zL2M*0v%sT9D+Bp)t5BWv$pf>o zI-}0;G|6sxWOGK}USrh7}g0gR3cpSssCV{el@v9KBnDLJp ziL7lB*Kb~gJ?wKF#g+6C@;dXAP$Y6U}B~e zH2(x+R5=5NK^K3G^EcNBHe%r^z`%v$AT>Be>l5*U-@I}zMew^w(^AjTxox=nA31xmv1(f2ul1O8#`-UgyzUkd6DJh+4r|<9S z)xJ%C9Vsa36RW3pNfXr2NqWX&d5!+wN*-10@F8efBpCMYKTNF^{PIV9aj*V9g7r#WCh|06eQ;K50E&^MI-_13_R={&PpbTUy2c(p+{q@F(eSEW==p z#xC77kY)w&7cpnMZ=Bu*87LU&VdwAp4fG+<;rkeJ_TM*Fk-aXHHpR z!*$0kjR;vqIN&`}qobR88Nd)*B{QwRQf*)afNrpw2E+FKuQxa!STPYzGb0TsPZ0fw zUH!flnG!IS+h?|Vz?xmPEN8SZQTtkVf%iB1k?a;=ZO#V#(`J6(1|am?hfPkQ;m~`d zn;3|zV3$-L)?On#E0tVq8xc2hqq%smzZ1Vb^E-t?eo+Nq(x*C9qknAlYpk%Fj+&;mv`dcz&;T=6 zmlz$?5Gr2g?N2$R#$)sGt%50tf12DgnekEz(nI%l4&2OIm}U6L1r$9%{Jli>lbrvL z-NeFX4;CA22d=m!ZWIdQFBWz)-pd)raqL!WQ=7>+3~316vZd9B-ShneU&gug4v|Nq zyY<)N|MH@DB>r0jvvu4#S=rv!&{F_QD{Fv&8e7OeCHz<$X0sN}WHq}Y(#cAp<5sNg zfE@9Wsa!79T^acH;+Wwv{>n4V6}$b03mTLNIKS6|YexcH?UJ$shvsFrrBq_o#fBtL z+p*(3G3wL@uHuQ z?=5aGxC`RM?z|ccEi+1BL6&V$=(G%6vC@*QsBrDO#=jFAgYM`uK3l(1%UzQ)L@E5R zC~oLVQ(Kv9K%ANZ4aHG(F`Um5PO-m_d}{gv89dEDv+Qb@onrwm4crQM`%c2*vE{+l{?cwbG27-XLOcQ6SW(9UZJt%?{)w>` z|GQ~5I}ILU6-*6ErMx0lIZYeAv$d^MbXJ`o$~q}lB!`+bSwd&$ELH_~j>0e#MhjV# z@jbsKUCZZm<+8df&=6uy6=#hlt^W=3JU6UH&=KqxLEMm|2r%r$Ll6ZS zIM~0aaD7-|zCKoUa8xsR8{@pjGTXUtJzC%(*`Xp=sdz&FZ0kI8S2iyiMd z6}i35c8qshc-D)KTg;K753k#|F<4MxXjM_j%dw{PcEo5gC|?{Es{ zF8cTh+NIB46@0f^>1dnNlCeR<=kYa^ela+7_~>A_(-EGQ^WePbw#Q0aciKl9^OdrT zc2OpyG!3@J`7PI3f-pwicZ|RZsmW3z+Es2VcNb>b+qo&9Ju+Hk5iUg1C&UT7Y7<$K zzDGiV*ZM^F{6H*Q4h-|$pvqU6hQs#dB(jWp-gilC8Q8b4GJ*@;( z2`xM1&BzB^-?9AJw!{VMBlyq007EX*oM1tpKXs!r@rX8)UdIn$69$1Twk@Oi0rH99f z?Z1ZFczDWsS+qO<-Y+p&rgQtr^gUeFQ zdO%waI05N4)1lN`=+CfC?=TE^e<73t<63_4xngv5L#g7#H)FY>e~dQ^i`MprEK9jk zMak%JRIH{m*ELaW=MM+kll=$U7ZL<6AExsx+E_^_(H>2izsao^JNX%^Qfe^QkqyNc z032W?q3mT;L89XI&OT51Gezi4CKVyyCeouCwZ}Jk3Me8vQ87DR4J}x~=Bv7L#7uJG zDtxD0khcDnE{%mSIKOq6Dn|Nq zr#NL(WkN)*khNQbB~R7r<}q$6D|)PTUZ6XJnqmZ|U^;y1P;_zSn~tQ9$AOn4gU7z( zqb|;B!$j@ssq&uu_*oJd43AOGYk^+F+UueA#?9=Cg0?>`A!gFchZBNRRE zqT8HjH7-AnHlcsoRpqzn8aXhY%U$`x?nB3R2D`>s@#QaoTZWV}H;=JG-1pSTPsK!R-8Pt1UzK z+o0rU%_rgG`ngpM%dGt){kc^wj=R8Rr^3z+v2lS2qyt~^441o*~3{JxEE;xzlaM-9aS!&CWD`$=jP~WvZ7NO%K=O7~T$1 zFKj@sC!^u^*5-u2I$r(+f6a=YS+OF@aP)ezd5%KvoK5ATdQW_x=Ay;&FvE652i%h) z;d%H?pXUm~LxbcgjbHXsQ)PB$(->N_p6`_Q%)&xAGX48>Qm@=Nnu{%pxFF=%n+XuJX6 zk);+i*`d^Jn<2=-R=9$Lg*hEPis=CX@bPm0fvK9=m{9>x7=A2y?f$f^*LKi>YQ=5d zwA<<7<6o>3Rt^{lck>2Js(j11?Ht}8*bK;@Z|k7uI*MEMvI`7zkU?^8RJ`Sd+YH+_ z)(y?W9a^SpBXheBQYSN(6C*V4P>V?*?rH@8vPTZD7LiSvo#!hUnZ3LyN7Ao%tKcv_tEWNFUENJ zY*hUfVmfJyHgqb2xt(QjtVPXd)Zvp`{WDY6!#6gEuP~$@8%$v>t**i?Me&ZvI(AcO zW-9WHWQQ{|>tFe%6r!ZCZw8^YBuB9(Zt`433A4*!q)>G+oFcVJDNL0 zhY*RkM4nh?b6S1gBq$lM?~8v@oEN%BTjNAa{m#i5v)gSsDYue>F7w38%}KYdL3?+UQsz^Lt@dM$m5#XvEZTBi_BR4cWw#K(Rj2USiCnG z>sWcwfjNe&+4gc_Mc>iSx?u??yLueH44{igPGt%?&`=gqpv ziKwFfcG9#FZ5pxA_6MScLVLNIRpV37OPQj_Z*FbsEeN@2Nk=P+znK;9#J}3l5jqR= zuo`^dO}CchSm1t}*dhYMgCM8e-qb;v%?o5clGc96C*cNuoRszc;+_Cou5V1RL*y9q zT7RUZ@*ae&DIzO>(IM)=-k#QjZflQvj-mlBEyfGleiB|g{vTvRgc=NLatL=LcGvSE{7gyr;mn96%w+I0cWGQu%ZlLd0Bsa^UcL#9>^237cc0*cUd1qT& zh7}pTKEb?=h~tE+MA=gRh(`hP&C zgzc%!#Sk=)-;4|&5Ae5-cZxLOoo0;Q(5U!QIH>ZpceU*a#m(0ttq1j?Hqu0;d!NxW z=(=C&5efQDO6rqets!Hq!}Tn&ZTp&7(O{!L`B|KgJVhQzHkqZYoQq)>wh_+xH+P5tYf*OPWiJXc~Eo`eS8KMsrLFUQp@WiFH? zT%6L}eQ;O||==DnFZ;aCn+png5Z&gBxeaVR%?_EyI zb-dYvy&XS>%=YxT$B1ZOJXyRd*jr>TD1hszR5nR2EuN}7-+9=c_$0JGDeipR#{Hm{ zy;(<5EbOT{LL>Eio#%S0Z<5qG95XVgR@LuBn)Y>Om{YHoMqNq#w%1eYsJG}^|DlXM z^)eRr5~ag!g(6YAMvf2S`5M9DwFTDSHk`Nf54y^uNjDvKVptQr`y^8x$=wE3x#h4w zoa125vsZr`l7F0Ne=NAT(MjWT%VMqZ+#ozYP^jLeSZNep^uABxj)BIt7nYc=>1mo3 z!lGkVw!LjE%z3N1wxZALc}3klxL$b6m|ilzzq{(?%&OU25YNpoEHZ1C7`S8b@Z)0u z2Ik6@9A)iWD9R+rm#jQ#f~0QqjJjHD_k32V*ugyHJ?f_z4O(~@EN)RA)>`~{Q4l9d ze(*K>P2a0tk`ex``7ha}$?FMm3JC~36VE%^D?}2Le1zDgKLj{d`tc$WSrhtd!+%C)3qtl3FY;kXy}cwp6U>ZxB?zh^BQ8rZ#|M z2fB@JzWNw;5dQUQg}rV?y1uKC{nTdv_2m&g&ke_nN9bu4ZX?2RC24lU9JI%}pUcb> z2FvvcmK*wzFPh17uHh$nKBJc~$Z$G3&^@}EqV}a7p28m9WP6mB#_+g#LfK}(f6`QK z7xoBJ&F-UA&7HSliS6Vx_uc%TEZVm%6Dl6AUC^ zM4`EHV!|Y}kMQiW77{1!vPq%|U-Flap1dAsd0?R#yjp%;)VgXm+EfFUY#!UuJRDtW zZlZtQnSDPX1mjgYB+Bq%+$Z{$+u1$n5}Qzo#-7j?BV@s{JcHbEN&3A-_x3*Jaw%7t zA~#WOk%ShY6a9CNTX+{$*@PS{+B^y7Dghnt!DUh5AMwH<&E#h20rY&A{o7f#mwiga z=+|an-6ZRa@!Fx|PfILJBA{Pioz8uIDUifFU3J&u%WU=q8i-pr?we3JzUSyX?^cKC zMd>_&L?)3pUM-CGv5p2bISRhqy_Twa`7l}K7NZ2)-hyaTX$3UKAC-yQw2wz0W zf=Mt$l7_*}WNlQweY-WGQ*3`^X_#yJVbZ+)K(4Nbb}6T8uacerlV~QDQ0wLM1O!Tp z>Mdm0elk-_(JxeXTC#Y1aj<(*<6UqTt(HUJVsoA~K=6aOW9K5w76V+lK8XZM1mi8BV>`S^4>lBtlQEX`;*d z$+D7-Mn~>hO$T3`cwVS<(3-HGAy?0erwL0QSsLo)Y&joNOYlHI(x>8ZWY!HM=KWqh z-HJ&PhE!?~{ga$Hn#jrB!f(FH9_pc!x7A3R=c){rEo;<7ZWc9C$m#72*sPNX!#2ZP z0!T5Ev~Nhd=@ zL3jm02+4#sGikQqr}-b#ET4HCE$fxo_a~-T-Y85ce*d7KP~7T$eMeO&8@9N0wR}r`Ryy6JT~`II`UC_4yX#UV5TWOkTV#+ zqPzsbLA9&#DE0W%+5jz}B)Govy?p>-c9E!hhlx48k31Nz1IR_?-A2U0t`ft}N!7Yfi`i@{OLb zU$NR<$Ent6DNZc(o+!tmwz5ke@b^x=W^l{*2TKB3FFdN0pM06kiya=iT&+OU0#bmR@89s$zYAL8YFc+8qD`JOLWgkOhI0xL4- z*e<0T%ZN<_2F>^Xcwum9JXdxElfi>n_xTrbA76o`LhhQ4j``zsHjyVW#EcGg)qw#+ z%egx~i8S}L7X@~DnBKjydoKo}pQq3`yvdqjRP1P`l5wNG`Q|$5yIBGw0EMRavxX+RXU0n=6E$P5Zp^W!zL6n ztxVg|nHv};m?HN~S9q2kzO&44GC#l0CL-nGNCbjJ?Yw9tRn!%Ps(TKGYWk zKYL3*DnQwQkz3M*+69Q_dq(04k7aK(ugpdB$|Yik3(z?C-Ru`9{t=Ia5#BBb9!uxw6R$U)Q zDiCAC>oG5qlgkFv?m92n1^WY4Hp4R%^{*xXTta;f#n&QE4H!>#c5k6}q$5sLzUm{^ zNSTb(S+j%CkqlwU1HOd@d*z&}3+vJ#T+{epP$Rp)m_bWBzD(LsA={5ka1j(5ok*In z<`SuY<&${3D$s%qZTV?*9?Qxs^JdJRmZ_7|jR_B-Az9|VH~LBLsp^+pxgPNOBNSb1 z(!!jR=NR@BzGmWzeuZ7BoOBKq@`!y|;$BX9k8#ykQS^BOck~69fsS!^`xZDS%0!_I zDb!^F;mI=RpPPysgrm9uA^)g@!4k!HN5jIQF58iFpqc*_s2!gE(&7p!Ocj>=%KC7e zmm#r=H`X7Cogfc0NYIKQ*i<0XUq0^i*lG*woPQvnW6zJ|;l49n@}>b<5hoTBnzmQD zzUc1h662U2`pxBI60gh0Y~IV6I^zs9Lt{ADR_hZ@(R)18F&bIn;%MH`S{3a&i5S7- zR!kd3WUBxBqYe%ESRKH~6=V*wV(&Wy8;{ zM`YEsPu;~fu;bPjJY!7T@r>M1@muFT`t93V>w|H64mKlC2#syuR$_^{XdHj;YH!%d*$R# zqD!g-uQu(mv8N&;?KK`UksH?=Bv?36Sf|sh`V4osP~iJ?92c{kUmL&MahRVbM60 zp{je>+uvI#+GBFJ52GL+@4JqF>F-?FAJ*2fHwiOepeDOzOvRoihbm;K`-~7GGB1Fq z%qZWw-+Cj(6G(r+z?WjxO>L&;4sI0(NCfXW$Lb5y38J96nBt!%paMW)>RRV^F0%Su zjZEQfn5SU4Yde9Ew#5`8J88+`fRH|P0a?C@Q8HIvc3W_mfrkFz_)baLyN3>M?-VKt z2>M3W9Q*h4NjqLrd}JRc;-IYMAy_ws_X6Bk+$XXz7n`orn#Al6q1LR<8+W28cMPyb z&QP7)Xxtr*Y(ZWx3~;J8xr!q3+Bo!EUGKz!`?Y;F$A+i{4L`ZeY_eH_)Fh@cS3q>s zvAJq*rJ-~0mE>SxSAv)ohh`m(fhew>E<(Kva`}r+{@CdWgEA9&iATqMxaQh%}gV~;m8~)mcrFf${-u+ z4ip{%G__11KWFT0cjlB{oK2YCq-*G?^DGnmL)w>cq|30P5;0jpjK`SL_PhZ7H&a2m z;x%71Ngvf)q23@fd+IHH|1lA3JaAAS?%gIu`-JM@zkFrkdnH`_I%84T}Q+h4J>FAOy-iC)^`pzCNP!$db_Wm4rg<2I+ z-6s`EpS(>)=aIKTU>;bJeezN>yNhVj{?zpGp2O! z4fpGZ8`8>oofH8a#sx;2f3yIQEI4N>MDR)Z(L=2BC-a=H5hYC0F zaK~~u*bDxS*IP-!Cr0T10i{#?AhDl=xKw` zs^n^^Uj|OrpP~D(N)Q+eJ}(?B5nF-}Nmwd|zOUJhID?O`88G_Zu==90vjq}qI#1XW z>a*)dbIqQ;352K%i!)#^r+*}k*{HC)Pc&* zlS038FZf29lG3BWn+$amwxo580xx<`YEC9zeNk-6?K3SOO?yAr_-yE_Y*N?#IAu#l zj*o&?nD6a(=y$gG-QK8`siHA6GOIwIYL1S4ZQmxqIUCV`{4H>$eP3tj+weM}8)5mf zaCMNc%Y~7c{;OD z<*b^9z{8r>g|u^lBZ0#;IK4=Cr1zm81P4V^F;q_v!g)w6tTBiP(q;)iCZXU1RSG}`RKVs1)BDy{gK;4tZ}KV(7E z2$hKts0d*SvQ#KJ1~N+blOgJ2b2wg0jd!g`J>`yvJ5KqD4h>Fw9#6xxXx^=8&CKYC zF!kO{@rUrKd*xTeDkq9g>bbd@n}N%j5?AOZ6g^9Jmed~OJrs%a0?4)6M~eY%-b zxt{sPv3fGR15Wa#ZfnhgKbJ5+8M7{+cJQ%8B%a6;Mx0`8W*G(PJA|V1UfYZLf!X?#7nkK^=VMtUg+WejxoPl+j9=3ukMbux%<&(J z#nqn(9-Gz4h>Ck7avI{;wIOm zrE@utfRx-cXF~+0_H80FM#z^Fz=*Tlulg90IW%dh-fMEjp8+&Z|I8+t(w!;qhuaL$48zyb-Z<}Juq+eXeUjFa+}WZ0y$dE) zsHg9}m=DXxlXj}iSjjXA`| z8cr%nLTB|+O%dCiV(gNqvBP)Dn>|~sMX_ainTPgDLx~$3nv50c#VA)yF*gg8-!l$p z?VKBrL(CjT{h@mi~o^Ca)@*zCCUGgkul` zyp{YwTzBjl;+UbxM_ndhujfxkG*3$g1r_W?PEulV?8h*7beBd^&PfDIX`elAKU;zq2|_yncVa_SwO?15c>CzF56B^4XJ)EFM*U zmVl;wEX)8fIPbF%qJ_(*t!1QPRmQ418n=K3t`zT_)SV37X{GA)d+H4QtJYc7uIr(! ziDmlpZ$qgLEEYq3V!Wyg%{x`eyoJH1K(-S{N6+S{kspp=M_Js>`XV72A(h!j=eR5q z=$hf|;eOLfB}8S#EmGh7*yDCQahcF2&N+zrl&nY=4Q?3@IE#e&aPt*_s$x7wZyvQ9 zLT6K?PWI)ahHy}(^Ym{n*RoKGZNIz@C$uiSsQ0KkyccAV>B5XQmR@>d?Kbox{}V&A zxWPM;?;~&_39CRCEqQAuI&$r8Bezt2cKaa*^QMvav`IH&T|2g>{D8k~LSp{1wRZ-9!q;HoFHAgudnXfb#%}F{&M<|7ID7xNjlEQtTA_4s5M5!q9-LGH z|0ESDZeStBjMco#CA)m_;+i(sqdmaN-}z>F?d2nxh2Ibg9b8eRfGgv^0!C`Ll#!Y4s-F!zP#uY$<`|7Byb&r}e z4plDTArtw6f2h1LlJ4Py@Z+X{mKFx(D?IF*L`l(fmr9?NC%lCFVx?MZXX}#n=-*eH zhZk`8fji!Jmn$9C@e=XI2(L@;n(?`#6h&Z?^5te1zSYM91HD>d9uGGi!S6}@Byo^x zRu%Ue`CCxRD3}5!aM6OwLTjZs#f^R4GsP#f&~%|{EaimPz;9D>ip;xiGMAFVb~D7i zMZtp@#%oq)3H^TX(d9rr@w7{QfAOk47v{s#wYz%oF8l0eSIwBm;750R@vDln96zIc z9HszS011Hr)cH0)A7CIyC@RJT5j_J0q{P{6rx1DVWsQg+B(&sn&aLo>HDCx#Ku3B! zXj~6VFp0gILiQdGaw*FF?xmtBNo8)>+?43r1xUFj1~9iG7<}!g;l`%dUnnN__a8dfx);D-B5y)CIk?Tgb8_tI&A#p!yPYSg zPW2qfM~kKm#hH(qCw|blR~+Rra{cZ^VfuX7sq(%?I!SrUf~$^P8ImG38rNS*_;1B6 z*UAurk9;qyJ4-IB7uBqkuNJj{mBBkr5BmYE2YvEicC*zp1YH8n$&It8!eZ9@vwlZm>v zBTtOJz9-)s_%=(VJ_ubkCE5L4o80vZFh-V3w5crGwY=JWmeVx7-KRRAu~r@?q6I!* z6?V8(Nt4yl<#*eG^J>2N4#hzAvwPD0^QM2B)DPIkDZ~Y|^fQ!3_b}3`?kcLB$m^YZ z_dUnBM;+b5F%(|Ec=x>#Rm|B$pT)r+g;^DdsF?FrmS?6aherV_wt*+svk zk0+trxyP3HVKu-yE!Y&1FZbF{kR0wjJY^}@i~}AUfORhRA1B<-wx==@)m+=Ss$F~R z^7Y)vWB3Gg;S+A;nyplsOR4mESo{i-cY=@7mymqij*jCF(xpX+$IhF%PJd!HPiZm7(!dcmBt0$qRtAg#zO8H1qf*2GEvGDkH802-9l{J+ zBviL?S&ZD6^h%}z>l~|EZg;wOS&%*qD5Xf4%^2?Yq+Dkz-K{o;+e5~W#m(!RG^UaM{QW#(P?WPtsv$Sm0 z6U=3dpu!zef)nM|WQr;(Ej*?Vd6up4ZJ94`tDZ$yYSXg=h<7%hx z-TL^8RCilRRWY=Q51C>YjD;7hx0_O&EHIrJ{mdnXdL$3*To=?*Z0 ztlw?Ekrz#mwpn^~YzgS#*~Ra7i^{545K&fJ5$;-@>(uZ%{6z?I6XKZx4q^@)xavlJ zyU&h4q;nuU|eM^@`L%@l;_mI?bB1Dm3q?V(G*th7=s{QzDX6afJuu5Z`@u8UKv|#NzhRfC9@-w0q>nRbXAAjOsVgu zi8q@Qf7PJ{tW1h;D}8vB&N{ho-NQ$>@)s2tbLwuD7QX3HD+0V9p=g2f5fPGp{SwuUq{FDdbYM)hzCK8ojOtcB45*>S=E6iN7iZr zl*=8P5a}7m7LUoE6Jg=f4=>NyYkG5asV9D6qhCMc;Q*sJ`rUsoX$XFO^Z+Q$r`kla z_x9JLt=6}(MNy_`{e@rNXh}Kxg-n_2oWHtVl`|O|C4Iy7V9<=t zr9QOhk%=PRv~i$TjLImATG|mn6$h}uqsGiv`je0Auf0ifQIQ9n!4B5)S zl7I6Bu~H|melOrkq8vy}uAcQv9q`vJbhprKAOf4|FB01OQhB!kz`f{xJo34BH!)De ze2cvP3Xh<9RG%WqbK}zB!vOze{PA>gn*aow>3kKd%9t>%Ozef1s^xm_Ry9Xr6(Vpc zt}GL}JyWxFJK|>j(~uEC@Zos0b4xadah7A}v~kMT<|?)51izZr{@JERmagJ60WVVl z7zATYM>9FwG$GOTD9~ zZ@w8(5*%9G&p%dKQF9OkU-N1%ZqYg}f9^-*F8rdkO?Ptt?(_cvuLqbvejkeD;e9w8 ze_~um`s~--ox%uaUL6B~mtd!UHtWDX5@$VHZ7T<7xIacDr=g?;8q;bz#?%6%x*Z=N zMc*hJ8mK_5#@@80Xc9wt^?@``+0Ug?cf#GLhvUqi!+b>r1|7gr3b+i_ViUK*t5EnO zctJ`Dics`QB6>WSbqw%))gEj!x_hF_dJzpJ+})eBKF*{swiLvzohUrw!dSyxl_nbD zOzasLEZoWl!2Xb(Le@;c+n)WJGVuM`?W(xbV(wMs3Ce9sQ!A-vWMFGB{C7EJDXrbW zSoA&i=6bbzP=x?Y%GBZYf2Q?pFVb$NOq!YFJh6bnM)eTb*<&+C_S{`7OSjh_qC1SorP8O*b)6x_77oqs+dhj-l0=t^@I1 zO{w9r1w-|cw6s5XJ!y(`@F)NnI`|=qrSryR@OrawNW=mjD-+9iwMMh(i-T80eEKGL zJm!G@oEO2)_QXN>P_>%69YD?AyERFUSUUmB8x&$X8hV*Bk#|&?dGN63&>oa0&y;|C^WK#`d=Iw+9B$re-bAV z{Z>S4i4^QwSXd3Da2MwnRA+J-*VzCr5RDBI#Sg$!&ueBj?Ce3KsE*`AHvEb`ZDn*> zl{_|^@`l*6(pA7)y7}t$?0UhCWLVh2-|~8V*i@!4nOhFP$d?V$1M2LzXc8~ag=s+Vv6!Ret5xX{}@c)yOQl;|(rEE+*nDqsI_ zU+kVRO8IHCUKX=^t>$5D3`J=Dh@5Tj$MN_4{R8MBBKVi2Qdh$P^1Ne=R~AF2;oL?M6FmnrsW=_kE^68>zCo2nxJ>hfge+8d`d=c+8iuX&cCLhiB3&|9YBTj$_ zm)a6Ei6T*fv;&xWB-N2d`bP3;n>8Jvb}qpTk&%{WG$`=Ok)qCCO>_EOYFbwr9)vys zWx&$K^+Dc_L|U8s{?6PFvylS(&s6FScwW}7Ce@afma4g`Iif^NB!j%=co7%f=Or@z~_L zejBAnY{LXou-4n#^_2_1Diy>DkNio?dwHG8pJVo58E`w3+Zst(*_FAw@ot^%!SwE@ z9AV6=<9M_$gEO77%iN(n3L4Fc-{&cAmgI(ZWH9$yIT1$p`~<;H^Y1htj{b9k4<5l1 zBmwU9xaGXbR8uChd&m#gq+rQyfTAG!0m1uzvzbMR#K%-OU530t^+Pa;9<>S+Z{68> zwadbwhD+v2@OtpcTk`qO=jVrXH)k*pr;=$VEHC?d#ti4Hq#cCQD6453c_h^_yKJ&A zv;Z8IDaSOeHo>QIH*1K_EgZ55c!5HlB0Sjz(hU6BZ}2aYOeE!z*TZEbffcUJ@te zYpi1)?&3bDdjx>7x=AY^_MJ*WWllc@kwI7Xac>zuGnL$hWRp<`LldPU`zeF^q3|}2 znW@|F@c2C3-u;LO){3CMP)txzD?IfN}E>FnUTuzS20EgLCNFb#E+* zqpRh?OyJ8$WHp^ljqMaXUzv6)w)Za=E3eRdh8Hs_v>P|Hx7i6p_;h_x+=zfI@H4#_ z%eYMu$4!4spkOQ|U$B(HHF}rL+3vEQRKBeK)L?Dzg4^wYigTT-*ic03s{~ATjp7gL zlmN()9hqK(CRdLEiD~ZtO-utLPRpXU4}-(xlO@(VoAq{@Gx+z`?|LZ7Dk$MH(Q!OX zHE@yDC-y4)?~Z5L3-G@)P{EXrpswA?CDlq0uX{|p(AT*F0wWH;i#U~lpJDC}H#F{X z&N)4`bmYy{Hl`!*A2$IuHCI4u%7HYub&10RaxkeaH#|Z+lUDbcoO^hQ<}4ZYfiw@- z7FU(2B6ahKWMaGv>k)u#+JG^bSZ^_&Noz=zq56UZ!-)HH0g5v`g6Y+zKyp83k#+h*Gen&h!=!oF5;w}a2(r{w&b!G<5?{fPSVbofLyW2^EY{FJ;^b7_p z%X(`H&x%*3#~Nc$0qs@btB#}aRrZ}TBi+T5ZC!o81{9WSQG#am;58jypVI-FrOIEJ zBac|64H7W+6aTMI>8}%o)Y)Kx{0SfxkMHy{lyE@i^HSKUM&trSz?A6qcL3pbb-Wn- zWNuGxOA83kj6ZS=GeWyn-ilmKu=2jkjiad@T(E6xkdJ|=)DF!bm^e~5PJ2sEuh&0L zW^iLWGgfXDEv0y z$Qz+D_)#R-t+Exv+S?Pf=BFhXv`iv=yj3xna*c?1chvKhiH3Elre&eQk-vs)*F-c| zd+AVxD)9@@PAU2_cZe7|O^X=y7+N@wv|7>eM0P}-ko<}p?T4$^thq%a`}+qDaD&g+ zl6a=XAoi3{e<3>mqmKvZKEenC88pI z>9wO!5cv}ru|!>wWk31Q3-uM$^KmkYSKiSP7r1omX+;XjhqZD6KTw_4{u}%t5?2aq z0FV)@eCu(b5LHUdHfAOis(v49-K07_!w#@iV?~8BYy`jJln!M}D(UimDb(({(CgFL zKM@`&Jy!?^2?VQH~8Cv z^lzp2RPTs@A@ytH6dextE3f+b*a!z_k-K%d05du1_?`@IGT^$k za?H@^v8Q*1>j5C(_{Q~+&*C%MV=T%&JcuOK(KGrmAOrD}I_emO_d ztU2>r@-O;3=uqo*}4g89Q=|1 z9b99wqC3!X9oRZZ+YY`XDnp}t9cmFa+LpcW3E31Qc3Y0T9&T#hym*7Q^BnJf-_Jq) zv4t;Mkv}sFD18c3-b{38xoL3k3cC4!G$ZQk`3T;fXKc7gUr*9`B@7&JGH`xQ`YSNl6n5m$UKly6u=hf1c(6r z9DmUT{@H8c4`B9t-NOae)cnk9VjZjpbqPhZ>OPQ%ii)XEzsW($HQVI`dlJwaGGGY# zVQ{n5WnO9$5uxx@&D+P2uzrY{DYSeds~k_!TD^xM#bTsK+`|;nZx_4YYUz=!hKf^& zqSQ{o9guQTdI>fK!t*{llg{#UIb0|dPlOiB`caos&h zM%MGM(W3ZPm7+tR#cgDq%eXuBaoCt%T=`7_{zQgD!nxM_&efa~&(PGL1HwC#5-E%3 z^>+>ncW0tR93_UEX*{aFvPtcgyXyO@1@G+bU4y#;8quLJ2~^Rhjr8K-J66`YHy>u+ zg+xvZWIi(yTgbp5U~uy%Z0@QcZZ+-d>g3j;Q%KT<_SRI`Dc6ee>Isvg%BTQMm~z> z04??}hjdaQAO!*reL1uU@?xSy)8usxr;iK#o6UXz1O5MVqR(LQI?wq13U$W8(!yQ- z7j#vY5fMwrc_B;qLH+Ybh!)9K?xesjvG_8dhQm6$>S`qS`}BsKS~sFq_?*}Nd}Egz zpr+oEFOG(K508KWy&A(>T~pEMBLKBt>2a4)U%?Y+e^+$}5WUTB!!0u9oKw#mdV_E! zmQS?ijxr*MEZ=g(^c@rK?AlQP6^pAlX?orZNgfV<`hneZB*NMQMxTruo42v3MDP@< zU6uNn&;3{!wF>-F774*~-*3iWS3ALZh+2U=Zx>^S766|K;efQWO z|BouVV3@pINCh`$%s9mXIPj+$#1`7qAvAfntvcHB1#hEEqdz#(fyv2$vVz)=KA<>RUqMS25+J5 z%v#>e*slaQCzMS5kkUoiZ$W|d#2y4i$N~9EZWj#|PA-~?V6=IFq9O_(SvP{we%(lu z_B9Bhe?5-^t<~r9W{XsAEbGhG$}`O?G!m`6MSuW*gg7Dwke3et(li9a-#8i#w-M%l zUm)Mk50N>f!+&~J^9C@oa{SLeN52m|{(L`3@JZe_BmmD&7;69F&P^_o4jfU46*MB| zmI4Oo;J`rpM~|D1>f+74m`DH5|KNOtW&gqXz_8Mu+pM2|@ClGxeSW?cSikYj$oyYP zADk~#wTy5vV7SH>m+IOM_jq2WxNnp(8xfB^uBKUt=p`~Z>8`QKBYF>_`*79^a=y&6 zpI)jv^G_apKQVD&^_FMs%Ypn9v#^@7{g|D3)6iV15s+mG+$`5IISZJ>JsNM^dyOFT zmiY;HnqcPrQ6-*BL3brbM`UtIJi@QAGHM*;zZ_ghT19Omk41Dr+ecL~WLfLjtGhQ#=u87iTquHnG;`O}7KOROO|(lH0mp&RVKrc$ zZ8bI6lx*EH$p1mH%6x8H>RKLs*=fu!D82aH2=O~-Gpd|3%sDm*>K4H{_sHR0^XA}J zsUb_2+v8lVd2$}iz?;F>&k--%&++z8_2##EHyL>A$?jB~$9{Ytf1YtD3rxEqjM_h+ z(AwX_A@sXifGa|8`WHsTpPjb;W0(R|JyN1x9J`b81PY;g0iSB=muXY{IGX@qtoVyL zA@-HtNI*?B^_1-v*IaED->qB3>ctkJtQV8*#TO^T-kS_INX5VeRyZ>tN@O4 zxowE^(c=BU%ti@ezD=Bu)(8`+=Zh(Zs=cvD8`W)+y85A;Xhig9J2ox3!dC^-&xk5u z!pl+Y1Cf8HPLR%0v`0T=OqE2nV+DU>z#F^0pFXCgyTI9F0@I;9re4YC=NFVkl_0#)F(&flm!5SiOOn0ownjMbjolM0f)m5)RCj%28!%Jig*Z zEqwpf6yaJ{N_{{4$qn^4i9jC8=)_w9@-V>v%cB4kwl)>Nn{uK4VLm4T*l_*28Amh_ zK%@a*WJwJOtv#-9Fq>FL0c7t{J>+(LjxrJtkY0Nwk20>`!at7#eslRVZo(x{Lht@Z zqp@#95Gv6>PeFEj@0t{#^RQq6qkSyJD0V&~VW3Jw1a25@hcI{dM2!G{d5X_1w`vYG zS}25eVhSf+F#@o45s?Z&r631z_VsM>xpT<>Z{&sUCxnS1KbrMNS?G~lFkfyk znFpqo#dn@BS_1)JGi@O{tq~tU+!py?`iFn#)z%RVpcgW4&upLnQuux(g1DnGNQAt$ z0i5u(TYw>BSR2p|%v0my%_5l?gw0J1j0e<_xj;Sp{) zR5d(YLQD?!tRyuWG1otg0d9YJ+v^{#&qaVWxi4a8lnMu)`I_<=`mcFKbQ&MI#5Q!u+UAT?#%N3wk`mdWl{q9TgDgodM*#YcB;HIiSt~C0~ zhyk)L5Bi({q(E)q?8BD;q4P0nCzhB%8dvA*1c+CnS0Y4-yb;TE=nE_ea0$|XGOYA6 zhHOASZacsn5yG6Agof<9(r$?|UEt}-Kj+5(O$>tr4>6>CK9<=7T!{vLLI0m$6?l!m zwZXKL1XeSAS5GQFrdB*F=pjZ*3VIf+->y6KNUC$AUp6m z2$E_1jYjl=n+<`R9{zK<1FsRhB3%V(kxz11;iD6PZ!kQ`xvm3JTY7O^TF)&nSpV!K35ltHPVoPB%>A2#llL#TrW17F&sy(}CC#POvgYO%4v~{_ zC?2zSYv6#B>-fK5W&buX`G5_=4EhzAkPPy(@1U0*V##~S1|*Tcw~f4ctZ=}${D3d% znyHM6`hl84R$;I4a#5TqQ8{ZQUP$szm#NHTuk*9emw01w-Jq9xhe$3Vjd~fc;9*F- zy*K7&Y|>o16ddP?`#0iT)C>$A9#NLMq@X!J+Iq>>VNxUSXyWjhuM-h=X znyH!~^LYk>*ng6ZfzAA(&=5>vxsfE`QDJSs+sNMR&uSE7heYwF4^CSYx zzfoflS>+2MhrAt6)NTU!KsR1Agz~OirbpgAP5+|eZ0l#g&kkY*wCEFyiv+`!a=033U)Gs-Sp?39Vp7pB$%S>e0XrWqUhekx=Wp|u2@@tuhKn&Q>Wrx*d zQJw<0`Ujk`mFQ7?0zQB9I5ZtdT2D9Wejb_y{OkyMO#c)mF#OGkCI*efZiB>fr5_U> zF$`3_BAl+$wzFaXie13-RjKK^mgT_@%v3t9L2MoZmTn@3+`;4kUPTM0=~OBu+84*m zd`DE9dNKxk+3b<=SMA#M^Yr#-^c4H%5Bo)5a)(;eOdg^XKCPdw_dQDs!$bTk7CZcn zHTP)1q1o!hH!_7$508zVBQUea&{2rAKlQSaL@8I1`Nec|u59OXFyV&V{TIcQvLB@x z_ZhOnym};xX6SH;LZqc{_Ns6~13^`-DeuTY3<%J`DuGM0V^M*dFQYu&pZ~rx<>)ZF zOVUE#duNJBC4Rt?un3U?_sCHb6A|+X!5}>E1;e~~bySCrP`rfbos~;VnRj+Lfwebd zrXn^eqCJ^ zB=BH+8~J)V>~YQkhWO!w_bAIsmX}OxNvJGV!sB!tFuzRt5hBV#p*;M7Y1_@cUlf5% z3}b9AN3GW35pBA`EJ9Xeyb|8A?3&vp7N#2JKtR@-!J^HI_udh{d8PzDDQbiaY-_p% z=14qRBr4FTydY$=+DVrE7%ZBOLP)Beot^!LgPu|UC#Ou7^T#3%HOzJ|Z<-)bm8wfP zZX6KC2Qg#b6|68qq}_{$af*g&Kep$16+c4(-#?rLC!aSb#hz^M+1Fxx*O zSpdiazk*x-9Z^Lfh?VeNTkCMWB|8V01bw9R5*EY3()UeqM~1Kw;gQYT1N-^;kLJ_P z@Vcv-ILHM`l+WzG#j#d%_T&dbq7}plm&f7oz;Jhd$PB6pW$CBZID-K}9Ih`6D|}vopahVm zqO7=(ci|b!Ct6=Ve;@|={fSAR`g-z1783QP@vkiEiRy?1Sx6FagFhV|zT9gPFVM^1 zvz6$tLsCH^_f*>(|;ub2vQTeCJW-ztRybpg;aZlSzoQCF#L&l~Aq#D=foh%ATv__U&%L zA<>FEM#;lXK~H3y6IJ9`NE(M-M?*N2V3&)GALG zDba{yjW|(HAGa%a-aOeJCa;~NvawS0HpQaz?WA11Sw5}$!k<$gO@6Mdn>6%}qN0`) zFrTjQwZ;m0V<^Fi+LZ-xjRa|9CuMJ(h{iz@vpy4rG#hIHz6a%M7BQZ1iNENxMDZnJ*xFz1Z;PCR=BZrv3nOZ4i5l!&zg! zO2B2f@7_cZ$=h62Ci_AA-3Gq|p6^lwYyixKOlQ4(BEkC}>E+23R86fSSyiQd(Qok0 zgikKBbf?W$A6shEpG2S1m@)MW8oyD)9>YPu4P26;Rn10qtigs8fxBf|?ZZULTqUAk zR3Ey(3Rf#JI$#Q2Zv8GhcQ!7H2lw= z-6G?8NvbjHAlWveb$?U5E7Mfzx*8JU%l}NaW{~CNCIq8JDE;ER=l0#L&gyuAmY{@0 zVQex_rYD(@x42Sq8=bh4O^WCqpLamf7d9E-Z5A#0Vs?^~cwzG85W_?7LNe>Fj^wL# zF3912y2xG>56LfHdyt0>6c(J#>q;iCNLs0=rzORxk5JqTzmxY}BSu9mnjAJ%@%1fZ0x@>C8dWwzAKf9^j^|#5wm9M|*pxmW4*rwZ1rapTt6x zQz6n}Vc%X~PiOeN_oVb)=w1i?j4KI0BhKrI*{^YGu&n&e_i@`!0CMuv+tncdE37ar z9N6kZ?$)rg+W0B&%Nu)8!_&efdwjO1#5y15X)e=w@LOmd%xS?`$58hBydCGgZYR?- z{PnSRwa0k7^>&}0cc^RVqlKKf+z;_-AGw*gAC6_&B{qFJy5x2DnnJ-J7B0B|5d+0$ z^Wd+Dk2NeVI0iexmcdtje9=gM#B0wpP$yITIgNF^MB@XUls9#H0ZI?HXlGzxsMinL zr^`iy1Gd6>67catKUY6|sSPD2@p}K1?rCh%-LpZBVbqW_oSo{!c@)k|yp_>MJt3cR z4xuMDT_Z7^b{jCSDDDOd!f+;^rrH`oRA4cweOv$VG#Rrpv+9SFK|DHPSgc0|Q* z`Aqi+q=z?Crb#1)Sl=qj9dvpib`IPGnYjlidDL{ zIEfd{R9aT2!R@+Q8ttlhv5UKxWE`#g0oOdD;K6+D)soDGp)%s-F>Ienj_9p>Qqwmk zACZcstha9yPh*+FWQENy7D^>>2=m{4k$nIDqstvp(-d82!)~;Wha4V0{%CiCT!ufb zQ`*7$y3u44-q0K1MFBy-A*SEV5_XinTPAW^LfIj(MMLS=5rBgZ*tB(ypILrC_~uB6 zF0`sh!P8h?$;=#R2-%mCaERa+Gt@3y!yl$gb;J`D6pGcM{gK_`@L7zWD;j}p-wc~w zYI)p05s5H1pXnL!fj#${tu*OYFj%)(YI;^Mlfn8KY>N&?fJHeNdXG|P=5m4OOQUAL zqe!(b;Fp{sms>TQ&X50$d(_p@!0kwbhJ;G|BiPv0@87e>^N`s0uiQfpPF z@QT-B`h^!Uznxk|2kW$L_ym`6qnz@|bk9WL_8+HXcR3AqyT_XflSaM=iAM8DKWEDg zpoZmoUFeeQLPbOOBnpM#$K*m6yAj$)ym&Zo7-~|`1==n@7n%|~zHYmZXMKiP%ri!J z9z$P|vkOm;G)wCC&w(IBq3AMHXy!oB$OwwgO|o!uXh`RUAN6-=u*Vvy3n-pp*#i|1 zjNIB^N^nY#jEMOL{_Da*y5hh$qnjR%vvtDKvfP0if7XoDd~}hoBUWjC>hV1SblT-Z zX@na?3Eig~?%hJ()k{0iO{Pqmw5m)O;hk+wEMx{oF-?~5Itm)xx?3EyDPO5+_rga( zJuc9xpFIP?8oASj;xgjRi`QB;R^6fgsvXzWN=K)G8WKD_;}Snnz}j-Wns^x0sTk}b zheelKKxTch=cHVw8wP~nOV(nP!-g>plF!*_@8vRLflanpX#)3Yu1Ywu%$6z~pYy57 z=$Ig~!*gWDjWD%1J)3N+3S6i+)pMOFVONnw90Nehp87+kP` zaun6T(2DvPc4@92zrz+zXc(b;F=E@IQp@$|7`$Un)hyVUji z%~f12bf-7R36fV40T#T(_BI>;ulauPj z9T*x_rsdUOARay4xVSWN)>C=h5FHDigqg-WpYOm9Br<~+M$bt}`0KQ@qPr#nEQ8AJ6|k$?;D4S8AD zUiB<5RL@arf<)URLhtcC zR<5QE)!{(6Bvc!|cAXRF3*@xnyL-wHh4i+c6w(%i#v*^}5_Go3E_AUqQHTq{2zkjm zqjm!uLoigm!4>~uwlu~gqV;(0t)6I{lo7Wp_0@%8$5mM8UG~}<(^!XxTpN!gtE93o zlQ#!uGqoC0+%y+`j4c)Ny>oL#=WJd8Ve){~`kR)f=!tVzOumjwdKR7Uk$=P$cfhHD{Z zX-JH_x73G`L4O5{+#0fErh6;(eB6vk|)ClFk!`LLhY7OjQTuT|y!R zX!Mt3_jkRPC>~qeC~`%r6F(a-Z;l)CQJC$5+&IF6u%B%7C+HeG#`Cx}S(mi{-S|sL zp&IY1K*|T7jSKWp*|;1#K$ZHd!GHRDKj50O*E05&M(k?g4=(`L`S+rJ>0Lt=L}D|B zV!#$&B!g7A#JLGCScjV^|tCIITA zZj8}Nwr47+m@JCl`YxN5rg>;WD=CMnx(7CB`!5RWzsDTPgoELtZ_yvpRY$>Pi4S1p zQ<{#C+&bDVX%#XmK!Xxf~8!o(TTQ zr?bQPs*Fsz7Z1k{^XZG!wyol?*bw0z?v*b!)5061P1Rvcr=0^gcP9&>Cf>v>J6-EB zGj@}|HhwMyZ0Ng-O%^GhvkOa~$pPcOu_tGt0u#29#pYg0Qu zC(R{u9c46|YA+L+3kT<__c#!vP;{^Ncig$>j+$AmyXyIuOCOJ#8-OC1fg!pY1T7u} z+Jc694^0=3jjX}ISMmCMxrmjMV(q09!7BOCM^Lg*t(XNt*z2r!O(=_@@W$q1ItLjZ zck3uM9Re~qVtLgXNe09DZsLL@u)7~gT37tWYTiCh2UV!M4|{6LBss|rOS)VVdJW87 z9PI#Y0<<&TmFb?XCW|m>%VBIs2=;_5&QL>K_to`{BhZjPA>utX{fzk;QUmfUI^rg9 z!2wM;LrXRRTKro*Xq0WGTq&d%Y^5l0PX(b}AFeT^Qbp)|2;JF4XAXN8;k&}`38QH> zdMP4}cYb)a^JqN(Rv&?VzJh~?hj_X{gC$H4Wa!SOv_Md=N&0i*bPk|#mBE*l{e63C z3xe7qKV)%5P{d0F+5{k>N49joRtb%%v0O%(m*Mqj+GtVKoGt%YP*c{Z*Tv%bh$}8o zrOvMPg8f90<^$7w1P)^Yq5j$K)E7T=`u!N~k<2tAPkifD9TqV3{B#lfLUiQOiyVoB zf%BUi=eE2LZ5U`)d>My)(0-AD^hTr9v=+!81U?j!3ktz-r^{dxr-NaP(GZ-?HIRmw zJ-Vq=Rm=_MmxjNV%-kP56=~t|2wN`H2&wzI{IGL5#lPYH$YRqR;p^qqI7emP@llsA zt4<+3GYy*%MdSL_HPm~Ra?VGp{-5qEUt90*A5zW-CA+n=iUL6%g-b|1JwsQ{Ci0Ze z6yDqjXc}BGMx(N}qi`docR{-uO+CnYF5>Ga#F#j=Rzzdut!*M9?J7=ANfKKDEfpP? zyb&x+EEs`AIo?x+t_{?^(|6 z^`3scF1w9wqpo5f)DH7>-5-bV(YxGXIzke#-JibCHjKZdc+O7Lz}Taww^$_fcB_vI zQ&~U;mBTg&6cze{Lod7&%2yM*GmL;%C?;1TIiAyo>lQz%%ap_`vz@Oqr~~?NG#_ca zKyHDWqyU=vn_|e5rvMZouYpR*2x%Ih>j~0)Bl6V0Pjgotw3AHZAwa~oU%o~smumZ_ zfcqSLjZOD}W4=)LgxN${@6>#1C;@yFKty`0aqr^~ps4?();G zi(nFHds!O*8iHA8mhnfG!3UCG9x^2*>2J_uDKT(JTL5({Qe4`qKhVRU^#%c`W|U-k zM#i#d8S?S#IG)vq!{!pdvD_j4u^go3{puyAx}6B#2k+`teh`7^R*pi!WLprrVU3d4 zNS4SJi%CoxfJ$n)9+Q>eGUd^Y8w70mf5v;@6$<0Cc{NyUbBaJh9IZZ=dC4oD6P3|(G) zUOK2K1oOPaa}i5OKq49MnWsxnrc7Bfb`6F#Sn`gNzC{42roYb$LHA(B)1S50AAW~x z&}q~ikkSkwKpd9yYWnWp#~&EtA(4S}<|SxnK&(v}MHIdesx>gb``8tFIr6p)^^`u= z#S83HX)%X)1l#nLGQrK^+PF31$kWgGhkV3>0RC`wfQs?jFzht6Ai1MU%mx8E&`^Be znA+SoAI|ftB1e<+0WcgH_r)n*0ZUP~Lk^>PQK?{5XLAO@NeABIpB=^uZ+;B7y8Xm? zHltfC;_Z5Ul0*D~l#E-U6m2!yP-tqIu&H3`iEm`tq#PavaPp}J&ROD-fTvOKlHZ$w_JBrfuciV`XmE)bG{n``~0jw02`X#?eV^WY2Vr}u}-FBI+v3Z+xO~9 z#5GT);x%-vogDbpxZA_Eye7>W4H;P5u=3&_Xe`|X>aj6f6O%K$kyt@*GT;U(hfeY(`z+u*o->7xl4FY8x3C07TYVGn}1#wUPgNyAUe zU8QH0aWI+vL$yjl=$bz!)#Op#^=a_d#1;{6Nyg>wdoGl#p?k zh98gs%|L*Mx0gX@b58e}h^mH-lYgjqK)7=9RA=wil}i$DNd;yU6dZ~^0c?0$<2PTG zNb>Dn1w>V*;*3a|*y7pZkKNH9?M_9RUd&gccQ4{`R2o5%iElM0(3D08y{zNNmwtcSLo7un>$}28s;MXEd3^@)!@wX1U>twmAzsEWx=wN@NVv_oSj$cAoOs zF5T!U@b+bisBA1xNI6j?03i9!-mHnmiI-Ea6J%*cnca`TeYh-nhr;s$UZFryc1L() zd(5!Eh9?Mnb1(%lyx%1xBRhu{PjGLnK%wCI^717+TBb(5;_z4TdM3H)=12Ow(;*g1 zYirQ+5l?J%YBF#)+ecdnV$D<%_y!(&0u|UL#xkEterr{|s6GD`7pS<)t}M$E3h$|gZRG$bp-ZcPd-7U&vUjajssO9mF z8JpVy2cgN9C+!JSwCj&ma#XyR2ms!K`tq2MSS|Y8Dqthb*s|6x35D-2OURN+6GY$c zQ|8+#C-Sber4*(4zBVjmvZSMdOWt*To&TWOV3o%)IbMhWL0^W#0u2U-3>?@Ro_2?= z_*fZ)EnYq>iQaUj%%pOL$7zI2?y8$>u_^tOlan*+o?J3%=(%{}T-s{qbGS=cbLaKT zJU7(8k8Ax>V-oy}CV@r*&}UsnjpTH5mylS*l6 z2kG^CUlfmmBS1jb*EP@3L8EtQ1#1c&K0DofL0%E;o^Xu;X;Zr;qALQ;fs!f;JBmA( zxB+dvNDY0_t-5-WL?j%q>%DxZz!gG*)hf?Zhs)2Z_v_w~a)Q`9n76j1VEIDeUWUoL z0YRFdNNQ`@df!~}_I zBN7{vgGM7DwRut*fPQoz*h=b~f3g3$nfVx7U;Lx;aSx6uUN6*w6k$s|NcuB|G;~a# zi=Yoj3}%@mX9RuRywy+jVXyiJ-d6Jyy_eHTP88Z4!iWeF-Ws>k$GVqNlC6MI?I+pP zdX&@+f0x2;im0E%Wv8f?tQaTsg6jZe7yVYqpsVQ%YG*feJdiGZsd>_PB)#m^kW1qa zhpy@@-QwHXUi^R-WRFi$G@I^Q=^^*24#53xuE;6LIwJ>iA{Bjtq7WYhd;%Ce^KtAk zC=XipR_lz;f-ebUGVNHdw~QcIzmt=_ZM_Vl`Z6Pm8 zntj=1v)_wL4!u|o@JUB}Mw3OCpD(_J4cR`=@uuNALlgSnqZ~Fr(#n@S>~LD~wcsm% z-!fb@TWp}y8Oy}_@aXY~L2$HKf*gj+Zo~sJIe#=#n%#qzV6_D(d z`YStyRcx_qw|XC58)&jlW@dcUYIc9-eznZ%{zd!YZri!z2(~p&%e`X`izcy6S8H>U zDj)`z)!gq1T)1ak92}>zsEhdFYDDw!oI{JJL%L?8YJ()6%undXfPi|E$GsWG8V_DE zE1M8n@bM97)jpRMfY{nQJ8fbd`;gIN5K!*e)6?Mk9{wNR&N`^detq}EA{JfJwP=tI z>Fx$4MM_eUR=T@W1f@knX;Eodbf=`S=mzP|^DKP#{_Wq{?>=+RoHJ*JKm3DX#(BQa z{k`w&`ds%TF7|mNvO+rlYnY>oGa{eF=yD2_z!9WGD@BJ`5anm0;5gP7f^06=}8mpPJ`h7icfceN@jgm{pq zA}F~zSs%Skro~>^n?Jj9UsJE%4GFkAz!aNrvJz)8{*pF};shftgP1mnY1KC1zCGaV zm~p2P>JXf#s>=QTu2Az-gM6nJRvG*L89!0U|@3X}a>N8`38lK^JX3PonPS~PJ+)jURzT-D-z;2p zTJ3#Pq@9O>MaGMuS3YO>^Zw;4i*NU+ZxiHEPlB(|~Ma_Em63*(p56ga)PreW~C z7dxZ?&Et`r)Xo)3Vn7p(_1<1MFiqZ8!g&MwbnCp2)X)s!`F#o(+xEMis>R-xAC-*r z%`{*>8_pHFdH-@}?c#^=xuB+7FRKA4>kD;bix z-|BC=My@f&K(J8rQ^629|vQ1cy7f8tE-7v>S~F zcNr29ikFbQlSs=ggmikDy*hyXQa`BofsdtjqbCE(tGUm$>KUT$oVMK!EVL~Ub~ve!PNp}Z2>PBgDk%3n$&3YSo|OaCHDVc1w40 z4!mEF8D@NbwxrG(P6NmQIXN+*=xKBWF_hxEBQ;LDmL1$>I!*oEg12zYfaT$1BtC^0 z|4nRY-fQLar7H7}%G;i2Cfq)a=lUkh;V8odNf?J|8tlZUB`-`#uj9g-vzawbq28h- zua~|ivE>;86aCIHEdJrb8V7c6;hR3De%TiMvSJC>K3Fplt}p*3hs487X*O2^*2)QJ za?bfCf_Vj;V;rZOK}vXJWGH;r zwzq5OOR_Sp7C*wX2Mc+O!B72-*< zKX^#aM>|B8WxA9CO|2oiB`YZq2X`^v&KxF>%KIoP8E^G=Xa0 zZG54L3VV*fa~Ms(%ttBMC>EF8}D0QN^!Rj zFm4XaQX_u7+stkgJnnB$QStgu7qFnCwgfPKzc*n)*omF=y!#x{7j=oy5$e0rZ7<#$ zH+qD3*Vo?UR6yfOs#4d;`}{MY*rk7~H`oZttj9g%8GtP6RTFG(&d?MD2^( zpYcY6p(0wHmsJyKQ!d~JTz9g`J6F5w8Jo+W`GI#<{d(53=7Du{s>{JV=FZTkW6=fd zcavDMSGQPgnJ+Lb9YH7ClYzH4-kVf*TVu6&ghvUXI3DufQcc&E7 zm6{}SNF{(x!INXtZaqLQU2Xz1>xyfXFYF?NN--=N2?L#N z-=&tlB5lIjO0YOeP8Wjg=4gKLejnFE&!gkb8cHf~VkEd^4Vz_m0bTc5v~2XK#KQX0%Mm*2_V$(n zst+^Y1&ZGVKOMhTJDsnAWqaa!wBsIyA8&u^UjBWlE-FyxBc>`-T<{@*BPu`xwW|r3 zgdn-v3B7*)#2k+!YH!ZMuKPt>M646K7zn{KZ8QjBNYJrQe!BY)ms^esB($pUDlwhn zJ^Araz4$lui*>>%80D0Z-YW%&#Ah^ssvXem@DVHK04Blg9EpE_yTHSGf4-}MDTf3} z7$OW!4dt_a+DuOK#Gy?rj7v%rm-L4;gJ}KiaDgFJ4K*HmV9Qy{_Xxh%ds906Ka=se zDG;B?1&O)`BVcdRO|K8(s;7?yKW0?j-{XhmE;^lWu!bT8%%L;IQhg3-z`xPpIb5YF z7L1}hzw|&Nz!?_u&m>#sGHuM=*f+1{zY~03A!85`85#PSuUYRBhkRHST;&v58*yv3 z`7*y0kDfrlUI#adn4?veHzW*Zb0qqCqjOL333JTzYGZ*i>y$VJ-cGnrZ9#eT0|3$F zMgl-c356_E(*|Jz6PgW$T18B@4hYn%QBw^q&JW z7f<=Gr&jRdU^ z8i!c*=^b43rwdXssih5a2_5gkkOAXxXgwPr=yl*7@}~>!j~Fsi0ss+_L;m(t1W@*P z5d$$(%L4Bf37;JyxZ&qis6z7c4A|mr!0TKltJK#CWAWYxOC8Z)8yy(^grPt$0gIf) z#0un?Io;4pXUDZz#64OYuzQSy0zinLJSgObw2ei-^Au;Zf3t>JM?^)f>5hNV3t3aA z=pNXi8@4dGSV#3}8KgVO_t`;W&k8^Px^F;DolhGND|RZsTq!kXKD_}23LY!%~$5ri=WE)AN5OF`jrlk1^Xypii7b*g@){XAl znI*@-9ftEA7{q1aY#CYl`1S||7+LfzdnMVoo&xhb6zh!696gZau5kf^FPF(U)D@}x zDmXFxL~t)!#0vr_kNq;lVpi32hcfu7L8BZ>ZS>4lGb5yQkkF1ycQgMyZhj>4C$Wr_ zm{$yplFN1qUy&JQq_9D1_+Te2EaCmOp@)c$rxdF4hW%TblGI3pgBo5PIDGL)+mBw2 z&oHqyHmbN11ZI9SZ}K~ObiJP(W)|u47f2P!88haJ>vz5C9?G7>zhUX*r=(R8A{W3G zgAcCoJ(KXCs`I6>_9UMwXCC`(tWI?ClYlNzPmw-U!qGig0sAFIVui^chUSF3dRhrE zJjjlxoy{05)U(9W_eues82RRM^GqSYuG#H36FnjOD)$BfPQo`y-%Fp}N(3&11$hJu zW#A~rO$GPKAzkmDUaUWvo*yjK`u>s;+J|)R>(~;s*&Fynh{hIHM^?6y#im5ZqX<@$31J9_hpZ`gG>iv`WRC7`yJ-R&qC-Rv@_K4X+Wb73o z{3R-id^s@=NOzksIB!g!Zt2{13v+Lll7bo!z6M4_BAa?LBWh~1>+2(o8h0-A%i~S( zc(I*BU`J=?K`{1?QLPJ#$6lkK*dy)vkefIC%5;hEBr+nRyV>twv10MzSa}NA>y?Ds#L2nHC>fH2D6$-{<{EMLt}gZ zK^a|WOb*==5AYF4QMq}yAe3Tm)W5zL^!zPj*$b`I+~!G z`r#@GLJ4OLCuRw%CM2II$M$G5VZt|~@Edx6H=rrjjzldKL&ZmlA#CSO6cOi#o<4;g z>K${OBij7DKlXL#p;i9}nz+JrVlG3RY7@WmYwI~3nDuR=J;3iaP)}Bx4Ki>XvOc19 zwjEplS)=BKOQcmDEQ?sAlS|3}LWcy-QTQ4z%HCH^;F2ymP6lwVhlrVcVfeX7&fn`+ z5R5_ljx8ZzJ_K1(p{iy?i%y?@E=<}U`-?+er%=zLmQNH4cxS`)?lcP!)H*l&A*<2i zX!nUD$mu3;B0|R_`(HR$q|<7j!mzhx=9|iK-U6b!<-HHM^m{lNPm2bAV4ZIC@F>OK zC?gj5m;W$xw5~D8C$!R$mI|?C@8{%d7_WWLCZeo7D2MQyiCH5vxS6zt=7VDXvAQpJqNxXYKYz z>3l7n<|4NWVmK!1b&L+6Bc+UVI4s}TPKdwQ>G6%ryZ1I^T;4npv*Pi4oTdir9vb!$@L zI~@HtL|^#r)sUF*aFSv+%|239hKHFyOpZ6zzed~55)B<#N;pb7A6nu;_Z|^@lN6`j zKqhbWrkkYxI_UjJ&ak3qB}lz(+?>y6$THCKT}QY>nk-vA&=NDc<2Z zrLao|U9;^7<*K8)*Xtgy)rP6UZ33_*R~U=ri&0V*2&{n*pq{#hQ}yqQpl|nMDo73v z(tCM^nu~-`ek@(CPr13{0K6RG-9h+!y!dUX$ar5gop>o6T`oa)dqj=VbD^{`nR*P2 z=P8Pf+PELhFL&g7@kpN{MDEjdbTL;@Tu8F5+;w7aOYNB$%e#hUBla6Dex%{|e$cQF zS4^tjYoYpuNoxZchc~^b_f2o|j>c)U+m+i-9#`&_mg|e37hgsmERB73tyS&V zg^9`*>#2VqhSmUIv98Ljjz(pm%n3)rk~DkKDtjdEjRRe5>-t&Ie|_C66;Ex903+Qh z@V&yRG{Pp2N3OH?c$oKk^RZSzjNrFd)BJ7WYj9#R?VgwfDjxScb9~ae1tR7%vZUUw zR@~PwCY8#&kYs&}vhIO$8QLQ}0Js903d^}Ir7B{;z#k3@#@JL`xV})Wc)gkZtfj;- zxh56S^_x6*b>&7NLK|t6PEi8TV9tSGj;n0%dam{g%(|L(M6H^i@3(x!^ndzAwYW+L z@9LOb;0rVXg8YeiVUED@>x}#EZob)U&E1RdrG`g>l%j4?-fTM)zf%f1ay3=Yt)zd$ zC*Zb5Bs<#v7MI}u1s4|pX$Zj7YWd@ zV;64TC}S18-2yDk+qSbS=@gX$u+C+x&=x&LH(;B7?{mF=GfiIOaY0^AF6u@4)~))+ z%H}@PA=Mdi_&ypqd<;JK>SBMcTLbJQsS z$5yq~HUAw)2jkhFzj(0W_ zmc&?xwdrBJ9jUZm*ChPmY&#&}mt4>bW*lfJ8aeX&&nJ^CYp74Qs`(kMD{lHPww)Gx z?dRqaJTb%o9%krlV~i+@$W8AOhK&&((xquYd4ROA{CU3n0m&U{kc_}eImW6O#4$@u zg|8Vm+Ao84GMwTU!GXeARS`iT~N z#Ut}MS=!K*f}0W&#@KH8SrBO_FCJjwm%(`wo;2yP1;8W}mX>C~LFOxms2TxEHJB95%`o1dJWj!+PQ7mo`>-t z`g}N0hAS8oY5!a1$VxonYhMgdW{l?;N`vthfO8Yz2aJCGvQp}FE%E(?E!2cr=&$vY z@Q40^q8Oa>*lbKR@vxgV28Ywi$@)Zh3Z&!$Iyk^dlYZE5Y@#~xQiQ!(Ai~ro?SQ%9 zZvB+5B?1ORcOJ(OF8=VNs6jC|x8X7?V+XOWUI!|2Sss0oeAsBe$sHdasZTb=!PT*C zW`QU5oMx(_(IH$sVF4@zBv(05g`fN3koPF+Lk1(x!~r&k1qB#;8+K@5vVS#@8$R1+B*> zAI5w+S@NZr?n$5P+8tDudx^G9(u0IekHv1p1JH|d@uP{{0?|fz8t#r+^QM~{Wl-P1 zFfjr{=WknQ#Kl!u7wLIb7=*lc2};f_#3yHp6>V%MK4rBC8x%|LT-hr#?7#Vntl2f| z#0+@=moO$qT~~zQ)m#+rumO>_e+`KMeXf<1G8K@N095J#b^Jg0>ZV=A-~#a2aR&J@ zAZCofMQ+BJ^CFEB?mz`m;LJ za<|ZwN#xsNo>*}ez!c~HFZeL{4?fJZ7er+Qz!wKQtyBL6En%6mFdm@pEN4Bow;dqJRL_=K;HT1uNCNQ)u;P zmq!jqHku%;hc^kH!1%TND5p9=te+w>-H4}1zg|R0L}cU3kk*9=CVeP15qE703n~C5 zJ+G8_ue5(^lAlHv`{K zT{~;7;c06z)+BuuoZR~f74CjYGa+Vli~-817i4FiLG>C4S9Bd>o`#F0`11TCs<8J# z`LV2_4DAe%dI)-Trt(7C5FHo+EOS$(pFsW+ueg!!)!`s4t{|ecaG;d;w?%$J51a%6 zzu3UU6;*KYlrD!jkyd;T9c1>qv9~o`cRT8%;SjRoU`r;H+i%-%UzH0PvZy`ljlgF6 zvjN8=g)?{KX_GbD8J$5x5$0>FIn0$1FD;saQ;u!v&Bq-cw`a|6El<`^sT@z;U;adx zjUrh*IS-selq*7HpNUecIL*G9O^9a*cb|7C^uSm0yTsDFYfL3XR!Lz&wnyl!Su$#M5Hsj5NE>ghi2?pDR9w{-3afJ<0U==CKAPG<)&6 zym1OQa-El4t$TUdaE&>Yw%XazuUG_w!=t?hf3HS-Gn@BH6&{QH4*imDOYD<&EIMs- zH;QIQk7B#h09@304<$P`bMOlAWoR`3T6Fd65`C5@m$F9&OBDQ4YYW2(xbCk~)>FEV zWR~nd;`PS?DjzpIB8O@PMudkrmCUr>;c1Zp|0=>_`Aq-k4XR-M>kazXm|3x~#}8JP z={G=_*m6=(b-OngxT?QW(8be=R@$GK7*|0@P-V_a@3@>Bu8p6D{dWx0!0aBqxtZDC>Fj=NEH6)vHjGVcWGMPfTK`r_LW%_T-#N_MlHKrx7B3@w@U1~J zMN)G1!O29?W8yD5$Ds`(3Vxn*5fn?|S*XLy0ZrfR?pUSvaK85Uey?9JRKd_WJPHeY z^Kg5+AVCNizDTIQs4*iIL?G6^RPWIQB3xn-aU)w3U*s){jOxkX0<1Y)MO~SCA>^#G zoDa4u;VUA&7G>0pzvNJlo0c7IR6Pnk$z#Fi6gqmk{)Z+{hazoR;K{0A(`Rj zbv;9O4JsheJ(>|3APNv82#*jl2RbVi1 zL`+10ZRB0~GGI0wS*zX>adCZswa#B9S!y-AF%~^;QRENYr=_K+a|D4}5|dMF)XK{^ zauTZOhcJWd8+|1<=Br9S$_@hljgup)fz3lY#4vp+M@%{hlSUj0w9!(#$Y2oj8HR8q z(=8FH8N_|}*;D(E0V^14q?ZdY_g}IqFWE{As*)#j!;y}4a=1$8UGSEcXr9<2`z~l1 z*Wq)^V-4%RQt<zu|R**Kell z^X=>gnxqFzJ_nT@B64WPbcho}SC@+DIN)`<;{Vw2X`o^lraLd*gAVJe6if)8NN*S?5B7PGbssIMebatXqX0`nyqvZKQcPIaP!= z^^Z3z1(hr;?SRDVACZhd9SX0E2h!uW4RBqBl>2ngaUFD;^4qzIuHx^yaKgh_8(5R4zF7&1}$2s;zi)Di3bV((GQZbbhGL>)NE4io|~fZ2O6vl*+; z&$R1A@TC^TWdkgB{Q$X*)yx1z4IVO=n4=~J=Dkn}DPtuCsm4CN+x%;d7r$z#8*cP$ zUj2AMa36Gjg&~DQ0UX&;%>M_c9A0sjJAPI$D_N9$CF(vkv07~V@@8Pm?H?Q*a6aA7 z^sd7s)<*vSf^d~1RAenkZ4&Tg0_W3a;-f>YgOpUX+Pe?2R}0S12|O7Rq;q}3?q2{Z z=-cZZ&v{u7IflJ3RCoRc3YEV1&bOx4pSs?fAVKpVPA;bA7uUwcc+pESUPgeFa4vmX z**z|g$Ws5$O2kZw*W)Vuzl&|r_73gX8W?-&gfJ=0=u12K( z$U6!?lD|5|C=uZXI^P=ja0_1=@h?$x;I3suRsqPO`+?wzSlU;F#Ui3V&X*YylZea>$d2fSJ`%nkkhXtN2CS^u_!!qn zs6D5|S`5gg>{l;-v=hp#+_Ug|5w$cuU!b8ki>{kKu(l{ELl{6DP&c-?8Sj2N`nRSO z3wl=H#gbxK^?7W6(dzwLcCR*$o8EA0hp1T=3|#7gk@tHlq!+qm5G)xs=?QY0)Q#NR znvfN1x8@q_WR}C;m~F@TR(O|p+Nl7=%>X_8vcXuL4w3CygQf5+Mor(Fp^QsmA~v0b zb^8;@y&H5cG96fG;ZT#DfFT{9J%bTN$-@Z*Bq#s(N)mvuyt*VW;RBveNibim47vgQ ziZ=k;k~1m7J6?pAt4L4ADf?V~B-I9d+CYRzP#W8%Ct0I57a>jvKGhYhi3AnU&fD0h zX4e1j(5rHA{cx?l>@JT~L>^iowh>M%W^AC;-=kLz2b~oAe*Urb2S)BP(7SUK&WZn1 z_$pily}R@JAUi$)@Iy(*fotV1*J6LjI@Tr$=#-?dehgr58SVcb!XqW>ol*3^MD*}} z_lTvqe6cm(Zhz)bpaHxddo*Or3pnCV*rY!YpJ-3g{R?g7%7p^VMV5DEM~80TBSA*h ze66h#*yfPNEQ<4Xoy+_614STPVtoK)*+ltYZcX`TvkOn@{>R-f0RUUu+JcNu zh~f5U?SAZnF~=A00AX0t7o}{jp=)*CugZ$Nt+r(2dKE#)TiPORZ?p{mElWY9eVoH( zYUx~V`*EklANVNA#XYNQ7?pGhfza!r)O#erKLMtOAOmzn;T`~#3Z^$JzcZYh%>lZC zXVU&G2(^+)NRRf$W|;;vMM?NAO^6Z}@QCrT3x`Z6Ka}q);q{?|D1J~cy#&GwQuV}d zTJjSJ#Z;98>jM{^cE+qUBv=L~=2FZ9z>!G)_9DjfH+b^TT1=po2oqe*$iGsUAxTgUq75jB&hX^sw8nke{iy|3`?K#yAHg+P0IyUU1X zSYuZMe%h_EnMyf8rk!5xc0F)9dKWhQv(AceEq4K3U%%NwePh0`{^L`7fafQ~;dYz= zv1ma}$oh!M?lnOu@%G?n3;19PMA-jM@kv2sd;jZ*C&h)jx z!Q#iiN1np72W2<@riHa{cK!l#Ud;ak$Z=WiMG3xg<3G=&k)?T7Tjo4n%Hr|#` z4l|+}Z=xA4rYCI#YUumuz3MuC@9DO4i$6P7^7PRs@rYcqtHE@L#48DC2AwBn4X+au zXooA+kvVYDHaHM_K%{X}3~vdkaVu~l!H({BEhk{I>2$=2MG5ekDqZe+m?Ah*jsY)V z_{oF&*#?bA(Qo{h|3W(}@YWr&k3siw=f^J%HI+QDs@8pnT8kK5PT)I$a8b{6!!R&# zLNmQ_Dzo3%Yz+TE5fT<=v!`>tUD5>%Ob)IutFZ_v;5_kLBhv<_52SIDdjDZk-r8tvk?$D9RlgVUwofTQKSsKTWKa z78=$voP@3CxSk&gTR0!}=xJHrIRkmtn|Yp6Zbi6uLU~g6qEb(RmM;QS6OxV#@H89$ z3!X-W=0EZ@*del)Zyv84xZMb^M+cNQcI)JL|oSjV=*<$9m7=Fg%M zK!8j6hFaJY46F;8phGfibd^Sf?xWZ)OsXIBFEqz{s!MT!Tx47VxG-&ozxfF?dfNl^ zZ5B26t6(KJx7u9wDiJ4fT0ErSyP?yM6f10HRnl*T(eZ~~=P-czeuQ8Dk+81JV* zM1oXA`qQrQj5HuB%a2%V{;4sOJvd@iu5FniI_O>{ch~LK2v${rK$q62_1Bc10O!5$ zhr<+n4_G9qrt-#n2J(aFJl^qGoeHN2i{^8m959&RC8499?B;Y(4z-)}eG)lP=6wb8 zjoF5_WylP^AloJ*Ul7>!f!+zdn*H{30mEteYPvf&A)D+ocK$*F_qjt4MyYy9S;^<~ z@S2`3BeX*W1AWClYwTR3)E_%q9MulVJ-l;RPtVRC33*+|NE zgrBQ*jD=w2C^dPM8;m)L-06mH{If1L>ggV9)ODl~Fs?C|idcl2%U;RmM-||D#%^j= zsl!X9l)6q;5htK6jF8Cwqyvq@b-U4UiW53ezcidvS&O-;>!UR{Tfa^AA#-%M$R$o& zG-1Gk>@PKwh%p2eRjphI@kAznK3Y@Wb}`PTp0#W5khF$iW_|U2V#2cYcsM5&rPiO9 z@7?o=khfzxP8CB#vh)k;HWuKnRtaSw-}xbNM=BDpoBjS=SfoGnU)@qSsBf-Z*?eLubBaoxSPGB~{wF2;*2-KN%77jZ%{NrHweuJDM8rXiRTj$f!KZhZN_&bZ5doKT*fk_$UoXrcyoiQ(pQ=dP_zE@Hw(1m! z6v830-vaAX2Y_{AVJglc=1m7wwVex-7rKVXK-Wv^hnuL4ySPw!G+ZWc>|i#TBIa>S zIom|ixm3I!c6RxC%)WpZ5FP;uTn#Ht?ABkaA0P&^wF%apr8!QSF|O7ib^BYM z4C(USOaLX>F7W@c6LfL%B~*bS+VSCe5?cV=nOcqm(K`^TgI9s2N1X(Y6)f;=bUvh#cl<8 zvkJ<7)GH^sAC*g*HYmktfzCe_Kp(+@v9Xf>*aZMzq4uxB1l&odzC=1TRSAp^8twud#bVOdC}Ui=H$#u#6rFC?Me4aTDhkdOH_A z$qV{QFb%T;1fb)&%lVocZdXULp$HJ?@b|`(XJtS`>#42+a1ShL7vt^?F$$ZSVc1Bo z54Z@zn9esRC23iNV)RdT=6GU@ePAL68nt8+l^Kz4ZvpQWE>*Dq zBfIC{;FBy(!#r-UN-lAdVa8~-{}mz9F33gK-bnDf5Pu+NB0|@DLGK_#!Ng&K#k7N} zZ#bH2R4f~IT|JVXNuU|G-QYGw&78RIAonL@k%X@39D`pbT9dU{6wU1NZ|P zBnJbo^`Iy`mOlyW%|D zszJqcM-uWdUf{2-dA32`(vXV%8B-6k*gZf_8>7QVZ*e6lg93@o1G*%H+p`0_5z9ki zz+vy8KqO$g?!7433`X^c`5s|H8dJ)s-j({G4j_+j6Yv3fmRCJT#Ak=UWTrw_^*gZ4 z>VH~i_Ht*#y#Go@xptb#^L}HIbW}0&r@ATGtPMGUk^TzC5q=I_d@B)?YSI0|aHV;@ z!S3njdpf|pzm1OjbqlLsmYEWp>73YbzA=3xH73?cuGe2yD`1}fjrTXy(2-;f&qc`s zM#H};d_X_WRH_l?>OOFFsME(R*uRl33417Wc1lt;_|#MbiJ zr2pAJ4|PTjmf1VH-N29p-1FXs$M5S8jjCm7!#eadl|6A7Rf!O3+*A>lNlnZ-k4G|V zv&+LxNUov?FnLLt4^ClP5#Gn7hkS0YdkD%F^cv9JUsx+)cUm{RL0dmZcWN5czyWrj z5fNEx`YLA$*0HtC5KHGKUb{&?XXuh_uZakRoL%@ldtYDuwQ1MKZUCqbo^j(9{5#a_k{y5y*cf*AHNV$#k!sJ zw4EUGMSXh$ahg*J63XGj<>%KbKANdzutirE=#r#fSx)UuoDe`rD`h!&ar9f)=mWX4W*`CjR{;2`U_z(+2sX{iBr{YD4{(?7euW-HqZUdVX;l___psPV|{ zyveeycNIi`;vkv4bw(9Lci-1P0q;zUBZotiwB==yLN*sEG7}>CV-*M zqpGj?5l@_lMphHT^XVb{f?B?=V0zb88;z#`bGv(h5Q(8=DHW95#Ne#}{k~-H=b9`* z7g!$89CNwio6J@)cuoF%>NlqFCOw9M3`5Q9RgvqjuLbm{8|_4)XBOKG_b3LS28RM_ zuo+6i3v?N%7jOchUIssvgmK|_i~o8JvzYq<@qFP@(-Vf-hxPRjLf2yL0*rTOKYqx% zU$qD1n-qXU2>b;A>c|J64q8OO3H$d`M*!|WkjoLhi4!>D9s+s3DIQ?EtMn5TB(8_A zL+kgw0oI|_sLJr?RNFp#GE(Wg2X;tM&=1`^`CT+=TfGfswN{H?3TuXIVBsJSQFD^| zOd#c^_;e)FVc^&I63m%X%Jnxe5&p2}Wt=MBUVMt0#z^K2sc#l$jUJVv%u&BsPBceH z@F)JM?H)Hpql{Q;ASo;k4D%^=0=tt&0-rmUrK3nsWXkjeB#T;F<*uui(Q)x~X!D5mCgxKPo~gY*pjc5aL7!}l!P3g2dbo2iB)mIX*clTPVlvLd4+-3ZV#zOp?C zz3B!Mnt}%0k(+amS_#X%(kN)5z2HNsrCgcjOX>v79M zQ-Cw!xEg66UL*HHGo$fn$Y*CzBEl6h>rN|Ao5at;n6OsP7m>U&**l3XKl9!asLv3(DJOpjROd4)Dnfaky zz}hm3FxAQ#R4OC8XXO?RSJ>&eY^WCePQ)&5pktGS*5|BCLPOcj3tz^#$xUl05o|bT z7cPgDHXe8510t^L*O0VwgJKp%xlRNE#{GAaOfh@!Bu%L!{NJ+3WQrJMWHiXpl?uA~sPxqwykz>Xf>WaU8Y*`_;~4312NM7^Vg#Tmu5S2XuQ% zTJ_rXTMkO-SF?FCMVU3&ghSsu;4ByMsJ2fSbep!kI6>*i+5H1M{ z>w}LYeBJ%E^Q>VfLkc)3G>*9PLqO1im#)Rr%_?8?%e=|biBiF?5(GO{E^Y@ky4FI zc8^Vk%H71ppTAK7MAnD7Xhdq4dYw{OQFC}5q-K`SPmUeKl9)t;7src1Vjc} z^BkMhH5G%bVI7$v_Dsk@u1ha=a3DR=fo9)xXmvW+)ajCbtizN z*OH;kZGEj)hT9`F zySpH1A3E)ld+2UMsUh(_BKoODMCwblI1rr#)lVHK?vzAM+lc}up2>{9A|W&A7`|21 zw@B-r)&&}3G{sSwKjvqG0N$Uy#eepc{k5BHE%ai5e529tK6gI&H+ziX+ZKlzmGMrs zTt(+cS>Lf`VER!xIBHj06;~fotpBwOtgd<{bde_ZS+G~tFiQVECqWpqRIuno<76Ry zxkB4%SZTNiHEc1@$Orb#Ygxi=*~Egjw`jxz%{3+7oM;$5{-}-O&_za8oVg)f*(`B6Aj}?g>N}rA9$X%q!mlVKwow zlcc9_VpnYujC&gd&Ayn{6X<--sU7Da1d~q|V?5~fWMdoQgJLMGK+`WHnrZ#e19K9t zRD=TNU`Ec4C{yp=%LP5Kb9cc-YBI^su}aoA=WfrqZS+X?7K9!q_+_47Ny(svSwR_+ zAs!ulxa~$BZ@M>zLP`Wh*ALbty%3-}MOxAhD-$;tlhwDIRU|y|RGJ}91y)J|9zJ0Dy!`?z;5RpH()Dd-7d@@^vH3hZCljc zwxb6hPM7o*M1X`QmpZ=tSGQMj(}Uv)Q=EN##muLM5qHj#tU|cu1AEEt$(@wIfv7ED z7=JL2F%XHT1mAnDB=~wP5sy0(kaE;y|Fe*BawFf$>y9+yl zZNOw|h#@s!aRvYtCZ`K@ zoIzU%Y|U7QAis7z&x^TsnA@2GMG=p*dy;IsTAGtw9@~}{^%W@w*|2|WRavt~dJ?ap zZkXX|BVXN3O9t$hOAG1$ZWIXjPE44+H5MLlNphOjV=~`0_NtQIyiYi>p1g)Hln!%F zRKW4a?M)d^cp{gXyI#aq@Pcezd$2Z#@c8-eZL#j>oHJ{&BwWC_cTHgt-AX=d8UN1B zRaj6E1gt53%7F9=AR{G?w-Qh15%(;YmUHf$&%J*R@;@%B(v4Qonvy@N%2I$Tg>oj+ z@@^sar&Xn$N&SIaetQ2CZV`JHSqp5->3z+XK}nUPTKFi2NZYtv5Jcr%Ow@6&JnI>< zU?Y(#u1^&92@$**;;LY!TUsA%E9GWJp@T&Eh9>xt@UYQ7wD{=TjEZ*20D29-r8w#S z!}=!wX+Y@lCUP0X0*Xqboru=I`7iq-1mGVPQ>TF3bFnBkH>haQtTe*oyu(xY3)Y z_4k&Uwg%GW;=8#%2TSH)X3WLmccCuBsX?;zwdsDZ2vPmsD-HjUr`mt*{{RVT6%V%^ zMfM@q)=$LZZ%O;8<^Xgw)Xfq z`UjeGAFdB!B71%RIip^h4Q}kMGPJVP;qN!z50*jQXptc|BSmy2^x{#n?*_B>10On03x8D>|CZX;vRzp3%SPeY`{WBr?{!2|-Nc&%WCkfE z8T1fpbUd#;c@dUIbT$m)ikshM#WfLA6r5XiZj;8^T8ST#=o;M<muD3BQuDKfb`E^Id(06A1 zBP1@CjHX{#F=1~mqJ?4Nf;U$_C*;UQE&-5ANQ0>_ux@{}R!DJ*C`I3t+y6T8>Z`{S z?NvR$ViF8I0t01OK@%-Q1z4;O1#u4#_;j@Bvk^9QZbWqOz9<4B9`Lizh_qEpBZFl6 zRQJp^FhR-!84`$!%!FT-lMPEz}X=HwZ)2I{9(y z8E_sVQJCm{ik}`6$nQGG7A2Z3)v`2ph5mc2p5S3fc5Vp|O>ufisyxFFqV=wR#$he9tp)r4NBAH)>TpQA(i3S0h`LCL&E$ zLp+GX6LNDs=(&Y3?Dtr8e7a6W2m#&JpQhEGfu)odd^+jv=4*Ow&dd+MT6^H#1*)$T`kpSJr6 zW1Rc$o=nhG^1AKq=sY9gX#k#9Nm}dbVLA%yPOaH*8voH z@F`;WLGgq`4u_HZC?Ldt4%z1&$uY5isnv`l;P@-y2c~xGK81-_$ZuWDx81-xrr6W8OdjA!!BU&PYL zF(56M>Tv@NiSA%rl#l8uaoJ+3nC~1CQe`jQb0fZ*f9XCqskz2o8b-`Gtbb9`O5|jK zjN`bFQ5JcpRKwm%>cqy_%CT>~*!yP2_AYmMy6%_0ImT=05cvD2MbN7n%;%^-86J;(%LnYOBrHQ|1-*nM#y?#RRfzJ`l@oZ=RgG<-&ZMzA% z(0f*fh0`hTwp--z=}*-rzFEC*Svl;+{$?XQ!pZDz9pZ6@VmQTiR8b2UGD(`R0;DY&T$3yAncY&=G(rZF%y9H@!uiqOe zK|h-}l8;rEdb=;zEd;d6!}e8KUzv3!>A=$FAWSTv}sYx>uwWbum8Ya_{ zuQD3gR{8DuZ@uY;Dn*n*wVJnTe1689;#5vb$aDPbE2=UE$ z_Wz*lEu*sTy0vfVk}d)14newGkPhia5E1F_mQImQDJcm7$&&_2Ns;dE?l_-?*L6R8 zKlgR-ckFizKkz|^ga2AWf@kQIQJlV(G@mFuXLC z7L}%zkMGeR=^Bp~y-=AAa?=^rs2gHSj3Nvp|1y|&M)K5Rmn@85>E@g? z&YJ7Jc2cpF=Es^7q^y14{UF}3j>5wyMx+;!j`&FvNiQY?6!lzsDhuChgh|rW$?qmC zk*~~u?9yP;$|Hmx0kpTUUxO zmp3Ho)J=Nlep0saob=;a$lP>bdnaN`WA)h(T(!lFp^i|6>&s&G?61}QUag&sCy_r5 z2Y09H@yCllI;(w@B(V#HQ`#-{+o|C7J0ZkjSZ|<*)nO1hRb0vKRvKAONPD9i@;j=~ zK2Wzfb;fr76e??VU9|z@lCjX}sRw4R|N7-L?RuEZ9_?TzkESZAHHDG&HA}>jh!#y5 zK`IKWL3=Hb{o=ZX2G;?X`?S8V$6#_+%CDn6SrBeHF+ z#F7dUy|f+?5O7|Hu#|vi7;Z~_y?YGzyLA>_<{-vO6|c<}l!T4)1rDzeWc-S~20>`W zXf~IoRb~jhV0-jxr&)VTGnmAu-1mOUTHR5!yy=cIL-YWP6vDHAfQP+wIb+U-06r0J zR-3Mxl<_%p@ND*Eh)Z6-UUYcG~2N7}GWVpK-D>u_wlf!>En_Qs(du70y z%BdaNe5IPmYdz|Bf8dX8vm-!Qhl^v^q}+U&c)sTvN^7$}qT|M({mj;Op@w#j(<^i& zeo6wCn{MB@eTMB-(W^|9!bq4Dt3pCl7gUr{>HtP+p-|YBI7SK)+j$R#AIoV!#bp-L zcEWY8o`Ia|)@6&`9_?XU!Mt($YhM`?!JN(77Q|8raQWp(gpXu*J`R^X-ZiK*^Yi*j zjf_%_fPWw&6-R!&#%FZWfBe`!=jgHst@3TIfDW%fHJx#QpYlVbqEEvA#6$r1Ks9PB$Os#Sj+;&^@c=|jq~auu}q;Aic2Dx*}Fm zc}}3_v%q(%D3<#Jj&ql`W%Pv88@DF5&`(S0rwbp7cghzyeNyC^wFG@;#A)UG6whbt zS|$umkyu{&PqQ|8p+bVC5 zm87wZi4JB)Y0sZH%{evG;L9m+p2^F7xkCe~v&FT80r)|6!0x;%W zvwd90nUnAh)x!I*UVPPPpwwofvg*EzhL+ghLeZf!T@!Bmu0sU0_mUuhL3Jz#etCe) zOnd05aKIyEzemV!F@7HR;LTjmNVHe|AUQ1YCq(_X2)2k$34>{`yvwcIK%G%T-XvYX zX80+$O#KT3cZq7e2M>B4;zub*Zd`BENq5Of1Id;F14amvejM8gIi#^gbx%Ki@=fN! zNCUH?I4y7%}v6c9cfbpeSc*Y#Xz18`W>vlPTgz?@ar$Nf6iZBSnnphQN znJLGPI5>r4w-A4U_ihUc7sm)8UW>z+5XK?PHd#!fqr)aRv&?&T?{g0R!QzB|wU)G* z9VsV9cAaoazLOdlgZw0z8h53aF&T-DWcxHvmnyIak|h-ioeB_FrF0{I%G^z3yuihk(pX+ z%66n*vHRCUnNhhKmb_Sv7g}2*A^X`sqHK^~^7&4Me?RTF3TX{3*Wy*zP86iO*1 ztmEP$_H^CU(q6#M3u(_Z}7thtH>=X}lSY3#_zYnPdvBy2vwvtYa%`D*_KCOBaEj>%cjDk}G=UjO?F!(D+Q4 zsR)yIGSA103_fj#9aZBVuw2eb8IHo*yNSD#eATHEK;QP2FH5_!zqVR-rA<#o;hAgT zYtJYS<`Y`UJMhi1Tox`UQO|jUQcQatT}C7|UZVBWp{IRZSaZE-!v`dZnu8MyHvzF? zHwb?x&;abzQ#8bNHs|z8G9K*@x>#vFR#{>5aL3vJlH8^txms$hCrx5O052&!fq~6DFOk3a2a=vH~}}Uv~2qK z&P~bPwjPv20^O}|(FXg~=Rh?X{}1wE99%G>h2}|IJROfG3j8L@u04g@xl5Ir}ccNtSF;$YX3L6&Ao-X7Jt9Iq)gT@EVFAcMhCldv7nz$`ik=?|FH=abcMwm_ zFRn?P&0tzc$sp?_O(DR(b%DTYj#pW7pk!^@BLhl z?@S!=;uC`@!j60wEBn_gLoL~NNEoW956ZDMRr~6*jzGJe<6j@M_X-SO`C8)x^By#9Nos zOu_HVJAq$y{C^8v0xX7Ii2&gn)4UClpzTaS57k(#Pt^E6u($;S+(Pi%NL+4JJ}a6b z-F4@s#9dzviQotiIYL)dA-|Ca$5HKI}cY^jd8PiOf_@4AH~lLHhkXdHaNW%f83&Hhmm`|*dtgJbhxXH73Z;E zt0sd*N-U;I*|n)+g4jh*4ZEbV$i~DZ zf#&pXEIG##SQNK=T79(>MY-b0Q5OT7@sA(>j8eEx1Uod z)7f;WF4%C`jFdiFS3C*jZNFNY`s75*tzk3hco~z9BkGlfRRGi8DajuqaM;->qhy^U z&-Vb^gF6JuLs%9NQBXwgmi49^p|Ox4-gRR#(tPau!IV~v$zY)^~4xXuuogZOG5aA`xK2z$dWC;?BE|jasV0}(?;8o;HQOkwrmZ{`&iR8S32@0XzI%q zJ3;8dg!9P0C^UL5{^+mQ$nBWv!#TJI=Ax$M*Yo`;I~bi+pGq=BvGsFGIC1U zfgz?_%lR}*2BmeIYynJKEcBAe^_Fzhl95MPF-JH@ZXFVVMZh6c*Y#?YyRN$;MfB8) z3=^hSzTl*OoB!&z>xF>FZS_;-7j93+!=mF?Uaj4F%hsKm4@Gu$3da68vmC`=Ld`56 zN^hj-Hp=y&4P-ZV?&;z zb!`cYXD&jvjwP+L>Jzzfh;zy|%9o>kKT}Nf%-~yeB8%R$g9phC{eGw=m4)|m=U16* zEynI%<=Nw-M)!4(%Vrtu%EO=yGFP1;gY~cc5s~&zJEQ(KhcsV%gztLv ze4hVRcVKi>`yVD9hcK(yJ1^gnyf3%viU z2uc1Ta`MUrvTB4qUo$iGMjV>8B3=$5l%|g75>P304!DLc6Cdzn?w z_|(|U$Qmi9()9~gTgtjFaCcf8Y`}sY*wW!(*0H5O>#nmFrIndmxug@sv3*a?-n|v* z>r2a)Tdc+1F0-m7Q(@7MaedxMR5>RYjDeL+K3&9WeWN*a2gI5jNjL_kyeFh`1D}&= zhB}>VV3=1)B|+S$_)l@aS8U|zLlN!gR|*egV^G={AX*B9#I_O-ZX&?5JnS8*&m&Pr zIR8zie-Q_55Dned`k6st zcEY4!7jB8eGgxqAkW#i?EbkD6*&_@1t5pa6?*gbR+NWqn5L}@=} z?uEoiYWEWMj_6*yrC`Z5dr5`U{&E}FA3rPN+z1Q8VcMl?bOAX*EDkGe3DYl`^l9@L zbfzr{*!>XRUx8h3?~EqysW1q$aXdK}C2@B%{5MElDci7~K99HwKI3^o1RRiy%1wVW zz+whUSzR*+BfT^vJfBWZO=Lwt=!!rJRlI#+y1VQATC6-x{X!x#R!63lC9!-;qNr%= zm3k|FM~6f{Ju(4Rg|P{cm0xkSo4^{9WRiP6S^V|YeotXJgdc4}ZU|YQj@PV1ek|b^ z*Vd8PdYF4;-5miDYhXD)dkj%aSx;wnB%ezAJoP1So1<0^E~gJ}wBg;!7z<@vyhYW! zxq~#?&gP~@HK>TN5Td}z1VXjbm99>U=S13OjowW|(*j+CxlcX(pU zytdArHQAzPW#hQ42qpK`VLE|>4Idf4H&|O2PRb8c+>`2uQVtpDOB0>s?2>4U=9SGj$P)6-#^T89Z2&5bkBSAzyzRt3K81J$)@R7 z-m^xRgIu=znrkOGokpM&YBikvBpXy)GQ0B>@I8kIbiB=&S z-4jm@JNdWfaojL$A-7M3FWS>8bq#~yQIc@By0@wJQb3vSGbLb3+dqxQ1azsB-3c9_>*4qEiF z$#;f%h7bnd+7J)nmL2m)!rHc!9m)~;FCP)mKi-;18X0am?ptP6zDzHJ7BMYoIqI5lGnURWC^ zpg9G*`l(*biZ3iUeN@1OcTj^<3+)=ds!^M0M#_Kj zyM)w3zvG*{-g+t#&|dlK2|cpg3m^i=JkQ2KUJZMQD=-H%5mAjo=>D*snOEg(9?fm8 ztCNhnm80M6e*>?mm`rD6)2*Hl-$x}Kbpw6pqw5*F(%DYCU$k|aN{0vcsxYMY=Q5m# z_uvxt<*Eq%ciEvmA*Z27DI2%h+jc%ayiwz_7hlkGiwsJF2My{Wnk0MKl=-2&iw3l7 z=wgJjn-T%hd+-qr+#GWa*B5)$7p?5|?t^KYgJD7N5ZM`sEa`h{2%6n!5d1E?zcBr# z#r8lx#~Z&B6yLJk@}H%50%}(d(R>H*eJH7R+YhsONq(+PP>ZJ`mp+$uOIzfs_9etN z7a4e`N5q0?ton#v!~Ehtx7wv6i$nP$or1H>_qP7#`CYSn5~L59(Y6!hdk|z4k-r#? z;0v_%A35nWA*Z=6*1A24p32&ED7Nry>+K{kwO2E@`PIfFs8hGNG0}O5XO-bGZOYZE1(M(ye=;fonYnotb%&xNrjP7LgUCUIrD9JaoDfB>*w z`(JDYU?%NwXpe#W?;JlFdi zzTSN-qD}hsdVO~+1`@+m8jS1jtrZ4xRfC=DCuhLy8dflW^; zc;S?;rnuf-+%G7k(9hJ@TUr+D%vC*EQS&iW=uIkDiAP=jmk`~R`O)UOUcveh z9Bae585Q-_C@d`f829Id7^TnOyZuf+>?8RAfQb@C7g`#-bBeaRE&97sES#tKJH2KUll-3h32+#-auG3ZqC&3V4GO{z^fOS7A*%Q9P+lBswz^?n+ln+DBZ zDT7@GSY(o{B){6_LPi&|JVL3c`iR~4BZ*oD@)JsYle)Y-d<&5^V$}dr@a&FbhEm0S z^M2_U#Ns^QbJBua7T+yw)+N-gy@a3JHXbNFb;kel90mRzw9@(gRaVmD(toMbgjo4u zw`Q9JA-lI+%gD;&dy&3YQ#ZVOkQ}Km%#Oa~^p)O%T=NfQ)eI=B;YpBQKENFRO*_WI zNq&s?)BjJ+J1O^9ZDP#)$anjx1gx*F^}skLa0?faA|e^5rCV7j{WY@DCk;fi=*%%; z`SVA!+c+Nk71shYxs(2sKMGQX3G`(d&W+NXx)T(tb9bz$VWlSKZxU|W409rdX^`%# z6^UEg>#N!X4na`~*t-|^t@ETsuY%Hf1?tuQ3$r>oT>U=p0*&AhAoDB_`_+KbGge99uFZV9~yWv6kTi*Zzj_ zpIZJu)&pc`zs)MXI3lBbU5YdmYo!9Yoi;r2+$Akc)d%>j0r~tZJ&xnf3f~ejj~rY3 znEknLH(1t_keS>D{V;?3svTdY2Kk$sXCx|cOQXJ{zpg4H4Ngx`JQH}VrW6HTNON!` zfZvWqS|wk6oh#vR3hu9p9wbco^=?IZy6J#n>orxnZD^RVVnm{C{M6NzB46!J z%*0z{lw>_!UE(J8d+G+aqqxq?U#7W*nS8HYM!i3sUAP~r51+Brl7OA>@xAY=&42FS zh4}zZq2_}MWVB9;zNf~iO~OV92l(uTFqPUXa~GmXNx-xn^<3#LqMB(Qf8d~Mp84lL z6k|)l|Er9eLYOLQcjvlT+gV? z8y;Jz^-1|nV4;u31?##qai7$K{KJSd+#jFe#ou-KKQL5o=hO!{WT-FFm`Fw46A4(H zt>`ee7J{hyf{UnDJeQ6|LnV>y`VPK)Lse^ijm`)0cWj{JL1K+~j+ibNW`_pRsdJd) znfBdut0_CzNQO1QS^`H)IR3-&=;FZ4_}Nmf1YhMe<dEM{tBrXmA3;Ob ze#luO#BxbmXp9qM{gxh3D$%8=MOn-yY#KTPIszQK_uA!%&Q>!orprW}+F&B!)kl># zk;2g3qt6T|sq|4{)Jg9Ld+OvCZuyko9)+D|ODME{8_*DN7l>YGH7sYXLPmL2mNz|=O`@~DP)UUYm+Zt_j;qx=s&0<}l~p4S<7sq0zGZFSdWJBQ-P`v3 zH>pQE4qID(lEjB!`00&sa8CC}5{tD;88-5L3uEzjqXL><@f94rWyxdK8tvh~4Jz)= zM5@`H1gUYK+KpyZo_65G=?ziDn}k06{t-Vz-lFYeL1F4ZI%U0gb?zat6u6oCMyoV5 zd@i@}q(Zw`)?AjOv3&{8R%$Tk&U{@A5x)#xCj9>D=oY^T+}A_t;Th|+L4;ki#VK}M ztPrE6PD*SEiGYlf-W~FSp)cQecx7)u@%!qcEX7xz)wUsXOG)N48d2ZN_}rv!5k=D< zQ3dhLT6u??O|Cysjv_ivBBmq)_#K0cUx!In9CqeX7l}7bPbs$TnEj!D%X3+=NFP*j zxc^190{qe%*u#QB0IwE||Iokl1DUK(MNe{$HT(b`&LNFqszXrC)AQX^vyx4d)AhqR zvLWv|azTrUX6nlO3O!GiP_asA!8A~dV>i>N1=@x)bAV=e9ct+JwGfj3eN(F%iBO*Iy`Q^MY1@AXzyqH5)# zdMoUQziFw$yh#?J|Cg3h7is@CqB{xlfgc(Fjh6bRs@sYDy3J1g32Y6&KD_NMCm}83 zlqW^-q#j&BsKe_@bOO>ty5}KZwZHo`vaG0WvAj@S!t~Lrj#kRxXY1b{FH`zSJdxNU zY1qOa@mub7I13*6wXMY3(u^Z4aIQ|r&V?JC^RfeNk%QAcM|k(gExb1bJf8T?dQhua zZ<&$}*V3PDjVt04Er5&kw7q|2%{J;L-rmfoUzpFMP+7`Y$_tKACXZNf8{^D762@e)#`T z%k*Sgu|)somHMlU5$J4JDte6g{wTWK|pG*;V#O@8#6hD?AP}VSb#|pAcI77V4%e?z5VzX8n$1f|j8D zt~~%Zp$?tEVY5iDn?SulGw)*;72<#6mXHZA{%}hXwnHeJX~(8nz5&IW^+zP@niymP za?txz%iOktEH^P^i}%D6ec*8(Lhrjhb!S=IW`Wf9{x|3vIT7f9ObfFi-JB+A)1X|` zfjE7itvH~PK&XEAyXT!CCFRE-O+0ONK7aW)*FU%yZrWZNjeJ|7H_JRhY*A$=k^C<@ zDfPe6Ns!AJ`XaeCl1xG1Mjv_+gbt&e5V9tD2Zw}=q?Jbwj<$>w{fP)Ay)$FvVDSM3 z`kw-Q>g+6lVw|KHQm(|u)54VbJ2RA@E7`eKu~nnPBBZo7--TFAWZr?tnpFkdwoDde3Bl}8LB2||BCWg)Q!~sMO-Km|JF^`X6mJD zn+B6=CH#1?PDYNUwCdTm2IFv^ed9JWoBMW9K!!xXX{d1@GG`ibHA%uKv2ou2QlJ90uRNF_TRTT11F2GJh6Cr}TU zjo$@j`tg2%e{A+|Kvg0Jtmnbm!%DIg*``Zm0jS9 z7Iu#&V40yf5v;Y9^KzIQbGqD=)vbCRa(Qq{BJr32?{A{2@o_?H!4hHltjrN1E~j&c zA)Y|B#S7=$60^P`S((pDCnvuBF~sw{V@+Odl;nJ;aJGFXx^|eUl+gCVO1|lK@UzP)B+Y8K-SHolaWtZ!9UbV`GrCMe=ukkaI<4!+%;V zmT%f_**Q9%wx-QLq`?>PbLL{?+yKe!392)>ZOhC3~i1vMaRg~YKYcY zxE5Uz!S{GKmPmS>l8#oNWpA396OK<6*^v3<{UFGeScE*5)?69+uPR6IK(-?DxnLF< zMf>S+j*jV_%hCvi;^4|Vg|Ck@KBMyEfhQI#1dBGloI=VZ-~klk*t_naj50jRj5Qq#)m3q`P!OjO56n>UC|(p|ZzQ=#-86tDR-1 zllf%ycS{CulP}xYkmwZkDCR^O!bvPlwBDh@qq4w=ICI=>EJSLDl_B<}9hhc%ruVJB zn(V;5zQr*C&_r2kg1gu8vhA{yl+P^OTRVu-k%Vb~O@__Q60FPF)u!Y{I3a1-T)D&3 zJ{0IR#|+PDdpB8g2r)Ore)}a`Rfi@U9%x|*Z0_=wkTGVrb3%fhrv*u#>s5|3ly31E zrN5|(SzGIEJ_aUi2V#T@nn{%rtxsa}`2;r+j`-TzdK&Kp8?E7&tc@Yg9bO0<=P>LNEcaM&l%C`6(1SC=PySJgOo5fq?7$-!h`8oJFvP9UZtw{7X@TFo4Tq$xS^TNX~*((>|g-l z+~UT*d6rLdvD91iqGkPwD*-`Dms%x&+(LnV_*>fJ)+eHC)rN}?-N)?bZc%FC5(6+QY43Rc5$O!2Z)U3({wJ3(7 z@fgNjY|3fa{(gGpe_O!M{KoNV!O{KFUF4Um*Ip~Xg^wG&OQe_En(9;$;o!Z39vqk#M=BK?_dHZvb@Nt$8e{bmP9x3h| zs-jn2sNnG&sy%$`lL&UD*ZGnbU-_hB3CoeZi2V&jDhuF*6PO8E4Qmj>K5-FpW@s-8 z1R|a0=y|yOE|J$G#5qJk7TLW4a$@Q{!p*I}R`zyDpR1lcka$@y9`<1lb@d1Ctx>fcdWib)Si z%@+~<6yt6I8Q8c70)HG$o554A%bSz(eh5!#>PU~L&5(MT=!H4cFl(K)57KC% zxWV@9w`WqCrC$@KEsOu4g6BAg<@4Zt|0el|GYwE03X7MIyM9i+Na7*O`!#veUdyH$ zR=if|ls1jWUcnv2)s(&Zb12>oPTzHJ;z1T2yOp-8ysfrgYkFWlRJ&QPwWVfd>*P+~ zx&3YwsVrfa+J$d05!opi@ zc=}Ctiw#L^1;e%{NyEk5zCC(ZW&Lq&A`v!Ejo6Pw5i2J#eGB1 zxLJ*IjFtqg68c@_PG#j~&KF@9(RESN-!00*BW{-pMpHDo?pT~bh})jIW6Obuuf7e(ASk{}!C{^SXoUx0QNusQrF9FZmal$E+P@cwY`^r*ZBXvCG;81>Vfwvyi9759gmmJy`XI?P9h@Wbtlbo8cYee1?MH< z0x;E%2iPXHn`b#C8~uANKwy5~;__35nt-BPbyW>}x8^H=&z;ufQXwLa`vFh%;KvIM zd!L9#Fe{;HMFE!yw~@ONmGqbt5n`k+kry>Ek7aDS% z)arMA3SNGGm{`fDcgjxZ`sq$#m!Mp(y7ew(Y(5%%SxIK(d)u}{Rr7Z6h+Pyr6PAw) zw&4FZoo&Q?lgNurj%S%!t#SNh=zFu^#H!@xgKaTs4Ob{%;KDy&7C}!|XZz&4)ktR@ zJ+B1p+)8__cvF%2g_5+O3(+4^&!yBa=nh=IlvYj%u=5YZ^#xHb5)|CR;^&sWJgk{D zRts!d8CUf>wC4;2I`u-%JHG;8(`SQA1TFz+3Iv#nOg|6sK18d>xyvasrN1=kKSI@W zHJQaQdf1Jnjc(31S5AUH#ZyqRg5kmR*KhlTw&E%P*YvANO+L4zK4N05cg%iNW9g3i zx_pCISikZNQ^$ ziZ>I%EEI=MRasJ~B)qmsUOz;j@EWDdmx3;c=ckV4a<)j>?bgd~OO&l+c=YY~kn{79 zN)I=;CrwAkjy6G99%-N&$s1};r>T1XLTYr=oQyr(k(y?*+6>A2X6~{30jVUC%ETal z#FNNq$eX`ff*@SnTssfampN4(qQ3+vnFA!6yq$>klgp0*qkziTFRvgSRLsaW0+1`yaDbEu7Hlg{3GJa~+(^ z_Z_l$o895`!(c97LqTC2bsily8H|?1zwG9^GbxeT!;2c!M&)nolg!*w5;O*k3R3mqNWc@19#H4%p0p z#TMq;X5C=2DNkb2Q>R1V52H@A>OcFvS1W;uqv_#|vFnRu6bZ2R{{{G9_Xb zh_`$CXV#J0#HeMF?G@^dqmE_@S^Lk1Zs1-%w6jC5%5Xg4jfWmFP0`XAx3%uUHL7k6 z8}r92&YX|_7R4-lt-7;*RwVUF;5b#1Yaq2Yb(xK>Zztq{^xZGOx)#D3RM>Za-hU;N z-3N%>d$C3Egh;9Wncz=@3I&hHi~P{NFr-3Yv6CrgNoGMVx8b*X{cPXORWhOz+o2_( zvq?T&)WzH+o3&T+Q8k9dCwLmgtCzezJp(_I1y;0lt88+=9>tiG=WmY}zg3&5qEi0w zz>JnQXAWWJv4j>Ei-;gV1sC;uOQNq5OXU?A)^+?+-kreN!jmjL3K#z(m2TMChoso$wHQRT zsI{K*OXV)M{-yOJ-Y7Bjr+7EwM}vQ%3A_;gijWVsLGJ>ZSPu0QdL*Lw*Dpb1di%F6 zw~5%yQ9YO>a6XZjNZ>P*qg5I!KcFzJzS!PQqOz2 zCh_UFcVIp)0253bOO`pH{ZMb^_nf}BB&G~pT%Bf3vv0ORr<@~rQIc~mlR_ekhK`oR zedK%2=C_aod@^~tC+;r9f87OT0aD(QGRD~NoZw)8Kcv`zNb3@Pm=ch+6Rq<=)B2U; zfUgQT;%!v(OhQnDVE#k00oG#MkKfSGEoF^YLwi^ep=xK=Jc@^xHPoQbG!FEc-p$X= zygKU%|IySxVUrKQ*EPE9p2lkxV=+ILu^<@I8J_Imv-dq-^KRxxFpZn*hsaOq{Kp2H zUcS5gkx`iuvQI>Dk}j%FI#??&V|TGvt5WniE+v@9dHvP5Ue^?TccWqc+39l51U4<{ zc{ECKx({`Sj-%NVTyPz4}r{{~m#hVx* z3du79WvKHvhw|b4E)oRZ$K|~G9`G`<^%7`60(Nd3Fdd=`yk0Pg-;sc&9*e>z#!-Ol zY68>62q`sekgI3aYia&&X6k)0f?{u#bvL9CPxH`ur%AQ#s@3G6Lu44*B`z^kaHmM{ zaY9H&=whZpeG~Es_=uk$v0(&jZh|kavYCX1`^Vk@jr)avivMXlV~>Zli`W>V^6yl~ z*avv)53v+0x|z~iG-AjoJRYnxm(EMN0*>baUi`irrNY%or!VX`*hZIkr~=PRNmM@} zevf2l#Dsld<*eZv`fi($Ox~Rx2?2Ctv@Dd4`&!J$ma^OxjZ9FQ~z7xy`CE~`Q(dUR|_+~i>|7A}g zb)jm92NN^sl=#Kvv6A6yek`r>MZtn7z)u)IUC5bk?2hezMYj0WRWKiuT6RRlUp=#; zH1hMF=INKb%vBYkXv-_On`^w43vcdDJ9wjhJ5!2>;dB)N%RDzSDn4FafY4P$?O%>L z_Q^LvP&NWns0oMQ6!g>}#Eu{!Yrh1S=ZvKuh`GK7PRLn-%^-@A^x;Ol`1m zW{v$np%9~icI*dZw*ZC&et;HuNUg=gh+A7kTo%)?TjCV-IQf!+VL^yY)^{h5tfy8&i%RNkSCt>;z@aP?wsd&|BbfT;qDlw`SH8h#6%@%244_(%b8*4 z5CuA6=#l6KxA5t7E~ zRh&r`AL zS5F#Xfv6;yDyQeTEj# z@JW3dPm}o`c;HJK(7p}!sxqr>qAa)pDF2Co0v(-ZFEo3OTC{g;lUT_kTq0H4-KpGR z#z^S7N;tg!Ts+J2M`mT1sGW&C3~L*!o}Z~Lx^=6~G9cF~%ErR^y0AKl_tZVFW21vJ+8*g-A3u09B&zb)7Rf29^DQ5a>t#HR`^Rl9fz$IgsowracVA0k2h5K%k{sS@h=+WAj&kI>9FSeOtDH&2=!UR!-1AY{7*M}Yeyf*uV&q-WfU3| zz|^B(6^7{BlQm)02Hu+ia0DoYPKP}x;9gvGP-J=n*iA<26{ZIuHl>Ra zCm59-CTm(_3-m^$HeLoJA(~T)_a&$|c$^Ujg~p;}=KamQo82uu^2V~Yo9vVZYwIorkkNja37US%0S^$#H-wq~O zFg7H5s*agazPj$NbA2<%l)yY10d?b;NqJ`2kop!{BlEl7^queaH2=v$uFpwImHp}Z zWy~ARj7{RxT6*$d5p&bKI>w;0X?1~3Yk3%jg`tP>r%_${I;%Ea3AgRiYBzt+A zAovEY5A;Ku$l|wmd`!7Qm4JDdPP%1*pCQgb}mpA7J`un2yHZ5qy zv3{mmoNViwJP@wA*?eyNXTWnMTyl|Mc;qi3AtpLvRR0Qrn0KAAmU^Mal=to+joi$A zj1GMhO7>)_hLx~FY-#4;ZI1w$p`3klK(bzQe~qrU2~bfp_eP#)oAcO`bHANgldpCp zfJ7WMfWb`4gn-f379Gnv=zNt5glR&UgiN1hm}0#~&^0@YiXw8m>g%*=7YXtGuL%(t ziaekW0sDRnyDc7@?1jI5FCJEw$?@Znba8M#;1C{T9U_37__CeJ1Op)f1Q-Nov*)aT z&Wu0gKjy^lDPUrA>_cY3@Xu_{3bgSL;SRyqgAvJJ1`1BD;(aRk)$)!u;zB=z1f~< z6aq=f?91k&6G41$XpFDFqRJkI?&Bem$Tqgg9xa7maVlLD`(7&pfrJh^65v&cs#IP zlNJ|kYBXd>7M?lYB$ogRyXb$Ij)wk^iCb=xGOdyd)7X;sjyxmzQAmv3=R!w%5jYzC zs#`qY8BL5WQ7woQN>Vmi&%tPEdC@DcS5>< zZ7HRZooS#;WLEZg|Hf`WRseW`9GyRiLg3!%x6mcv&7*u7a;QU`2!j7cKQsdRklv_e z%G1%tpdkyn23u+3t|*^`g6IBmn&69CUwIHp+2n4_;FC)ccigh7@al~zl#_VHta z#XwaI5!>sQdlx3_xn}vqs+WGXM$iz|iw&Ip58AKW2I?-)DbAzPUY_heJl0rM{7 zObMGoBQYe_B)sd!olhh3F-5M+DM62m(BQRmE@PcKBW0$55)#JKYyhl8Ci3a`GqZ_E zE}6AQ3h_8m!o*ZbRShhMR9ABe_=;pk|LA=C-uACP1L8u^MH)$o7Vd+(?wyX{?6 zAXI76R1gS)fFPpuPLSS<0@6XLQl%4WKtNEMNbg7yQF@UQim3FCbOI{9MX4g~tcaib zeS7b7?mfSM?j2)~Au$7z_g!nv_RMF_wccG)4xN{Yn!9O)83W+Vt6Bcj2>`Gt=(rzaL7F! zRx&-=F&6;)c+rV`*4-h) zLTkc(H4l(OijJo)&>&ivh1f_hgN|R?1bbb|bQ~d-8`W3oQyn|E`MpoyZZtd1rC+Ax z$*S1pEa`o2alC-ujoKF%4`P0Kffz6qtK9+8?0ok$5=1=gY#+Edjb*+|!j<~_aeJ3( zD8D>ghq8Qm_U`?yLj;)IQAtPQGb2dgBkC-X+y~0oF*9*ZMcS~&6ZP1;6zweQ$t>ij zCg3u&!LQW7!9ZlML||`9?+Lu|@W1dz;DSYnyfC4~X;7`LCpwUoeMFT7&M>*@8u5ba zwpc)9hLAKq>AQiLyZN)-n1-?GbUnedM%9lE$xk8Pzyj2_GsuncKzlQJs0jPTBl@fw3(6CXw8hoNDP_}>x}31H2|WxghVAg4nr|1c;JX?TwQWVah77R{Nr=?yTO zCEca^FLF+kmW~i|3L&oOv)sT6W3-Tu>Ld1v8*{2kZZI(z&Q)m7{%nzqq^juxrrg!LE&1~0n*S;Gg75cJWWNW_+CXm zgLCsC*H2XP8v~X^$^A=Q(ifr?Vm=akhJ>B>@6V!o!1o3D!Cev@n#3pY?<6pWBTjc# z-JlAcKX|cA3N9C-nKT8L2e58Rq%!jqmrkuF7EnwKVZsH5Rf1b5o(4#EGLJ1HY-3Dy zDxoP`kKE~ErWmD=#b=5iY1AnQkr*OyCM>f_dZQT&tOggyztniaHy2>smsoECSFp4U zHl)h?DE6Y|R8J5wCjk|NNeV7=&Ef&Rrl}zh?%Vv^*X@s2aljcqh8|txRv0FyT=`KL zH4MA?UAV?r(?zO_4UZnlPpk%cQa2HrDx7GfpA<}NLo?Y)BHDAC8$3sy_{lpDDMg@> zQ%az1uk`=aM++3R>Qi+Urp$1N`2nN}93H+MR^xtVdD~_zo$r@E*4hz#c7N#PHmmQB3yW*iu`~sG{iZmN^*^$m+*PW2q)( zj5$%<<~#ipUYy)6I1#M<_@{rBzg0&<-s6DmTZM2hB91fG&MP25pGf8U0f&n|7{Kl1gYF~H*}RCZNtJ{QcHbMj?4AbRF}2hDvN`#@pBbK z5shzK2B|-~&1l^TC$?(hic{&%bUyoJ1NB_d<6;Fu5$bXe??zxMLDmHb(LZV<7@e6J z`QeD>LjR2;;-=6@C#)aEO+Kk+ox&<6Cum5Ov!J-@ox3(EK*S{F5H?o|dXT&zp%bu7 zQ()nlrbVaaaR1QBXiV;@m*mNb589Qk{KJpdt3XvfnOAHWr&PgHK8~vmF$a&q#r&#f5{rs4mOG+*Zu4X#^iQooOoCs-?&AF; zWBRQ$;B!zN(RF{zY?glamHjG;F}InV)kgSS*{zqiH97Pvo)eJC>OXvbaU+@YW6kt% z?u`Xpj7i~o-oM88x671-fnU>l{)2=6!z6H%Pu-xqT_JX|xhEiiABesrgcpwWmjZ*a zv`GT1X_J&zHvq$C2B-A??HKIe_hawFeA(Iyy!4IM&``nu zBM_ZBDTdPi2v8^!5$X0Dq$J z4}bQ@=ZN^gm#^qEoa|79HPM2x-EKLL{B2wS5M%&R?O83_oCXui`G*hw`@{(B1Ev85 zdk$RG$4=@x{cjNfXVNqhtT9a~Exeo}K+;7>EN(n03$r?^XpkGJ;R*A8zTV9RL+W zU}Ku;AH@T+!)$;dF9`u-`>~(%j~VZQo&l+&^YC$SSQG8#|Lw$X(ESfYj=3e%|3v5h zGA6J*e=AGk{-Jr$W8lf4$He0HfPRUf`iHCet>c+6jPJ;vLx59y`xfyaFEMrCAKQg~ zixPGOFjlmGNO~3cn;g+UV8w4;1``YD!}}kI9NZG7@ITNw7=jfHfQE|<_!_W>@V{>6 zmv;Zx&HN2b{MXHZXB+&VLfe1c%-^;T{NWG(>t;@l1Ur!Q-o;{-jS+A=N9VP)^x@eATJjR)$Opgz zw}i^6A>^=ASeO??+39N)Qez~sMmPvaBozWeil+#_d7V{Ap6u~SDMFdGvV1b)q;|H<)H5kl@u2o`RV6_$qg25pKEDBM)22v*r0KU&&cS@S>>D09`elP-sGyi@BU@0LKIZI#275+Du zK|m}7RoqD+6hd0y=N!u!CvY>TYYG>CNaN=VI6MFUY9a(s81(;c_5P~{7#04n8vNHA z{8tVB8x%01@&BvdV0APq?60!`{$EGB{{{$*X#cNq0^65`4vvkr>|`DsLy)3zZUu69vw&I;Ar8yll9HhR>xZ)|!vmT5)WRNvC4 z&>-izd@~Rh$n*898H7g_05}!Vi%)+eCulrCKc(hck{K}U)~6?kD-r{U0Fe6&Bq1J? zdpf$)d)-lzE-s^@d6-)H;o?~S9#L^`jBq&ktfod{Fl>hiU>js>6-f5t;{X6DL_*$n8T{|O>{Q14dvyqMWB@D- zjrk7)C8GZ3Llib!isEy39Y7Kh{WvxAHhhpOdxUo!YRvO9)a8+A)iwx75 zpEwo^f{hg-pfGI%@aJ9Ce~&+5!GtfzHP{bZtDek(M-|31jllx*J_xowG_q8@HjZ`E z23(Xqf;K}6dKVX5epFhz`L6}Uf?NcDe0b_|Yc*Jl*Z*lf5(7xBGFxbK?ulfz+!3xP zk-qS>BNi5@Rr-|)!lR85ojA|a(|>^8a7qAlOWA&a-2i4Vb_{O*OKh2MAXmS=sJvpV zd)Z>bQQHMM*|53#^c8opjto@FnBKu%U>7sa!@FG!e*nxGut*4Ix&O2T1S-Zls(8nJ zVjrudrRjVOv{8GdN^cHm6*94KRnmd9Jp*It5nVJutIMOva;1NvI zR{44Pnb)=pLTDL|kz(qdbiqHQ{It4hJOa1up0wGU?r(S$Lodn{U(n!ryh}QOV3(07 z>n8Ue?B>zat_Mm%9~>X8K9cv zm*05*wKAs=D%4 zHlBI?EL2U=9h?Y4mbOaX@WTQEprjl(((M0O!{{-L+P8-O2PJ(>`FzN!mTEYKIhg;L zqM*VnF)%wqJIC6Bd90!$*UoTK;B!YBC+@{)sBR?7eoQa8*z9J%)%0&=C4YDoNa^#9 z{~)FJ1h?)9NptY;s}j9ND#yrl?fsvmHn+U1VFo?kDnP%gS_g?Uzy!QVwTtSE7(?-f4e6vNQa5(O{dTB zS?&mnyPAkwHv6xrhBNe*!C8TYNV~+EprM!biapcG&@nA3ywcIuu4Pqz}SIEKAoF=7^mHB00*D$$y10@2Z(*Hs6h$z23Hw{0~ zy2ib}6HCTIKE|{dGs7rL|EVY{_&UZxVYS#n%5DNjvnuBBl=d%A(k2g7e86J}XuwPG z1M<-sOtK9U?O!*4PL7BuQ(Wgh;P@u_Iw&o>Ammm|xxm_!?8>>Zd%($*?~)a)=63uqCwX>s_@qw{MoyW9Ovwhbl$h(^8~8`+-OK1>S_?#dk~WdPplSf{qF` zfwq@{7O0Gf16W~pty#IgBC=$+y`j{iY%hWO`A7YI9m|dZ4SmYfr*%SnhVmSoo(^?- z?C;zTekJA^y9&3f`QWVQ)aB;8J|yy`q?KpPtu{mbY5I2cqq;*q+;=+nwDOR>q*<6#gV6WF>Qau?F^!aA~^W+g>J0myo^_t9;7dp4vU!o4{oTBblY>xX~)x)Vi zh*^@E2=78S6jNS^twjW@x#iRfJ5J46sM?NgIZ8)m9H!{$mPoyzv2O@j+U_z|SNeRX zmyFBSrsqtZs)tFpSntZq{XJ`&-3#GWh6_u=ISg=QRqXdyaS=QAUAo?DoXTTs(~eyc zGJ2-R468LyJ2u*JfOsGXad#v}UG)OrGk4KL{oah|E} zI2Kln*m_LFOhi;6Z*LAM`RhL2@p)8iOt9eurFS; zmqBGe*L3>qxTy-;#Y+|ty4Uh~Bk+mflQiuF;ev<~f!8qIJd)I^Qr_W??e|e>9d$nL zqB|c@ZB^*0k&P>lR&rX^rt4zuS*iplr!1Bf>RM&0^VN1j!jXH0o3X+T$-P!uWV?A~ z`(vNzuF_5FT~?Q0ubYB-rIWeSt=pOl50s+Uccv;BC`rCuEAHWck0&$gl3gFMIvvq) zPjA&twNsyAA=@_k^irD(2TCIM`}p0cGzP(4xK%H`LHsQ{-Ri9U7b9FGuS-S-U5`k{ z4lDPmS1Rj|E$`ST>=jU!G&1u+ua2AdN*d{;k6adCSgX{mrsi@gsqf5OiQ?bGqj;-N zwi$cYvr@frmN!9K4V$n7D^7bp4Q7r!9vv3n>!GgAzMt+YeyIPbFoPfB5sKiWtlo_0ucD%!2~UAO0D+2xe=5^YHS+ zF4-4mBG*H+MMK$0IYkk_h|mC75^#@B-~RGbKL+tcO(*_F!C6;rV_A;i+L!9zTl}pI z8C}o6GFn)!cwvfs8Ncn%eR*FwBGa7z(Tl_~oAb(|H5Nl|FS$plILgr?_DQP?_aMx3 z!^9mn`Es)S_5=0H8mES>G@ChMb=X9?uehWN?%b}?^VyN^)XaU}cN=`ru==^awYIys ze%`=Su8M4-FzX4y&A`tuCX8r_tHIMu+p|q4Ju+O{;DSW8*SS|J*w1~J?ktrOxP;`W zGx?6SYuM*Iu&KtjQfRX)G=4a;=RUxbvy5&N*L`N+>A*W)Xy9iOYrXO))rx-WwVw1L zUA1NMv>W?cjZJUVfZ=CD90R{YI<@UthWy(r!!8Q;TX1W(U7zyJizZXHCVCwXQJS;g zKO?K>$|Eht{AS%(_nyr;7h8$!>`l&uKk2GcDp#+%u)b&Bd%aGj)3o@K#0by6mv7~M z{*vduR=jVYo4ne3C5N+~9!frbuwMO3nnQ1j=Y*=PmyzvMytw0<`!p0xzPDbezcTA5S<}fp2>1DXNFqP4zJ*HX9&TwEDVsp6Bk{OM{DQg; z_C0}iDa6eYm^T0=&42}VNm@Q7{}mf`f8-4@0E3sZ{>0(rW0_8Uc|APUrZqNSjH&t9 zisId}CU;m1k!I9|XZW`eJggV1iwnyw9#-C)5Gw5K9LQv_J^VT^&sp4UlCHDvewUxm zmid0I_-X^N?u8nXg{rUm3kji`vsG@Q?qwv4JH9VWm>m^fuW(2Cx{WXXrMiO}x;}m{F+m|yVfK|$W1=C1g5}K} zVeBOC6WiL1I)CXGblAY;HCyyvpk!bRejZ;?DKe~4VpUJ)*j(U_-dUSS_SY_S@cT4i zm2k7>YTZ;4uT}d?Jr|4iCzl4YWnGr~veJeMZcbdi`nA@)T`Nh@(JyQ-j#D>g_?3ZD zDYZ}CwS7qck{c*pXq{HMavK^OW~#@D~!;0=-ySw4hNy#AE)J0y^|sRMVG`dJNNzZmKE?3t#c-NxdMg$#e~ zJH=|EYmhOo1$yPKD1PR+m9mLM9*Y-Z`>UO-P0c;!#k2}e@6WTf>loOZSp^$U`yb!+ z`W$f_jFM+v9w}xEr5{#ypGL~hUPSML3@rBRAG35O?=wS4Tur@b8-x|uA@YGJ#B|(a zFy6vQ^~f(B7I+}ObG~e0+D}xC0h}dHkvnEvJT?3JbL5l2z(9)5JKYK&YA50F42e*M zV&nbyu&U?2O(`$k`E!TNxmUq!(37_q^lM zA`i~S^9sD-Etbe{tM*)_^@7Xm)jG7~4K%+Q9n}`E{X`WhmqDHTt1E`D6}D`M(!TGA z-`GKU_x5cJu>4HMe+3hEGQ=3J^4xx)-gVuy)jmA&@NuQ`>{0Q6cax`1hXWWoqw*Yv z;BNTFO3>!t{uJhz=doU&yYx}r`}<&l_wL%<*5H1UYxc2L%~b>S5&PvJtm;V~_WpT` zw&)3IGMcwUEYBapB@qxpGWzqs^L`Em3=Y6o|4A#vFt6Z({F`#p5t_Ri<`5mEtfHa8A;CBp@T z9$)YR=b4-{<2;S}XEq#8m8eys;m64?+?5c2ISCe6B-@?qtJxAh8N50zfPjqo6PLS^ zxv~dv7M(K>T&Q!Ok~`Wi9=x$Vr7p2&XbfK>DYw!!ato`l8RS?u&T}@ZWin6)TLWLV zPVDV$M@d?Cl$d#pRa0rH^CxaY8C3xz$R>3-9Z?-aUabs1a>1mFO`41aXH#SmMhmy6KP%+%a#r>!dKVZI+55WetQvOn_bG+8Hrx6 z6yci>|7^zYjXOjt97e^ zZSTy`H*1Qt3w7G#bd4Q{{l{(CI(kIWz!P=d0TbtphVdG?kHPx0 zNGZf|KRR&hC&L1*Il6vl+0U&Jb7eZLXRkz$;dWBc$OhqyQ1izmYw?>I^RO@hTuY%~ zewhp*y8c=hc*8Sd#C_7=w^t1AP>%CvNDyQWitiG0mQJR{bhs_S?ZuJC$l5Yjo3Cz5 zc_~GdzKp`JjFBRXdS)d__M7{76pNvqg(!8X)a;qh;(ru&_t-#E?9zq7c+Sw8JMWZg zzAw{trBB{(jnI0f-;URk;g<|0llb;vF)>^a|6Cs>Dce!QjGcz_L4D5$h^=kX0X*JT%c5lj($k|d%3CEOKuFe*FzIcOJByPOX<$< zS6DNnds11ayVAKyazpsIUr3*ldJzSR)&(>czKTTFz24thj)WIdIi_mu4L;qp9Vt5P zP-J2?KMh|oEikIn2@`Xd1F~PK*xp*JMst)~^~T|zrsgm!d! zf-a13!#ox+Q0<7G`l6BSZOy?d%MFkG%{5)>!$cLoaT5@@aan}vsKBXiAvPlzzwpX3L;{A$Q z&>(=d6{edp)FuW}wIODEC66zXiGA^$Oxb>PmOBQ4<0#W$I2KVMQy=93K%S8prXsJQomXNxb`K9iu6{Hq)e0jc;_69oy)nK6on2x1n6 zZ&*BkPz(Vu6hZws+mX=L9LaUF4ZHHNDlS^3T%};vL__qLL&JRo@|;J?Qpm>oD7n2N z|Ebz-=cU|tNJ3J25!e=-68jS{T&SU@PJE7^7>VG-IMqMY66 z#81u)E$}HK+JHE;+FJX!zqjN{r?~IGy$05AI`1naCiV-(h@3*pos+$(V z?#1r@s%LZUHeJvH%aasq4TYY|2F{1yS6FIxQK70^$7|JOVfuCv-y4sVFgp^` zrg6x2CjiUDGxnNOJwVO^#7{mHj8(s?{AgZuacwD8+T~+>yE83+d;<1SLOFnmaGoQ1@Gr zX5tho8AqX)hYRuAhyNq|S!z zkG?|{{{viMK{n)|DYR68;5r&C^FPKa1J7>FvKgC3s>ObX{ptw2Toju>5 z1VVXH@9>~Kw7K4E(_*pjV=cSq!z`gMW_ugdQuGbq%tAY_)?Fjuu}--b9RP1+n*Ea} zBYzJ4p#bEdzvNlmU9XXsdbYJ^hNf!g;-$3m)z&Dyh1^$#ygr33=toLrCctcYLsLz5Ki9)b)EI{I_7<)7Zzrkt2?q~{c)x7?MN#;b~})ol0M%w z3XGA-bwXFtfXap2i%$WEUvJj3{zUR9@v=7>nZLE>{h)rc2Y=oqmNmlS%giSf0p+#= z3~6#H={IB|hh=6%$_h~EyE0Hjln&{9rTWb)*?H#(KD*JT9D5wudOTcF z7U`GiWOwXi_x_j}GyqmbpaO^*ZhVJBUyv*o-khFB)v@er0 zP%c*~3u#zpUSQ}kr8$ zT73J$qy23(MRi6?0-7eBRgKYd|S<&1(a_aj;pOSRuf(h4ybaFWO(ks}mF$ zZ?dZ#YVUct?V++GgJc+W+X(*^0WoB=dCJMUjJdli$Lp@tvPw;9ncyYV6?4|aN4&xVggIVy z?8V2Q=(ZMc1s5lR<5xz5MMARFxC{iyXxXolaBUjtE(Tqva9QYyJ;Qu-HxT!Z`E`r> z)w0t$Ms)&adUiOnqh0Kd<5l)tXN^6phFLgP8#Dxii`tz)229 zYAYnxien9WM|OSp8O*Tp`0Vq6Llk-HKig(-L!2hw(#Sn6rnoAd;k?4k&co*!HS4vV zxn7%jSy606ECd#hV?Y$c2^ssFo>OAQBJAB-hK+e=yjYZp^Q{?K4ch(|pd+bu@5yn(G@TnD~Y#v3wF(WXR=Ri=^DN~y<4Iyx`^Ag{vm=ob1 zb9?vQr($oM{~2kP1`=MGY5N{e3p{AZdMq*YZ|V#EQhlPoH6G)OEvGi;xuQczR`A`H zmhXFLgq|Dv?*6jf%BXa>+2>ah_5*w&hKMlgR|TrGQ8ZqEMEM_~w~YrY0}mIQuxxck z%kUpxtUvpuV0YgX6Psj>|Nb{DNSR7gz7zr$ct!Lz)!APt??+w^MdSJ`A4=SYP<*qF z`N!W*A+AuK$f%R_>O0wAdHl&>yniel4QAnH|M52%v=bclhzZJNLCW|4F^vu5rhF7S z2o$0J|20LZIwU-BxJ5D6k8G!keMx*B@LsoG>1zX;i)}Ek8$3^?P@y$)E%wOA%i`d0 z*QU&@MQ&-R;2D74ER$WeZYx0>>VkW;f(|SZwEQaH&htEN3=l7-urF|!ss%h+xy)GC zMy_%~J0|pOFMo)87PX!>v}dMUe?qD?2up5>g{88prBZZ-AMOrjO8MH1S18W5dS)KUG@Yw&Vh}uZ2yX@Gy@=a#Vq@Wh^X)TSGk#Xf9ua;EEWD~|B1Xf-CXPjy;r8uAmy@R53w4X* z3vODq0m`rojeV%9Uv9Z-Ymv8Z%h5Ua!`pGp>7B(+;)EgnYlVe|_IVdBxcRrd<)q#| z@)WtEtP=qD2OT4u)S0M8y~prl%SX5JC($a)heP{odviC@)ftNOaj-!1r)@#7ba2{5 zrG8PpbIFLYiQ9)u19_^PE}Lsr6LNTh(;S@-&j@POmQ)7PQ2j3diR1@ERP}2J~?-Opt zb?x3qfLW=KG2?qU1L9}Qlm}Y#P7<2oZglwtuQeF|@@f_>!&8t3*)3-51ttdhW`6twt|;BN;Z2$J1*y6NYIoryF{cH$@|01 z*;{d%Uz}-!BFvY$V&3JV7%#uszeV)A(d^T!1h~H#ef%W~kf10$oU`~L#cN~V7w6TZ zm2{d8dsK##fP8DmQhI??C{H+XLkO`meJKEHZJUmwmPrZ$cD0!YOML6z5P`qQM#Z4o zHFe!_?$U5#mOi%bZMm7}nkkNWtdt6w`+|0(Mp=if(NOTT8$xem8>y|OFSlEWC1ldm(nRC$oBD^#4(GX?oaoF@K>t`htUlP3|(d+t=7nkn(fM6~|U| zRIV*yv@qW5(a@xo8IVJ>0~qnhrf|9vess_20iNQuT;rxghJi{ldJ(8uF~ng;lNFDG zWq)G*XTHY&eB7XO*uaAbK9)?eHB)Af z+vV=xqJb_Bz=_6B$w6h{;|t@s$G{sCy$Oc)J9o`p8+qN7hxQA0SG;C!qDKze)j$b> zQ&s}9VF=3zA4;JWSyCOD?|$aN=-Bv{gClw-LJ$=Puz~g`>q|r|eT;(Ap`;0bdFaRrIpwfrMTDZ{zEc8vb44+hMvNQd8DyLb# z)R4+eFs4-l!t4As)8~XN53A9o61@kr5a44D-yZFw=^-$Bn#~qE0lR1n_X=<7Q%M3E zvg#;GLi2h)naNU;ze(F0S~93EsTz&X=<}u?dGx)If|ToyWP)%t zP_!n2AKn@C7h!b`CAC+6ylvOIRbW^XzId)GW^l4*(_(2L*HUFq=JP?rMu))$NSq-N zGh9Jz4aZCvB3I8S8wPOO@okjnXaBr>TwkKSITdqPf;7EZzRd)w&u))Q z6ZXuJN`2|}TEC}YRni0yDh)Btm*BVFTE~En5frCNbsrCFCV4^sW=F2r4UXgA9Eb~S zj@1P@?%YY5WeVxGD|VAS5<(GYWskfCg^2er^Ho!Z?}wV~%_W3otB)^R?M%9yJ`r z8z#lJA{Eg`ob2ob6IkNhZ0bi-UAEH=Mnk90(dSv9>i0m>#J@>TUxmF8(d*W?cl-8$ z#I|v<@s#PqL|f&jf>(GQm43uHC0F(c4AE(sa5U~6wsYrBz6=5q)+1^ZC0@MckrFxb zT>Qmi&Feewh&Jg|y_FQ*m3FGrrpTr&D_{*Njtw`rs+$2?cJO0ntvfVqmxoFfT~OS? zL2LlGXwuN|QoJExpDqOM@52es_5`-NH2Ljm#;NV2Pi6uD+@%RN)Jy@bys~|CM{4=7 zoJ3}Vh9p-j_r@S;j%skq#Oc$4uBCCk$6F^DaN~9+9|;kF!6B30=$83*Y2|!yxT+sq z5|b{9c0$fCdQO+Zua^kEBNd)KCA?Z9s}VS%ohnCXc#bH^E!xCSBA8`)x(4 zu7YVk7_6Q=y#LfLDDd#3U)S}}6t?zC19MRlMv0-x2N52qvHE`FweAvYaf-#!uJ3R6 z9O|~CW7U@F);@Q2!Z78PN!P<-Db}-wPVu^gt&xYun6ib73+gbF6wBpfu$6M1yM344 zu9*9#jefDXQJn*&u;~0gle9y^-sah-=f+Lf#@(F9EJl)gmmk}mE+HdjsPy}s|h$AA{G9$9OsRezKLU;Zl9*Q2(6XW%kb$q21Do9n=| zbbf|kwkw)};gp4-*PyCLTdMG;3>|!{jz;!c*`Sg(P8@_^p)@-5;gHPpSTZm+xV`<4%rv zO7MDQ%-s7T@XQo&9SVZc>1*Lq$c&rWVi3EjP`JO>VwoC1OpUJ-gq9C?93P@`i)P0KB_Mbs!=s~~(w-wA4GU=`EPb|_M++=X)ji!lBWLaMNKn}Cd{uok0ji-` zYi2OE{df5h-Akk_-*zVMZ+!dQoAf>^#erkJHXVlTa+_ya(mT>R%hm3)_03$RxHk?1 z6O8N0g5!fI_q5WUI_rs&%}-M>I~2vVLo`US1l31?EeA_gYsRVk;7bLq@snI&Jc$_<5b)6dEO)9+RDa>t`W2_ z-P?TLNp#a0W(T6QMpl==<4;ET%#yVLvh(JI^hkobLKpeP7%$HZ5v={gJQ5;IC3eY8 zaYVvthFYpgE4GAWDH>0NC16LPzkGqAS$NAe3>G+$>LCyf6LgPe5 zfET`XZu2PK051u~xyc%KJURU=1_Am06%ZT>DENwaIqRYKxMfNYYo=0Awd*p<*L#pR z-YeGXc#n^riu!Woo_cto;CJJwsSwk}bjby(X0W~mD_S)Ck!&sKUbv45}m3 z=;3Li9)3-7!y98O?O%Y(9^xG#tFLA&yXd8Ug(?2chK9HqR^!iS8jnvB)Vrw$$ zer!S|7Zi{g(vOr;f@L*vC0YyA*6)P(Hy(Qpfcm;Y&V%B0biXyw5y4#P?ok-7M=*R! zba!%aL*QXYzLXRWK4_WiWf&lsjSBEiQxyP(4gaH5#yMpEj-X2Yng%*5zopC^@_d)= znM`^afd)DsWfH&12HLYQj^pEx4*WYLNKuVi1UTHg~nvzl@&a}s-y0nTBoV7z(Xm8(pzqCnXUOslIAWEM+nGvbF zt0b8NFuXL-N+eU-;x#%~pJ&|U*Eoh3%;Aku`R&x~m-&L-n`rgcCHqER%sY=>K~NOfuaU8V|FU)fAxa&3FtwI> z#p`P~sxRUYf_@L$NxPcqRfAbdD$u%*QgrmcVAGz>e@m9L^zdVmdf*D>$Cy|ntCueP zJdOJjV|3Q*R(!9-DHjJ@MF3j71sVb@2M!Wyu;Jy~AQ2&cPvUQ&Q*3;fXxW%|YiUID znFRmc#tAy@81L8~81`DWVI9ZF(x*qgF(7t7z7jdJd z2a=RbU{{4oU1W-94hT5&9CY7dx|{rt_ReD34rWVQ;Fo-5CVA>2y6FTR_>7j9Z$6>z zbNbS}ANpz&xht1+y|)reKf}D(sIJN@o9hat;{b=L|Ai&F@){{AM-dZ{z0b>qL~1s6 z3#1J!x4l>5F0t$$&uo2U&{ab1`~AX2Bz(oa*vet5xmm-d$qlKF*bg>Oc_=Q&$J`TSAG? zLjkLgThM?G-6?RU&z3$O zTVMBWG*}}7pvej6oU0Hs{qVzr1F%+k_8NU$_Z&6GIiHfc@L2az^SCWPp3%QweEIQ? zT&8#eXeI-~)IEcMR3!wVkYpTRC)7NKcA92t&jpC>_5PsK#e^@9szR~}Ub`*2;)4=- zlrwC@F8+|@S)D3UvX|5^WcBLy5wS42o-wgObrc}0rph{>?^^9i^#pvHK&w>yDIMjQ;VxrrbCzMa8 zy1v~fUaa6uiDaa!ebQuR=ECGq!C;^k4MaWAgP4v|zq9DGx(R%#GMU(6$A|+|sRV6~ z3U6c4Gk*oz$R9jv7P|H(1lvg&)WdocQG|TGAkbbAo2nBzXW~=Ro-J5JDq`JOa@WCe zG@m!x6costo$#bpk{oK6MEXCHT+H`I``-3DbbGRj+)W>-MxTj!RPR0U1qLv)ly5?ORP{c2W6_<6i0Fxt_+AIpw2^lT4|lgZ ziou^AZ?2WGH6=^mwT&hXbR9jNuUGbfB6eys#n~2z8jtrtl=O~uKX&oPtv%eK%aMzq zUH_D-zR!oLqHpHoh(3g=U{#Z*En{%e^)WqAxd9S%EZB9?&(R05@`bFP$rUUN-F!EV zt{~MB<0?Z7wa^*%u<+EH#(u57CFlKp+MSL8Gz7{% zvTPpxnh-at!^8W@?KJ2fg5MMw=fCO5dauSc;~2CVn%Aw>vXl#N9L3o8&G+jkZxKv({Z))}AGh%q{`}Z)JsTQrW8~yZYaV&H zUbh>KNwh-b`^+emcmY@F)Yw>gMV~cqivXl5)lyQ`KGVKYZQPA2e8`X1ePL?rs=K!l zkX&K(06idh?-bY2LUR#XF|j0hVXk3a3595|{pbU8ryo>88k%3CiC%DWQV)4eK~Dwo{qi=9u-!L9!oQW$i7o-SnjTGq%b&|B8>)Fg;>OC($H zo*Ur36NT=Voi8*XJWU{LLOzUfiNGtD7 zuAp4__C4c?ODyfV_of2$uEbocgD>Z50J5%JY1 z__WW};l9f;E9)cZ+he}FMmHul6j_K^JOLb-1ALYslAidyv+5$c-HL9OD=px#=kZG+ z+vqT3oYfrUO>6Zt?%~uJP*ZdfoA77*Q+Z?Y=g`ib2@igx*J$e23K{t1 z7HdjRb*t6_qqiO7m{kUn&xUn^Jj>Dbu_#H%0Nu_`E#U&mUuOY$t{k+%0wd@I@gkm& zglsHU0c3Jv%(;_`&s*zeJq+6j;mb2sq*9yG_HR&Av$`|uU zv_DXaqwlu&uc@?fS;lS2&2Sp*9PEhlmPtvC_^ee5CYxSVl~3m^#U|t{M*oO*-*Z+# ze>e-TRnNf1lmh+AduAhFEW4BOrkfX((nKol%clv9TK`Nc@zbPUCKX{oxulErZU6KrD{Qm_Xj>iuY8KaFSI}O2d4{D$v4`bbrZXkJ2_J^zxP#;_5841nZ7_XfINN7r)-)j_MxO>nyrm3qOSUYuWVFekTl7Hx zX#wgps{?A%?GS}78y63nPv#(>`R$Y*VB~$@psGA@x2Cp}qDl55xY#-|@AzI}gh^m# zl;y&7js?e!!oE)6pi@n}GN80>x47C3EyP8I6fKKB^(tvPl(tkYn4aMrd3#*aw6NmG z##d;-Fq$Qa$So<|wJLn7J!;-)#cMO#(d>a3=!tnBX|KSMc@xwyr^x1v`{!w3`&~nR zk%EQR5M#jq?ZERga0=bk6zR;JCiE)30y>>JlGIdSRPcA0Y)1Y@#6Ik{G2pd@1P<~Gb&o(2Ea(ZK#Mf=*F_E^?4`7LE#SixQ*j*_SPCGTgN_0Y z)&>ARmwpbIdO0KPg3^FS)Dmcn*#^-907WX-sIsS+1Hiyhr)K~oc*n-4t2r-kqMnD; zrV7jNG!hu26>%JT?=)5R`}ftW@1*KXcx{?1_&dDK9y9)g`L^#;Lon+aHbtWOl0F|h zu_X4gOG~YoI|>14)1vjqfk5!gSh~*-qKKJ@Mfx*Fq{3Wc%sOGGacm7Ro_;hc(HHcze=?*xdkE+dUljFEUv@{aAx!iTOCQ9ORLr|5zlaB=-7nxh9A0#~8~K*-!C3ss}|5&UI$fA{kxN}UEc6ukQV_S1s2Kg1qF3^<%a*Ta|3 z>{~cTzatTBOUs`D#4Px<)*v!4;g;KE1#Ab|*s;DL{hm_B^QVx(8E$E%%{#d)p0odQ z+)f%>Xru28NAO|S{jwTrOl$RYJunmhe4nPU?d11+=N})gA3)A=kh0pF^P}~aUmkLY z?%Y2`Ro4#(7##i#r1g3acx*$O5@R;DHvv;0-y*exgo2)gv^I;q!G z!aHrj*qN7&ZlMwOn&_EocG&{4>6Vp)HqwT*jn6|Z3Erfe|JXBbUHMmcr%2g!^Vcad zJejiELI67;AniWz$0kTL<8@?^CipI7G}~v;s4K)wt{tQLIPI-&CHpvMM2OmF$0(?; zt`9uN9Z!xaelM0xz`#}9yGNC9w(S59_6e{o7-eXVP7j6`D1&v$W5jaqIYyq|=gbmc zCIC~~oSb0b+WQZC2B4$RcjBArCzr#g5akD zBp_}^#_I0Y^&oweRkJM_-ASkcirLAoj3+$*&NIl#NU9C_#}M2+UlUW~#+@W!?cm>F z2xnYgE5k_8m1nS1tJ!)aZ(ggX2U*sl^LiHPWe@A=2Ejq^*@~4Q_INo}Cfj}0rRg!J z@;MHE{umG^i|;1L8Pp3RZ2k16*8$*4f}z@LzUeJgae4SMpGH408R8Is4-D6L0bnd6 z&Gp6%l^w$aEh(;mX``|U86!3IV(e#tfjQ9mmoef@UiRlg1HEh4c{_laCxt-f?)$ki zI9K9Cd+XsO_efNRxPzE=fqjdom1!Pu8{<#;5+3wWOla7Ar0RqLke4bTIW&EDJe;kw z6Mdc+kp9h`e4Nt>#Q#|q%^;s9&F;H4G?Sm%O};{;1uqAhy1)|qtnyG5+)F#-s( zFg&)!gY$%U8Q}WaHwz#{lm3%Wu&z%U*l(M*Z@P()PJR4~ROK3GIlU~2@3txsfVk{e-yq(MyKzgr>nIs;DM_My z!9u??pC!D7>OO}7sKaDOkgwP6b0P+^ezKaF2qc260OnvRgeF0G)+5*s;#XQLo6dQ7 zx!?4!L1aw%-$I2V1vmcGCiwaMqeKJG(Gb_TQQzZ01)qGQAE_Ft%D@uyqI_om08Q=# zCb!A9@au@-J{>;8bgCE~vGzxMP_$U171-VUeESn%!cxhTN)BA>|0uwPhGXF8_Ao%= zoOlDa*`Do$0USh>N$A6I!Q1}s^G%g=B$)+IKEUpf>H|CdK_QbF(+#l>WQcwtNLV%I z)Fc7lBJS!oQwX@h0`g&j2OYE=Tz-T>s-y~L_HN`R*4V3!DIV$q z|6kWG;Qk^)W)>yW^o2Jo*3>RhA3#iM7sC!mzWYR;W8J8BKdKLvGIRr;1)r^u>ILxG zpFRM_5-B?KR@>bF)vIRk(oI|{BySd71Eih$14rNxU@g3izw_4&$ouhM9;LTZRtaBS z069J9u2u|vYS}W}drAJfq|1lXCD~W|E8}z}l)zTgZEQre((zBV9|>F@v%$R#vYE?W zN3^yK^E2E~f9QS>y*flxFdH}lJI8w&fJ7Bod!<>42E*yu;n;{8*)i_uXnQIJAI}}k zhb}ljE8iMvcr*n}B1JTL!2UuuouEih5;*ViE<;G8m5=(eLX4{iVUjXqKj|F-QtQ!7VEzgnC+l5 zRamG#&G{JM93@LFa~*IkOUhzLa)i#e^(1Q-HT8kJyLHi5 zr$Tg(oJrB}h`NEmA5rH3DMZIBcPN1|feX$MTa?MyD}w2lU=tcl@hxEBdA@C)-%r%q zBs7?!yyQ%->wZOcn2ppUY#I2smb*G=S;jry1m>UuM{v_71_Q$7xlb9J>_Zt9?u1-W zU(0%es6-3{RQo;8FZSd>Y2m)%7FER!lFaKY+-XDIe*#F#mX{ohnvW#k}p_C;KA6aDs58ZwjyP zX2idURA`64$99u3Q0YslFZWNL0nraKy|;f5JnQYd)_{VI#`!I~R#GjzUb3>waRw!Q zFs$=^xy8#UlyBUgHq+OFmz|teU-@(m;I|*q^S|Kn9=}Q30#q-bqjr@m3Ij;}_Ozaa zsAHN#;C7BA%v)eZXV0mPBxmgNTMK`@1g z_CJ-b#=k3F7P9%;UrVbn-CNIp-(lZv3)PO5d$qnhq3X0HQEAo)-F9(DeVB9E>5$Y{ zl=A1Z)+ss6sJFZw;Es@rpqkKbbK0iMy6;zK^=Zk>EFiyZk=ay8Q18^_>Ro#d|AH?$K?rLzXQLwJY9FsV)4HYbDE=TgvWEvq%eBf zP#7eei+uqH{fLawal#k)InTXIGp^PM*uG}zD$Wc5g5y}!&o_ZLYFt(HrL|`@as)W2 zKz;MGKWMm~*>;Rg;^a>$SX{}Y5*BJxmRAtmj3`9n@=y%n6KE}Q^^uBL01?P8kX()Q zkWcZ>cf&;n!P?E=n{8}Q_EwiVWkxxjFGENHRoh*lj{d|M;==G8{V=jI!3$aHNB9h$ z-rGI$(K{Ctp?v1n;<2PV-|QxK>|~5mm#@p+6aoN)7VL~uHiLTB$z7)K$ zQH0K;+8fS0&lsj5!4T9DV)J06xlI#eM?MO_i>nx9nuYz6f!Z6B?(Y#+32_MYIE zVysMfe6qQ7>O#YD*8!cb7X{I~_5M0E-FvR6xxH+`qaodSIr4kiC8fYS;kUkd<5~wK zoxH~1cmI3|&jLv(ZFpHrOQRD4^ky;Sc1YBWN0g%_N~^lCMxM&0Q}`g)l{5DW6j{3a zaRsnp-1|s^>Vd661;y`jJy(CJQgiWRfFow@Hw%Vc%vMM*o3-Nyba`9ah|?yZrst+w zY^tSZ)Ag2@pp5M)M<8wHS(B&B;&;GHnB%Ol+mu54;Pdsr@G-Zh=NSFGD|3D5qYiuf zzx^EBKQ7VNepC_PfN4%8ZlRGs4IADySF3i(vw6nccdIB)8z_QDm>mElD-3l672BQD zjzdfe9`Xq?JlUFSEYGTC68wgKx=@?b7ZTa>tSC>H8Da!cI`I8mDHop99Eb^LQJ;R(Y z21cP~syM9X~N1t8VoIGV~H-Ct^%0H&P}Jlh_62`&MR z+VJzIO8Wubl^JNA)v8vo547oN}X(Q6>Lmx&|bcDS$J z+drmu$j&(mdA4`N+h2IEP41f9+!us2{-o&&+4+47cSO}q!5iS$0HHg>b5H_5>F!h^to5oLO8@CSc@p+# zMZ!e{qu*KnIEUE1BQ}+j9J<$#cim$#&u2=;@++*ho+GSCmb5WUUwp44ix#V?D635>G-lCj!%eW%Zv94F#mG8~+aHA4C|KX}J&IacoxEp?d?#op* zPVw?@Zb9|Qr#kPA8;;AcbZdX!%UE#hG#VGcaeW1Zg34<$6&9KayNw3ZBT9eHIvT{T z!5)hC_Hng42#p1)=%->J*{mTxSDR+myMFKKiX?P z-Du~gR}zrN&bMkZcTOzcpjP6Z5D1MAUdw9L8`o-5{D^Sc<=Ag-Rgvsdl7Odc!exu& zBd()!U9VC2xH8A)i^Ddf0}jp3vVP{&O)~WHjmO2P_$)Kg>mp?7Bqgn!d3nsM%fc1x#O%_yOGTr)e!Q2-QJN3R? z0(4Ru+LOO<7V}fS2#{_>V^qlbLlp5Q5AcsJMM$R$X_o?KkpZf@9C7`!8W^1{kUXO(JQc(0)H!j(?}1zUZ?tPekg;=+>~)XwO9}Ty63ZF zudbbHT=Y2i4ILnvY5*t=YP)__vLhvB-(!De^F{8VcbTj3Nn^0kT~>MBx$zcPdd})4 z(1JRS9tFcQ8?8w>&)>POFcG(zNw#XMbfGp zG2bsPBrB7CvTV1s)G-(DJ&oH7spnkE?X~NzlM|&HmgChhePrZ2DtAe;*XG>4YE#z$ zrwgbfSq`T!p@dxdBDm62Zq?zm33_Mm@mQ>ydB`O%0)Z#EoAp{!t?LWKfVZ5Fu7 zks}jm%f3wq8S&iC^=PSl=FxZ_iznS(gDuZLXkZ}IQ|B#P;_(}$VEN{1#2$}qb z_`uYzk%ix9PiQIA`$9}kRFT&1#A(o=D4>^^7QxCZ0HH|JMX&mc8$meC07M5 zo!DOj4iy$t&$R3^=N{;L2LTy>_~3STl&hAviCwu`gZ+lz$a(2%WkfxAx@FDpWo7V0 zn%JEU@XT@8!BU;FCUx|)S!q$#VI<+OzB3Q@g*foG+;o7o_(vf}j7Ui=(@Udua-yH} zreUuvtMrM#ngaw=IdP*BjvN1c3F}Tc`C1}AZ!C*<_zr1pgZIvOAaXP=RBS!CGN#y_ zcwwJ@k!h((f7uo>0#X0$;SUxn&wcTzv;sHIj0hpdqr`2m>&SR7{w5b|vPC-6%|-94dc_b1I=io#GWBVCsr~pA-dgu&h63c0gNOn-~=1upRzE zaRM4pMwS?a-2VfS$~{kxyPZ(a2^m|zL6M};3G?K;{H1F~4BiwcWz;0QvUZhGS8ou=}92w#^FQQ?aKR=GFG zeg_l1aWsX?+pr@Z7M$lULk=D{Opt)a@l*M2t=YH1FqaVyzJ~8!xkysQI_85N4h#O2P|@U@@sA@T3P( z!5meWw<)eq%u#fDfn3`QP5?Es6fPCu!wZ*?_jXBZJSJeE5{1@X(SLAr$=f1UMelmq z`9ibDX1UxrtKDFDl8=#0Gyp1R8+)Q%%p3SO$sHP;9*2bdaLOCr9N@H)UGh%>a`v?A zwuh4a(nT{to1dR_M_N;|NX?+pWwXd6U7z}#VFJVaR1b)+IYq_K=)06(%y?@Bvc7fs zWmNpKHiL|@jh&Z+^PEXwk6}+JL;XyddEuk2E2axjuN-q_!jlTgZ}Ibpl^Db1-IHM%>8{|HXh{ z|9p2TsERbw;$=gCIb&~EVAN&tGmuZp=3OdS>FOK4 zCgiaT2*Jd2jyIQ0I8cOELqf>2or?D$6V^9wxV~J#(0Jc^TD_1e!a*NAYHzOykF|bT zt%;rMg(>`QYl~-T_JN}BLk@M>i>{14=&paPu^5hz{Ihqf`Bo1BZ^LseyCo5Ismbxc zWuonhW|_&ebHece=|{FVOJ2yN5WVb|ruYW(Ei&0usO?WTo?ky~J$bvmaLU`_`jX;`>mLjmP zG%*gI7WoThvmI|wLoKq2z&7ha9*>hE0$~fc77_5w5^{*|fK7u9ws4l+WI=i%KV-8P zn!MK~uSZ`#xm|ZT=$vniAU|)gqqn;DrS~wy9*kHfJZXVcvWAqf#J`LuGb}MzpNh?W z<>^ilZG1r)#&^q3cEf-xG_~X9@*u*59J?HsuLE(|Rxs)&6B&qYlYcm>1a9)__gM0% z^ZTWT7+}_()VWB9Yd0d-R;frHj%IujaamHk*?<)N7Sz6(KnxFQKQ0_GsC+mEAx-7XZdiIoT_77V;4M>AjUeApLoFKM z9@f+HyN1IhJ69LUnh0(FGCv<)I&&vvOP14TaUfO)$U83srf^-`*263aGBT#VCFG!plx=3~YH?(VKY6j!RF zDmWa4G%%BL-8~I`{5E7ZeG_a zBnpXkf4x}QV()t)Znjd~Jd1fI(ERc7+lu%)RXY)e3CKqvjEZS3oIgryIRr*z6;{;KFVu5juDLXb^0*Adbf|o4t8GEz8hE$mJ?{Y+IpOFDIKo#+Ex%ZZLD_ z`T*FS_eTNg2+(j1eeGH{8L&i~3UJrl2g_K{P1}awyz!I>Ud&8Mb)uL--ISm74Ymh`81khPi{PK7ol~ZwsGn^o zxhYjn*5fzIaP6YDB5&PfI6(N*Gv8 zON$FHQ9gG{59J9THLtO?adXdF6H4$zVmL;ME@aG~=|^KSvo$EAJ@1~nF!zT!{0i7| znnA;XkmTd<;^Fses*e9m>WE{J1{`|(YbgdUwK-_Qy;Hl)OZ@%N6fSz{-`c_~ex<>+ z-Zry0UxN*Cu-V0VVj6)tl6jZJ>uA0Z2>H%!Jci;+ zT9JjH#)An9$hszUFQdXRHG@zZ4ya5D?8_r)2lbN-CQRP}Q%~2~DmpUr@rMg7Y*R4j z+O}to8}WCR?kEtCrij+q7}rle4biF$bOPf~qVA$8KH!4zo_f|#Jpi~U1L!cU97z^;%f(St9qEmXIIuA73B2J z^9||!iz)j#0alvJ+CYgE4a-~OP5KN`5}+0fJN|7#+$?&{s3%&Pd}DZpedpvRCTZrT z4dhXScfi;)GTI)To-ZT_2;R&CthZ_2%V-YyL!37GRn`ZE+s-`UCypw4k;f$$ty_`d z9Zdb&d$Nb^5*#0{-M`gkNs!+vj5_0eqsblo%^;#8EnC3YiseA~-w*O>rV({S*&XJo zy~JRi|LHD9v;1}B?E)Cg4()3>e+CtV8!cl~*wp;X#1>V+-EIEDRyp5dvPsjoD^` z3+d6ndPS)tofaU^?kMb*bJ~@M5V;?dXYrglx<`lYr@C9glZ46Bzic0hJ#trwhUt+6|Mu*MZK5IOhf zbo39gz=Mh9(qdkQb3onOo{LVYWIhvz;S-o@=r&m=tpp?moxC|W`acl!Xpr{@wf;_D zo%dvj@)S2*qe+{}xb~xiOhNI^{fE%0qhZN0sQ`+#&=S(`_u?%!-tFIm0+si_lAAGB zyIqIjXX?$Z>L>?-84h>1OgDQmkaL2&UIX`s7#iO38p@~gtgH_}8j&tUbWcvb>gzxV zYF;YkZ6L(?<9riA6w@8H0S9o1@*l#aDvv32>|`^-K4-akW1G>0+O>#^SIDNj!Fed` z0^IvI8rlUt0EQo@cc|wDEKafY5HBQtw$-<`u1WDwBb|&D$Qs!kdwjh;{2-;^6IwLB zmF%XeKSRAAlkBlOr`9-YeSMBGq<1IyJ<&f{!r+)`tGP^R`X~;c_xM;rV4+{{i_iTd z&PxH{C_W|wZ1XnJ)Z!sQxsgY@U9aCI^Tz8m&psZdNo?bu0&n}<7&k$`=I?-!`Zbv| zn`xkG+ITqP5RZb>2n;AY?7{(aR`$a`8W{uT>pLcihbAL<_P0EARECDHwJRivYKZfD z>s;_VS*H`?KmVvrDZ&o$p(Haqd=BtXK1`2T3$B10U#FIe*A)T=SXHUN43Rb*uf~DY zIm7QgO*GbqCh$0v=W^%Vb6+#6t6&4hYxh9!!A1f$luxz^R=1H~KmYCWr(yPqeM}T| zmVcZ4Lm415X`)z+OqwPa`*lQmx?%|xI@Z=^&Kdj0acL#%UZ80y*p*wfbk)Sjzjo3) zjzt3y0sO}@;swB5lJo(Ib&C5<~r)lcNFK$k)q|W}? z@ag`E@9n4y5plpkm$3^>*oJFe=n4gqLg=zO?)OH@shaQg-8qbjWbt}c53(jIXf#%U~j)vv4>ZM1%Vp|n=*ab~! zU1me~)?0}+omOZ3qTprrgsR)vDJb&iWHL zHuo z)J%4t3t)&$bq2I4J_M@ll49L)&q={Eni`R7@l`y;EzRRqp7RHX_re)5_rS$bS!8yGip_UMCRXufZV2b{&CbXm>pVcB>>2KN3LVaI-NP==@mPO|C+i8#`;V zN0D2?!h+>@TPFiWLo=zYqbn~T(((&60bTkuvQSt)1KPejqf$mvQ;KcqaXtxK#L`#s zYYw9WOm=N_k2!^&Rn9k@rrzV#x&AmUOUfo|6K|AS=5Tv)#o)NZiIK)o3ENyXCY=>; zIHX1kR%$1sMOB{{7m?9!v?;IdD&zPN+lP{l@XOQkaWPPt-0dn1h-T@9B5 zgiyi4a2iUxN+xq;Fvor=kjPqJCP`HTc#W0>t1tH9Y2=3-45EPO#!H{KG+Liks~J7e{QG2$Wf-~PFihm7`V6VOfrvRtK_;~rUt zJ7K$0I`^e}v-c-a5t-C`EavqpVA2DR-HnG#e6JQdSbwv(o1Pa%Q>i0Hxrkxgj==}_ zvwXqNDOt9{{QuySJBrxKthDk=COz_A4BtcYYHI-NjMhT9HG~9P6|kR-(l*!)ygBax zubd{ZYmG2=<@)p7kBiRuc8y+lsaox}Um5mUtB-*LQ9w6yW%I5nRW#s?EF4^Jc2NHo zTb$$MX!=sZ=3!gga5IlrJ)Tc9;V6%-z08=V&#k7fZ2EKk5Hd6~fp3^tj?6(Xj=Ylo zzwUV^W#?d96M~E5}p%AMoYJghgKfR3faLmQZ}dH zpDt?CNzvSH>cB#Uv3CUs4EjNHOre`u#CuI(X|I~H#1Zpk0wXbUL@9~)G&E`Cj-OTk z&ue%g`5@Gj%{;67lPXq_?^Vr#7`3re^}o#<1HV>&6xB;N=I90rAwE#QvE>F8H2O~5 z6+wL|XWapF(n+7nJOXyy+$q`Pw4mub_gsZwRj>rQNS7j5E}_bgc&_YIfk8gpMUNc) zk|v80_@~vxe1 z&V!s&Uh|Za&mq)-fz3Rc^>E)wD!w;uYsHz4|XEa z98UI8u|ywPWmOWB3FnY=%z2h~lW1-F2Fq~yv`o?pAYYb(F`>xAxPC!`Y6H0%*9C2x zy5zC%r6@4zumI2yhj33V7o?orv@5C52e|w*f+A-4id{A-VB7W2i^c~JmX)@xY}RKn z+YK*-N*!C0b-gSzK#^-lbVXA)7ycv<9m!TSK|)M>?HSHI*9SHoTCM!9nhk!MTqLKJ za*iky8;4UrPf!rxvc((OUb>sp)cw92tC~y|e5SIS)tulo50wGkdw(C@g2Q_jc6SZ* zOA3Q8_azz-2|2*BofbI2icM|1wt6q2B8k=>_bGwVPK7xjj{rf$?!s1YUr+3nFCmiv z5w^e*=rDj(554eD)yLJB8-NraeePRCMc`Y3!)MGaN;94-8&N&7I~Vy0nxko8)4Ni} z`CMeMW~M6?=Q%Su)Ueb)IS2%}jtySk(c=~n{NWtSB0-;w5 zcbq>;^cqA@bpNWe^pYt)albIOCh4v8*I$AJPL+PdWrire{4@2=W zrc`p+#wzd<@KYv(6$V!ZEEhpGxZ_QgA|jqp~gj93ni$T zSE@*DhWBFi^m>o}Lfp|pyK#8T>71FY1#iS`OmXl}%&QgQg@)2^@cMg+!CF@4cAsAU z)I2cq3vu(Vw{?T1Oe}thpm4ue{i}xFM19kP)Z{clbD#{ypL}d~IQz{GhQinIwqt<0 zS=i1>&7@D6R*|wYYvZF=er-%KUE_gJK%4ipbAon1?)Sl_%6YrN^|H&X9FM;=4wXU{ zorY%1COZ*`_9N6{k9S*GYsJzG7GsCJa+AC}iFn*1UFX<2PWiJ5SzBx8Kl(UrbUj9R zYKO?QiPy;E_?`uisyg$LwRWt|As0U`ds#}}&OYED)y{#-)_(-)70Ffx-Tq`SjFqjB zcg&7-0zLYBI+#4(@*@nZUug($X&Ab5`iZlX2rKto!pBd*ub`w%H;aI{WXVQ-x8gg3 zvWqXGeE6&NTaW|8ezP9&EgS$Ycdl>D9O3<&iBsl|%?wAzZFuO6C4!YAOPD@I;qjq@vgPa$Qk9s?MyxHoK2va3H#g3(D1v$;DVipXB4iusXd?mK*&MsXFw=S zReEtwG&!vD7>r0UsFRmgZ!iD}x1?PZwV;&+9+@2oX%o_59{T4yJNRpz`35w>02q^L zm>=LRP4c&0a>^{uP!@1^j_;h>ZC2%%;WuBaqLUXa*!>s(b}iZvHCKgd9z#{KxxpWL zIlFt*1=wl{!g#hj^6A#$(2S4ao>;7m*Zgnfl(+YO(tOq!>?pkwSqL>H06*K>lj;p_ zAPIG0U?+6+n82FuwjW0oQ4xmfeCZvM@(#9TD0pPF9RPG6y|{VgIVnixjqnZx5T=0R zZ3g$^XhJj2ER8!&)ySm5g$fwLkWu=%g;?t?WY>lr<{+i?f-Atl;}W1w&JNU_%8(lj zvxDXjT{N8qPT=PRxTl%OU5|gA6SdL3^b~Z4|Fk2=zz*GiwIgS~D8J)_->1^k?`)K+ z#<-7{F88T>9qoOXJ3g2WBFe1x-Ebokj)$RL-aSjNY(&)OxQQWie@6u9+a<2jzrznV zYG{#CZJ)l>jUGJyN z!m15sw5if(biZ0(;Zz9S7^?2nq49m$$$h-$KUo0SuT#n;uSKFkk5%bhp9;zG9P4nt4rrxN(50b<(mSTHk$@4PV=%tOsXSui z+O%!dX*xg${q$~Mzv^Ho%m~3&JDAOxs!~8-&FZP9sSvjf%0B)m`a9>WupLRM&?hfF z!vml!j||c+QKj9Zy6ZtnlYJuOi1a;h9Uy0pt#}|9$7q;5^-)*hN@Oq7+!!M#)Th+% z@u-(9X_tcX)NG&=BAKGh@dxQRLK!!_!29Fs z)F>3cSup8zbBZf(Amsj7+Ff-k6VvI7h2ZDh7HI!`AeFE^AAkCEM(&0-j4SVE#T`i@ z(Ve(|W|KMpD*WastYSei7k0zvi41dl^(T6g)xcWRU4x5F21?jexW1W2{Ze2xjlIQ! zf$T;at**L>oA9`~x@@Mup3;-A7tXC!dZwwMS7(}@41i;_Z#G)mX?{a3vQiYC_Ax2! z+zVZepVq<*lM_Xp5|AIL18~J{!W`OWL<}*C)U9dRvj}ll(SI!Y^2C9I-nJ z4klE%Nz6cM!#OBDwj{f@NBhFqu*52+2UgQTSj++scFNa1*ahO(;H@|2N6F&a@t3h@ z0vYl|djA$A@Hg2L(+2%3Fy-Qq)1hPFz_5A`4&H0u+yN+b+!z)dK5O-S*D@uVv{EPHC) zQ7cTMcsftKk9iM@yml9L%P{Jz$>H-k9%N0Mo4p#g)7(MXGc~VG^O*ItJ&@U0&mw~) z?8&*2JIQc3#8P4y(9NtN90z@tptMNESRo(OR3nnwXR!Ex0m$S74O6A(wRzAP@Ll=r2!A-Fz%^LtaxJHf2-dmSC zAr_aRnHJI2-jUlI^LyU*O_Gaet|Idr-0ViR>wxj0-G%+YNBcBWgpk3PssME!#Ump$P4ttPXFc4 zO|FuqB^{5!fBsp$Qg9Nz1UV!F!q1;-B4jTQ=7PazUE&VyKlVaTPPOBP*#6Xh<)x&l6nZvbPYmrqmS2^D zO!%J5@&qOaPqoQFFatRR`E;_9BiWjXT{`RWrb{Am+)@v~&uqHsf($}_obRFtuG4RB zk`x}R8c3?xuQYttH6Yq`z{luExl=|zCo7tt?9pJ<6N{el+i<9HnQ&2w46MXtmpwh* zgb18^X)y3SrRFj`4JF-WXT3K=Nxju^+L)2Mfi^>2{HV)b0eW4ecKj!cFVF)q>r>71 zD@gsi-H*iUZeB|`e~Hf`x%H?$Syuy}awzAL)}_3}NGelk$FL-R)Li%_GOBgy@R2O77nMq+BU4N*Gz)&k+T3J9sQj<^0n6rCe>aOzta&$$zzqO;$|_`+0@wh#H zZ(JO_01u?VGeDN!SjcUEN(rO$wyQ@`bv1BT`KaEOvx^|3ON}r@EFe!ugTiub16Y#^ zzfz=4lxXHiP`e}5#q3TO+x>R`PF0xlXYhZe-{ZytqOL*p-F9y$H$KV-{M5IcIGce! zL$%1xK{kdI`=9Cc`OYZe+uOAHge;zl$a%KKI$tQ-0=llygU?yFF5e~#J=S7)P*ulO&lPuvs$HVqK4?fyS?l4{u*hrG(wlhk9uOmz@`h~H z)0K$2i!&-UW5&eHXNjD9gxAxuSF|%@LG@`y#fD9O~B8Ga5HCCm`2f6%Q_q2x{mb5no zgk%Tp6h<)~5Gw0b)QC6n_T~;CdCjcwN>vbMIUF)Wbp3a|HTo`q zh7}MpI#f1@0H{}@ZbxyzTrnmU*PJyA_&rAgt2-)7B!0$U{*tJGq6+#( z!(_hDfcxeC2q^EUxfHg$12Z<*GKgHGFG)>d54=eUm6;SWk9Qd<=NIRfL}QvYeR#}j z)(3JT285ZK^f8+3y+vCtOBAy3Ac@`x?{s$syF1mSX*P8yAPvdKmOTJA0-AsYA3bns(X<;E zNr{xdmVDdRRv=?NBz(6Sf%kW8pOrm6!0XCd=D0DS4lzoP-V7O*oCK&T+8Es%>0(me zlnAS-Zm{lF;;60D0u#H!y!#klnAPke3DrKGn5Y*$-AAoeel(?BIg=}kQ;7!D6t2N8 z0;z_wiYUb~g(>N?K;5{)^#S<8T9D??vPx=}Ed`A^M=3hK)ZsCs%cOxP0y8F{*JR`m zjX-b7bRG_z)urai8$OJpjqsxn-R|ItT#|}>~FRLjB1T;EyGZdxpB4kjmW`?R8 zwqFK7k+uu5>)PllIk(363-kg1s8-2;h1yDpi^=&cD%23b8noOGZd^pn`cHAxRg}9i zxZ$3k$GeXLb5Uc52#R^+jD>@j3h7T`Z(X$_$|ZFJ<-H#H#SBOe^<3=(PV0b?+VB`d ze@R_c*bJK;yQto)mOFM?3uZxlIv0BfC9b|JGre^9HqIHa2}DENxpRJFv7>uFhEyg? z6c#yz;>Ny>;=`c;a%HDB6ZqmliAhOub3+l~Dv#e(Wvr^MduaYDp87yId(sFTUc|rf z*}AM{|N3e|UFy1F$(nS4!!=9R7Cq(swPnJE=gitgz|RhL1!YhL#w6d^FLa)xDi`W4 zm9UFV9xkqM&H^h~mnnN<8)J*n2H5XHulQ2e0*mT_Hi|e>PcnkaB?*>L!sQhERdP*W`rdyfInrMgo zlw_uHJ~wgLjRs&rcMR`8YM08t)hVCMyDm7Sn60CyzRO9v<_l%dyPn(JQfMYpzc2{G5Z5py|Z!X_9`Q zElz0?CPrp*d@uvcaqaRZl3E){N;S(uQ*)-W?Ff)vpTrJgmyskoT~r zURoKuqa9GTJ8h|TRh^EBQ@%}`17oN;#lCe*F4)AtXjG6(rDwT7u5V-5=IOg0C6At$ zjwziyGf5;o0={SB9z(Awy^|IIGO7l2`r3y2G4P%rsTh}PqW?#BavDUZo<-ghw#@Od z(1`krdLG@NRAF$pgm?nmVxc}&DZQ!Mokr83mzDHS;!_QwVtE~tG18^R1tk>jDe;BM z=gTQmEV(a+9c5fG;c}H&*`{%4-f?7y_q@j%q&~mWO_}vkVa|D$Y`g~nSC?Y=BP9q~ zV0ZhZ9G;WB{%Mts!2yfYE@8IhXdsk#Y%@z&OQ9bq@Qf3tLLolcRiM%`Mw-%m)3|CfUDF2V(uqyQ z5ob+WBrx_<8IR>|ORTTw!H-UwvLD*YWbG3<%=eZXt9^bxC)7=2B3b~Uh2InhCr2rc z6A(CGm*;BGrwj%FIf1;QJyNdmN{Fs%(qDvQsle(8{AneE1gLBc7o%7HPH3_=E)ADE z1!itE#*dnD!SG_{^W9Dpq$9fuUCKFFxd$D;VPDU$IG(-68@UkD>9TA)B%cp(aL>?w z^A{3&@%jVBj9UZaMOl#!?#9cLdt)TdnZ*U7v5|~&{Oj6ns1#DBOJl^{AL9EYa(;p1 zCSeH^jwroS-|y1mHYI?(Y60M0?LUCr{6TG=X!?AV!Y2If@1|Ch3owuk5w0GUhyZ`7~teAsn`x1;9(3 zy;-u+Q(vze>;-RGWt6_KE0w9KlJZ9uHypY_FQ+|AykYJ3I@Q4vU=M}Oj=$C3UYKk? z3gwizB|yy+O~=7d-vX1!642>?Q*jAAU~HoB_d2G11d&svI^LHfI;kBwtPN@v;)=t` zu2(Pd44#VVs5kh4z%-~UYPe;rZ|!^8CbR;7$2Br1;f_*oc0ZS z^`L=K|H;n9dCe2pbjx5%6{d9S>Q8V-j8N_QXN5O*K& z8}eQ2-uJHi$9?ZzzqME{R5+i{o;@>r_RKTSROLNstfnK9q8RwLno(=bHJC9Uq-hcR zvDPW)u&;?VUe&CP&uU_EZhUdI&wi%Aa?nn#K-UJ^QBm{bi2Aeq0{KL6czVz`V;4jD zHG#NY)`9GfH0w=fCrG;w8pffalbB;kgG#2tplWuk6Br1#!CX1>Il<-o4~!jqAI9?c z4We4l-)E@t2wFI}Wk#49=?kViS>3a;hnjvSPH$9K>M`MX1iL`Qq#4_QSg)vg)^EHt zkm{L!dE?p1D2>y5Z`gsnmuf{mHLR4CEXi?Hbjf|62QVO^( zWxvBpueMrrND41-y) zvS`rWttT@g8d6z_UO!M(m%^9u{4S&8gQRXlN zau7K;^p;wXi2{pTESsK1`-k}fTahW{sM|N;d=V;y z3j(tUP}g1J8%nVXfszC_HL5M6MUH+Zcq!b`yVm%J-QAitJ z++%Y}Yn|oPn^E*=n|xzddJU0e%Yzvob7AH9O^?5`cOX^|ah9U*Y#&@4{@n9;sE`wY zx-a<7-bNjY8#f~9q(iE4AK>4HO<8egjBX0gDGZFiqF5FiP#8Bfn11W5=M?5~)U)#5 zGv3mO>?-e1I;e@bn8nP^2XmY{=BQg>CS5P(?i#eeB|^Y{E{RP>8iIxu<-DFT_sDW| z>}jjJeDLC6RiLiDjs=yw>`vNei!nvRe8un!rqJ>-MF+SGf`$XVp)-nPy^hksaxngB zbyeE9OA|3)86K*-fnvCEu0Koj2%T*GyofI+zH+RsTjPzj;&syWW0f-(uHRkGh3UL= zjD0{(@Cy-Hf+`6Tn~tI1SvmgTB1tC^O73(yE8RzsTu-~WQB

UCnwlDmg)mZ=$9G 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. Services in a distributed trace are separated by color and listed in the order they occur. [role="screenshot"] -image::apm/images/apm-services-trace.png[Example of distributed trace colors in the APM UI in Kibana] +image::apm/images/apm-services-trace.png[Example of distributed trace colors in the APM app in Kibana] Don't forget, a distributed trace includes more than one transaction. When viewing these distributed traces in the timeline waterfall, you'll see this image:apm/images/transaction-icon.png[APM icon] icon, @@ -37,4 +37,4 @@ After exploring these traces, you can return to the full trace by clicking *View full trace* in the upper right hand corner of the page. [role="screenshot"] -image::apm/images/apm-transaction-sample.png[Example of distributed trace colors in the APM UI in Kibana] +image::apm/images/apm-transaction-sample.png[Example of distributed trace colors in the APM app in Kibana] diff --git a/docs/apm/traces.asciidoc b/docs/apm/traces.asciidoc index 214b9978185034..09d8f52b92840c 100644 --- a/docs/apm/traces.asciidoc +++ b/docs/apm/traces.asciidoc @@ -11,7 +11,7 @@ it's the collective amount of pain a specific endpoint is causing your users. If there's a particular endpoint you're worried about, you can click on it to view the <>. [role="screenshot"] -image::apm/images/apm-traces.png[Example view of the Traces overview in APM UI in Kibana] +image::apm/images/apm-traces.png[Example view of the Traces overview in APM app in Kibana] [float] [[distributed-tracing]] @@ -22,7 +22,7 @@ Distributed tracing is a key feature of modern application performance monitorin service-based architectures. Distributed tracing allows APM users to automatically trace requests all the way through the service architecture, -and visualize those traces in one single view in the APM UI. +and visualize those traces in one single view in the APM app. This is accomplished by tracing all of the requests, from the initial web request to your front-end service, to queries made to your back-end services. This makes finding possible bottlenecks throughout your application much easier and faster. @@ -31,6 +31,6 @@ By definition, a distributed trace includes more than one transaction. You can use the <> to view a waterfall display of all of the transactions from individual services that are connected in a trace. [role="screenshot"] -image::apm/images/apm-distributed-tracing.png[Example view of the distributed tracing in APM UI in Kibana] +image::apm/images/apm-distributed-tracing.png[Example view of the distributed tracing in APM app in Kibana] TIP: Distributed tracing is supported by all APM agents and there’s no additional configuration needed. \ No newline at end of file diff --git a/docs/apm/transactions.asciidoc b/docs/apm/transactions.asciidoc index e70587baa65ea7..33f61adc8be630 100644 --- a/docs/apm/transactions.asciidoc +++ b/docs/apm/transactions.asciidoc @@ -10,9 +10,9 @@ The *Transactions* table, however, provides only a list of _transaction groups_ In other words, this view groups all transactions of the same name together, and only displays one transaction for each group. [role="screenshot"] -image::apm/images/apm-transactions-overview.png[Example view of transactions table in the APM UI in Kibana] +image::apm/images/apm-transactions-overview.png[Example view of transactions table in the APM app in Kibana] -*Time spent by span type* -- beta[] Certain agents support breakdown graphs in the APM UI. +*Time spent by span type* -- Most agents support breakdown graphs in the APM app. This graph is an easy way to visualize where your application is spending most of its time. For example, is your app spending time in external calls, database processing, or application code execution? @@ -22,8 +22,6 @@ This could be a sign that the agent does not have auto-instrumentation for whate It's important to note that if you have asynchronous spans, the sum of all span times may exceed the duration of the transaction. -TIP: If the *Time spent by span type* chart is missing in the APM UI, it means your agent does not support this feature yet. - *Transaction duration* shows the response times for this service and is broken down into average, 95th, and 99th percentile. If there's a weird spike that you'd like to investigate, you can simply zoom in on the graph - this will adjust the specific time range, From 1814957edc1c3170d062b0d6e2e3c5bfc88d00de Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 20 Nov 2019 08:56:23 -0700 Subject: [PATCH 11/29] [FTR] expose new es client service (#51066) * always extend all common config and expose new es client service * replace `es` service with `legacyEs` --- test/api_integration/apis/home/sample_data.js | 2 +- .../apis/index_patterns/es_errors/errors.js | 2 +- .../apis/kql_telemetry/kql_telemetry.js | 2 +- .../apis/management/saved_objects/find.js | 2 +- .../apis/saved_objects/bulk_create.js | 2 +- .../apis/saved_objects/bulk_get.js | 2 +- .../apis/saved_objects/bulk_update.js | 2 +- .../apis/saved_objects/create.js | 2 +- .../apis/saved_objects/delete.js | 2 +- .../apis/saved_objects/export.js | 2 +- .../apis/saved_objects/find.js | 2 +- .../api_integration/apis/saved_objects/get.js | 2 +- .../apis/saved_objects/migrations.js | 2 +- .../apis/saved_objects/update.js | 2 +- .../apis/ui_metric/ui_metric.js | 2 +- test/api_integration/services/index.ts | 5 +-- test/common/services/elasticsearch.ts | 33 +++++++++++++++++++ test/common/services/es_archiver.ts | 2 +- test/common/services/index.ts | 4 ++- .../apps/management/_handle_alias.js | 2 +- .../management/_handle_version_conflict.js | 2 +- test/server_integration/config.js | 4 +-- .../actions/builtin_action_types/es_index.ts | 2 +- .../tests/actions/execute.ts | 2 +- .../tests/alerting/alerts.ts | 2 +- .../tests/alerting/create.ts | 2 +- .../tests/alerting/delete.ts | 2 +- .../tests/alerting/disable.ts | 2 +- .../tests/alerting/enable.ts | 2 +- .../actions/builtin_action_types/es_index.ts | 2 +- .../spaces_only/tests/actions/execute.ts | 2 +- .../spaces_only/tests/alerting/alerts.ts | 2 +- .../spaces_only/tests/alerting/create.ts | 2 +- .../spaces_only/tests/alerting/delete.ts | 2 +- .../spaces_only/tests/alerting/disable.ts | 2 +- .../spaces_only/tests/alerting/enable.ts | 2 +- .../apis/beats/assign_tags_to_beats.js | 2 +- .../apis/beats/create_enrollment_tokens.js | 2 +- .../api_integration/apis/beats/enroll_beat.js | 2 +- .../api_integration/apis/beats/get_beat.js | 2 +- .../test/api_integration/apis/beats/index.js | 2 +- .../apis/beats/remove_tags_from_beats.js | 2 +- .../api_integration/apis/beats/set_config.js | 2 +- .../api_integration/apis/beats/set_tag.js | 2 +- .../api_integration/apis/beats/update_beat.js | 2 +- .../api_integration/apis/es/has_privileges.js | 4 +-- .../apis/es/post_privileges.js | 2 +- .../api_integration/apis/lens/telemetry.ts | 2 +- .../apis/logstash/cluster/load.js | 2 +- .../follower_indices.js | 2 +- .../index_lifecycle_management/indices.js | 2 +- .../index_lifecycle_management/nodes.js | 2 +- .../index_lifecycle_management/policies.js | 2 +- .../index_lifecycle_management/templates.js | 2 +- .../management/index_management/indices.js | 2 +- .../management/index_management/mapping.js | 2 +- .../management/index_management/settings.js | 2 +- .../apis/management/index_management/stats.js | 2 +- .../management/index_management/templates.js | 2 +- .../rollup/index_patterns_extensions.js | 2 +- .../apis/management/rollup/rollup.js | 2 +- .../apis/management/rollup/rollup_search.js | 2 +- .../apis/monitoring/common/mappings_exist.js | 2 +- .../api_integration/apis/security/roles.js | 2 +- .../telemetry/telemetry_optin_notice_seen.ts | 2 +- .../apis/uptime/graphql/monitor_states.ts | 2 +- .../test/api_integration/apis/uptime/index.js | 2 +- x-pack/test/api_integration/services/index.ts | 2 +- .../apps/rollup_job/hybrid_index_pattern.js | 2 +- .../functional/apps/rollup_job/rollup_jobs.js | 2 +- .../services/machine_learning/api.ts | 2 +- .../functional/services/transform_ui/api.ts | 2 +- .../apis/security/kerberos_login.ts | 2 +- .../test/kerberos_api_integration/services.ts | 2 +- .../apis/authorization_code_flow/oidc_auth.js | 2 +- x-pack/test/oidc_api_integration/services.ts | 2 +- .../encrypted_saved_objects_api.ts | 2 +- .../task_manager/task_manager_integration.js | 2 +- .../apis/security/saml_login.ts | 2 +- x-pack/test/saml_api_integration/config.ts | 2 +- x-pack/test/saml_api_integration/services.ts | 2 +- .../common/services/index.ts | 2 +- .../security_and_spaces/apis/bulk_create.ts | 2 +- .../security_and_spaces/apis/create.ts | 2 +- .../security_and_spaces/apis/import.ts | 2 +- .../security_and_spaces/apis/index.ts | 2 +- .../apis/resolve_import_errors.ts | 2 +- .../security_only/apis/bulk_create.ts | 2 +- .../security_only/apis/create.ts | 2 +- .../security_only/apis/import.ts | 2 +- .../security_only/apis/index.ts | 2 +- .../apis/resolve_import_errors.ts | 2 +- .../spaces_only/apis/bulk_create.ts | 2 +- .../spaces_only/apis/create.ts | 2 +- .../spaces_only/apis/import.ts | 2 +- .../spaces_only/apis/resolve_import_errors.ts | 2 +- .../spaces_api_integration/common/config.ts | 2 +- .../security_and_spaces/apis/copy_to_space.ts | 2 +- .../security_and_spaces/apis/delete.ts | 2 +- .../security_and_spaces/apis/index.ts | 2 +- .../spaces_only/apis/copy_to_space.ts | 2 +- .../spaces_only/apis/delete.ts | 2 +- .../test/token_api_integration/auth/header.js | 2 +- .../token_api_integration/auth/session.js | 2 +- x-pack/test/token_api_integration/config.js | 2 +- .../upgrade_assistant_integration/config.js | 4 +-- .../upgrade_assistant/reindexing.js | 2 +- 107 files changed, 143 insertions(+), 113 deletions(-) create mode 100644 test/common/services/elasticsearch.ts diff --git a/test/api_integration/apis/home/sample_data.js b/test/api_integration/apis/home/sample_data.js index 7ca66e87a93254..042f490768af09 100644 --- a/test/api_integration/apis/home/sample_data.js +++ b/test/api_integration/apis/home/sample_data.js @@ -22,7 +22,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const MILLISECOND_IN_WEEK = 1000 * 60 * 60 * 24 * 7; diff --git a/test/api_integration/apis/index_patterns/es_errors/errors.js b/test/api_integration/apis/index_patterns/es_errors/errors.js index 4e50b965211c29..77e024c9d20ccb 100644 --- a/test/api_integration/apis/index_patterns/es_errors/errors.js +++ b/test/api_integration/apis/index_patterns/es_errors/errors.js @@ -34,7 +34,7 @@ import { } from './lib'; export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('index_patterns/* error handler', () => { diff --git a/test/api_integration/apis/kql_telemetry/kql_telemetry.js b/test/api_integration/apis/kql_telemetry/kql_telemetry.js index 87d06ee9458d63..25a68bb4bb2b64 100644 --- a/test/api_integration/apis/kql_telemetry/kql_telemetry.js +++ b/test/api_integration/apis/kql_telemetry/kql_telemetry.js @@ -24,7 +24,7 @@ import { get } from 'lodash'; export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); describe('telemetry API', () => { before(() => esArchiver.load('saved_objects/basic')); diff --git a/test/api_integration/apis/management/saved_objects/find.js b/test/api_integration/apis/management/saved_objects/find.js index 0e7cf08fa5c266..6bb3c0cebddbfc 100644 --- a/test/api_integration/apis/management/saved_objects/find.js +++ b/test/api_integration/apis/management/saved_objects/find.js @@ -20,7 +20,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); diff --git a/test/api_integration/apis/saved_objects/bulk_create.js b/test/api_integration/apis/saved_objects/bulk_create.js index e77e08d949f2bf..3a520d369120d6 100644 --- a/test/api_integration/apis/saved_objects/bulk_create.js +++ b/test/api_integration/apis/saved_objects/bulk_create.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const BULK_REQUESTS = [ diff --git a/test/api_integration/apis/saved_objects/bulk_get.js b/test/api_integration/apis/saved_objects/bulk_get.js index 8c5b589a12a2e4..52733aa70200b2 100644 --- a/test/api_integration/apis/saved_objects/bulk_get.js +++ b/test/api_integration/apis/saved_objects/bulk_get.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const BULK_REQUESTS = [ diff --git a/test/api_integration/apis/saved_objects/bulk_update.js b/test/api_integration/apis/saved_objects/bulk_update.js index 4bdf257ceef024..b38934aecd0fbf 100644 --- a/test/api_integration/apis/saved_objects/bulk_update.js +++ b/test/api_integration/apis/saved_objects/bulk_update.js @@ -22,7 +22,7 @@ import _ from 'lodash'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); diff --git a/test/api_integration/apis/saved_objects/create.js b/test/api_integration/apis/saved_objects/create.js index eefd9e8ab1a95c..363aa9d30c08d1 100644 --- a/test/api_integration/apis/saved_objects/create.js +++ b/test/api_integration/apis/saved_objects/create.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('create', () => { diff --git a/test/api_integration/apis/saved_objects/delete.js b/test/api_integration/apis/saved_objects/delete.js index a9037bf697406b..8aa76e99312b05 100644 --- a/test/api_integration/apis/saved_objects/delete.js +++ b/test/api_integration/apis/saved_objects/delete.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('delete', () => { diff --git a/test/api_integration/apis/saved_objects/export.js b/test/api_integration/apis/saved_objects/export.js index 9ab7a09309952a..59c9afe24b8025 100644 --- a/test/api_integration/apis/saved_objects/export.js +++ b/test/api_integration/apis/saved_objects/export.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('export', () => { diff --git a/test/api_integration/apis/saved_objects/find.js b/test/api_integration/apis/saved_objects/find.js index 7b2b15d298ce02..e1bec19cf8e6ae 100644 --- a/test/api_integration/apis/saved_objects/find.js +++ b/test/api_integration/apis/saved_objects/find.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('find', () => { diff --git a/test/api_integration/apis/saved_objects/get.js b/test/api_integration/apis/saved_objects/get.js index fb4b6f91b8bb81..9034bc5d84a721 100644 --- a/test/api_integration/apis/saved_objects/get.js +++ b/test/api_integration/apis/saved_objects/get.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('get', () => { diff --git a/test/api_integration/apis/saved_objects/migrations.js b/test/api_integration/apis/saved_objects/migrations.js index 5c492951ec9384..c4b258d47e24b4 100644 --- a/test/api_integration/apis/saved_objects/migrations.js +++ b/test/api_integration/apis/saved_objects/migrations.js @@ -31,7 +31,7 @@ import { SavedObjectsSerializer } from '../../../../src/core/server/saved_object import { SavedObjectsSchema } from '../../../../src/core/server/saved_objects/schema'; export default ({ getService }) => { - const es = getService('es'); + const es = getService('legacyEs'); const callCluster = (path, ...args) => _.get(es, path).call(es, ...args); describe('Kibana index migration', () => { diff --git a/test/api_integration/apis/saved_objects/update.js b/test/api_integration/apis/saved_objects/update.js index e6ad6b2b781dab..c73ed0ecc6424f 100644 --- a/test/api_integration/apis/saved_objects/update.js +++ b/test/api_integration/apis/saved_objects/update.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('update', () => { diff --git a/test/api_integration/apis/ui_metric/ui_metric.js b/test/api_integration/apis/ui_metric/ui_metric.js index f0c86f2904638c..51959bf5f7fda8 100644 --- a/test/api_integration/apis/ui_metric/ui_metric.js +++ b/test/api_integration/apis/ui_metric/ui_metric.js @@ -22,7 +22,7 @@ import { ReportManager, METRIC_TYPE } from '@kbn/analytics'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const createStatsMetric = (eventName) => ({ key: ReportManager.createMetricKey({ appName: 'myApp', type: METRIC_TYPE.CLICK, eventName }), diff --git a/test/api_integration/services/index.ts b/test/api_integration/services/index.ts index 573450cae534a4..782ea271869ba4 100644 --- a/test/api_integration/services/index.ts +++ b/test/api_integration/services/index.ts @@ -23,10 +23,7 @@ import { services as commonServices } from '../../common/services'; import { KibanaSupertestProvider, ElasticsearchSupertestProvider } from './supertest'; export const services = { - es: commonServices.es, - esArchiver: commonServices.esArchiver, - retry: commonServices.retry, + ...commonServices, supertest: KibanaSupertestProvider, esSupertest: ElasticsearchSupertestProvider, - randomness: commonServices.randomness, }; diff --git a/test/common/services/elasticsearch.ts b/test/common/services/elasticsearch.ts new file mode 100644 index 00000000000000..63c4bfeeb4ce77 --- /dev/null +++ b/test/common/services/elasticsearch.ts @@ -0,0 +1,33 @@ +/* + * 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 { format as formatUrl } from 'url'; + +import { Client } from '@elastic/elasticsearch'; + +import { FtrProviderContext } from '../ftr_provider_context'; + +export function ElasticsearchProvider({ getService }: FtrProviderContext) { + const config = getService('config'); + + return new Client({ + nodes: [formatUrl(config.get('servers.elasticsearch'))], + requestTimeout: config.get('timeouts.esRequestTimeout'), + }); +} diff --git a/test/common/services/es_archiver.ts b/test/common/services/es_archiver.ts index e72bb49a76c0dc..cfe0610414b4fc 100644 --- a/test/common/services/es_archiver.ts +++ b/test/common/services/es_archiver.ts @@ -26,7 +26,7 @@ import * as KibanaServer from './kibana_server'; export function EsArchiverProvider({ getService, hasService }: FtrProviderContext): EsArchiver { const config = getService('config'); - const client = getService('es'); + const client = getService('legacyEs'); const log = getService('log'); if (!config.get('esArchiver')) { diff --git a/test/common/services/index.ts b/test/common/services/index.ts index 225aacc1c98958..3454964f35e070 100644 --- a/test/common/services/index.ts +++ b/test/common/services/index.ts @@ -18,13 +18,15 @@ */ import { LegacyEsProvider } from './legacy_es'; +import { ElasticsearchProvider } from './elasticsearch'; import { EsArchiverProvider } from './es_archiver'; import { KibanaServerProvider } from './kibana_server'; import { RetryProvider } from './retry'; import { RandomnessProvider } from './randomness'; export const services = { - es: LegacyEsProvider, + legacyEs: LegacyEsProvider, + es: ElasticsearchProvider, esArchiver: EsArchiverProvider, kibanaServer: KibanaServerProvider, retry: RetryProvider, diff --git a/test/functional/apps/management/_handle_alias.js b/test/functional/apps/management/_handle_alias.js index 1556897d69387c..a5994fc5dd1b49 100644 --- a/test/functional/apps/management/_handle_alias.js +++ b/test/functional/apps/management/_handle_alias.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'home', 'settings', 'discover', 'timePicker']); diff --git a/test/functional/apps/management/_handle_version_conflict.js b/test/functional/apps/management/_handle_version_conflict.js index 217e6d4c1a8d38..e6c0825136ba10 100644 --- a/test/functional/apps/management/_handle_version_conflict.js +++ b/test/functional/apps/management/_handle_version_conflict.js @@ -32,7 +32,7 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const browser = getService('browser'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const scriptedFiledName = 'versionConflictScript'; const PageObjects = getPageObjects(['common', 'home', 'settings', 'discover', 'header']); diff --git a/test/server_integration/config.js b/test/server_integration/config.js index 18575fcb5fcff4..77aeaa8af3b9f9 100644 --- a/test/server_integration/config.js +++ b/test/server_integration/config.js @@ -29,9 +29,7 @@ export default async function ({ readConfigFile }) { return { services: { - es: commonConfig.get('services.es'), - esArchiver: commonConfig.get('services.esArchiver'), - retry: commonConfig.get('services.retry'), + ...commonConfig.get('services'), supertest: KibanaSupertestProvider, supertestWithoutAuth: KibanaSupertestWithoutAuthProvider, esSupertest: ElasticsearchSupertestProvider, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts index b9b40be3a04b3e..648944a9256b29 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts @@ -12,7 +12,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts index 44970a9260c42f..0c05ad3e3e68aa 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts @@ -18,7 +18,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts index 0a300c4ce65da4..c43e159bbe8ca5 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts @@ -20,7 +20,7 @@ import { // eslint-disable-next-line import/no-default-export export default function alertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const esTestIndexTool = new ESTestIndexTool(es, retry); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts index bd0226d024d1fd..d94556d6cedda3 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('create', () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts index 6d5147e9f87b81..aab683df097404 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDeleteTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('delete', () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts index 8a9b7e3fc35c44..d2076e0f92b3c3 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDisableAlertTests({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts index 543805fb83b189..528db61dba21ca 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createEnableAlertTests({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts index 74a1255dacfe59..7e971d033b5c42 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts @@ -12,7 +12,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts index ba8a5aa9160a53..e97b6d480c4703 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts @@ -17,7 +17,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts index badec079d68285..28634c46b6350a 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts @@ -19,7 +19,7 @@ import { // eslint-disable-next-line import/no-default-export export default function alertTests({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts index 17ec83b5b4f18a..80459690af7329 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('create', () => { const objectRemover = new ObjectRemover(supertest); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts index 3ef501cfaa5887..3aea982f948ea2 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDeleteTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('delete', () => { const objectRemover = new ObjectRemover(supertest); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts index 664e74835d4158..750f94201216a7 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDisableAlertTests({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('disable', () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts index 2a8de1f6e31c37..00cd40c0e80cd5 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createEnableAlertTests({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('enable', () => { diff --git a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js index 27435d49c252fa..e4637d3807d4da 100644 --- a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js +++ b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js @@ -10,7 +10,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const randomness = getService('randomness'); describe('assign_tags_to_beats', () => { diff --git a/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js b/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js index 6cd4fdf22bb41f..09cfb33e4fad24 100644 --- a/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js +++ b/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js @@ -10,7 +10,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('create_enrollment_token', () => { it('should create one token by default', async () => { diff --git a/x-pack/test/api_integration/apis/beats/enroll_beat.js b/x-pack/test/api_integration/apis/beats/enroll_beat.js index 4b4767e1d98497..59c42db7c1f81b 100644 --- a/x-pack/test/api_integration/apis/beats/enroll_beat.js +++ b/x-pack/test/api_integration/apis/beats/enroll_beat.js @@ -12,7 +12,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); const randomness = getService('randomness'); - const es = getService('es'); + const es = getService('legacyEs'); describe('enroll_beat', () => { let validEnrollmentToken; diff --git a/x-pack/test/api_integration/apis/beats/get_beat.js b/x-pack/test/api_integration/apis/beats/get_beat.js index 07cc056e3af990..03667a53920c96 100644 --- a/x-pack/test/api_integration/apis/beats/get_beat.js +++ b/x-pack/test/api_integration/apis/beats/get_beat.js @@ -10,7 +10,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); describe('get_beat_configuration', () => { const archive = 'beats/list'; diff --git a/x-pack/test/api_integration/apis/beats/index.js b/x-pack/test/api_integration/apis/beats/index.js index da47fdbf77fc7a..8ca7390ad5b1fc 100644 --- a/x-pack/test/api_integration/apis/beats/index.js +++ b/x-pack/test/api_integration/apis/beats/index.js @@ -7,7 +7,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService, loadTestFile }) { - const es = getService('es'); + const es = getService('legacyEs'); describe('beats', () => { const cleanup = () => diff --git a/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js b/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js index 1548aff1182b33..dde8916dd24d5a 100644 --- a/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js +++ b/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js @@ -10,7 +10,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const randomness = getService('randomness'); describe('remove_tags_from_beats', () => { diff --git a/x-pack/test/api_integration/apis/beats/set_config.js b/x-pack/test/api_integration/apis/beats/set_config.js index 5e15145cf47c8e..21a09333dc31a2 100644 --- a/x-pack/test/api_integration/apis/beats/set_config.js +++ b/x-pack/test/api_integration/apis/beats/set_config.js @@ -9,7 +9,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('set_config', () => { diff --git a/x-pack/test/api_integration/apis/beats/set_tag.js b/x-pack/test/api_integration/apis/beats/set_tag.js index ee9a601b25096c..630c3772b1661a 100644 --- a/x-pack/test/api_integration/apis/beats/set_tag.js +++ b/x-pack/test/api_integration/apis/beats/set_tag.js @@ -9,7 +9,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('set_tag', () => { it('should create a tag', async () => { diff --git a/x-pack/test/api_integration/apis/beats/update_beat.js b/x-pack/test/api_integration/apis/beats/update_beat.js index 228d651a590e6e..82582b553886c5 100644 --- a/x-pack/test/api_integration/apis/beats/update_beat.js +++ b/x-pack/test/api_integration/apis/beats/update_beat.js @@ -11,7 +11,7 @@ import moment from 'moment'; export default function ({ getService }) { const supertest = getService('supertest'); const randomness = getService('randomness'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('update_beat', () => { diff --git a/x-pack/test/api_integration/apis/es/has_privileges.js b/x-pack/test/api_integration/apis/es/has_privileges.js index 5cbbefd8f2f370..37d6d734995524 100644 --- a/x-pack/test/api_integration/apis/es/has_privileges.js +++ b/x-pack/test/api_integration/apis/es/has_privileges.js @@ -11,7 +11,7 @@ export default function ({ getService }) { describe('has_privileges', () => { before(async () => { - const es = getService('es'); + const es = getService('legacyEs'); await es.shield.postPrivileges({ body: { @@ -104,7 +104,7 @@ export default function ({ getService }) { }); // Create privilege - const es = getService('es'); + const es = getService('legacyEs'); await es.shield.postPrivileges({ body: { [application]: { diff --git a/x-pack/test/api_integration/apis/es/post_privileges.js b/x-pack/test/api_integration/apis/es/post_privileges.js index 4b1695487f832c..1c8f723b7a278a 100644 --- a/x-pack/test/api_integration/apis/es/post_privileges.js +++ b/x-pack/test/api_integration/apis/es/post_privileges.js @@ -9,7 +9,7 @@ export default function ({ getService }) { describe('post_privileges', () => { it('should allow privileges to be updated', async () => { - const es = getService('es'); + const es = getService('legacyEs'); const application = 'foo'; const response = await es.shield.postPrivileges({ body: { diff --git a/x-pack/test/api_integration/apis/lens/telemetry.ts b/x-pack/test/api_integration/apis/lens/telemetry.ts index 6428ef9f478d4a..5e6830c8f4689b 100644 --- a/x-pack/test/api_integration/apis/lens/telemetry.ts +++ b/x-pack/test/api_integration/apis/lens/telemetry.ts @@ -22,7 +22,7 @@ const COMMON_HEADERS = { // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); - const es: Client = getService('es'); + const es: Client = getService('legacyEs'); const callCluster: CallCluster = (((path: 'search', searchParams: SearchParams) => { return es[path].call(es, searchParams); }) as unknown) as CallCluster; diff --git a/x-pack/test/api_integration/apis/logstash/cluster/load.js b/x-pack/test/api_integration/apis/logstash/cluster/load.js index a20c524f0a8f8a..36b992559e15b8 100644 --- a/x-pack/test/api_integration/apis/logstash/cluster/load.js +++ b/x-pack/test/api_integration/apis/logstash/cluster/load.js @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('load', () => { it('should return the ES cluster info', async () => { diff --git a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js index 8ed10ccf31dce8..cd128d92498cf5 100644 --- a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js +++ b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js @@ -14,7 +14,7 @@ import { registerHelpers as registerFollowerIndicesnHelpers } from './follower_i export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { addCluster, deleteAllClusters } = registerRemoteClustersHelpers(supertest); const { diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/indices.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/indices.js index d0d08101e54448..020d6fc5741b9d 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/indices.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/indices.js @@ -13,7 +13,7 @@ import { getPolicyPayload } from './fixtures'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { getIndex, diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js index 5ce1d7d956d671..bc8b2af4014232 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js @@ -13,7 +13,7 @@ import { initElasticsearchHelpers } from './lib'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { getNodesStats } = initElasticsearchHelpers(es); const { loadNodes, getNodeDetails } = registerHelpers({ supertest }); diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js index c13ae4a15c97ef..598db2ddc8a650 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js @@ -15,7 +15,7 @@ import { DEFAULT_POLICY_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js index 7dcf3c995e3cea..5c6e3d0e89c81d 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js @@ -12,7 +12,7 @@ import { registerHelpers as registerPoliciesHelpers } from './policies.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndexTemplate, cleanUp: cleanUpEsResources } = initElasticsearchHelpers(es); diff --git a/x-pack/test/api_integration/apis/management/index_management/indices.js b/x-pack/test/api_integration/apis/management/index_management/indices.js index 09215eff20c692..9302b0fe0e16b2 100644 --- a/x-pack/test/api_integration/apis/management/index_management/indices.js +++ b/x-pack/test/api_integration/apis/management/index_management/indices.js @@ -11,7 +11,7 @@ import { registerHelpers } from './indices.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_management/mapping.js b/x-pack/test/api_integration/apis/management/index_management/mapping.js index 91f995a7d80453..0a2713e9407f1c 100644 --- a/x-pack/test/api_integration/apis/management/index_management/mapping.js +++ b/x-pack/test/api_integration/apis/management/index_management/mapping.js @@ -11,7 +11,7 @@ import { registerHelpers } from './mapping.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_management/settings.js b/x-pack/test/api_integration/apis/management/index_management/settings.js index dc41f530085b17..d9a9e19fe2490b 100644 --- a/x-pack/test/api_integration/apis/management/index_management/settings.js +++ b/x-pack/test/api_integration/apis/management/index_management/settings.js @@ -11,7 +11,7 @@ import { registerHelpers } from './settings.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_management/stats.js b/x-pack/test/api_integration/apis/management/index_management/stats.js index 58dac9f5b911ac..743b1f596e9d76 100644 --- a/x-pack/test/api_integration/apis/management/index_management/stats.js +++ b/x-pack/test/api_integration/apis/management/index_management/stats.js @@ -11,7 +11,7 @@ import { registerHelpers } from './stats.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_management/templates.js b/x-pack/test/api_integration/apis/management/index_management/templates.js index a6a74932184993..00a97e55c013c0 100644 --- a/x-pack/test/api_integration/apis/management/index_management/templates.js +++ b/x-pack/test/api_integration/apis/management/index_management/templates.js @@ -11,7 +11,7 @@ import { registerHelpers } from './templates.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { cleanUp: cleanUpEsResources, diff --git a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js index 25bc503682bc7f..78a04b729ba661 100644 --- a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js +++ b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js @@ -13,7 +13,7 @@ import { getRandomString } from './lib'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndexWithMappings, diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup.js b/x-pack/test/api_integration/apis/management/rollup/rollup.js index 5ac4e06adb23a9..6e99af2ba8e329 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup.js @@ -11,7 +11,7 @@ import { registerHelpers } from './rollup.test_helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndexWithMappings, diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup_search.js b/x-pack/test/api_integration/apis/management/rollup/rollup_search.js index 2a38cd563f3128..073473f202fa31 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup_search.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup_search.js @@ -12,7 +12,7 @@ import { getRandomString } from './lib'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndexWithMappings, diff --git a/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js b/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js index 6d3dbe68c77ace..2443448ccd0621 100644 --- a/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js +++ b/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js @@ -13,7 +13,7 @@ import * as beatsMetrics from '../../../../../legacy/plugins/monitoring/server/l import * as apmMetrics from '../../../../../legacy/plugins/monitoring/server/lib/metrics/apm/metrics'; export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const metricSets = [ { diff --git a/x-pack/test/api_integration/apis/security/roles.js b/x-pack/test/api_integration/apis/security/roles.js index d1d4c3c7b7af88..7108656783f526 100644 --- a/x-pack/test/api_integration/apis/security/roles.js +++ b/x-pack/test/api_integration/apis/security/roles.js @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const config = getService('config'); const basic = config.get('esTestCluster.license') === 'basic'; diff --git a/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts b/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts index de03fff7edcf70..582864795015cb 100644 --- a/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts +++ b/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts @@ -10,7 +10,7 @@ import { TelemetrySavedObjectAttributes } from '../../../../../src/legacy/core_p import { FtrProviderContext } from '../../ftr_provider_context'; export default function optInTest({ getService }: FtrProviderContext) { - const client: Client = getService('es'); + const client: Client = getService('legacyEs'); const supertest = getService('supertest'); describe('/api/telemetry/v2/optIn API Telemetry User has seen OptIn Notice', () => { diff --git a/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts b/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts index 9dca3f40c63034..c305bb99c28f79 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts +++ b/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts @@ -106,7 +106,7 @@ export default function({ getService }: FtrProviderContext) { before(async () => { const index = 'heartbeat-8.0.0'; - const es = getService('es'); + const es = getService('legacyEs'); dateRangeStart = new Date().toISOString(); checks = await makeChecks(es, index, testMonitorId, 1, numIps, {}, d => { if (d.summary) { diff --git a/x-pack/test/api_integration/apis/uptime/index.js b/x-pack/test/api_integration/apis/uptime/index.js index 8f4e4ab9a7ea10..6eb77fb584133d 100644 --- a/x-pack/test/api_integration/apis/uptime/index.js +++ b/x-pack/test/api_integration/apis/uptime/index.js @@ -5,7 +5,7 @@ */ export default function ({ getService, loadTestFile }) { - const es = getService('es'); + const es = getService('legacyEs'); describe('uptime', () => { before(() => diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index 7e3b747c81993a..4be89172e24f0b 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -30,7 +30,7 @@ export const services = { esSupertest: kibanaApiIntegrationServices.esSupertest, supertest: kibanaApiIntegrationServices.supertest, - es: LegacyEsProvider, + legacyEs: LegacyEsProvider, esSupertestWithoutAuth: EsSupertestWithoutAuthProvider, infraOpsGraphQLClient: InfraOpsGraphQLClientProvider, infraOpsGraphQLClientFactory: InfraOpsGraphQLClientFactoryProvider, diff --git a/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js b/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js index dca5534fb68b31..95bae4b24a5350 100644 --- a/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js +++ b/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js @@ -11,7 +11,7 @@ import mockRolledUpData, { mockIndices } from './hybrid_index_helper'; export default function ({ getService, getPageObjects }) { - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'settings']); diff --git a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js index eeff20105aed22..0888f0972592ec 100644 --- a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js +++ b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js @@ -11,7 +11,7 @@ import { mockIndices } from './hybrid_index_helper'; export default function ({ getService, getPageObjects }) { - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['rollup', 'common']); diff --git a/x-pack/test/functional/services/machine_learning/api.ts b/x-pack/test/functional/services/machine_learning/api.ts index 270722a97d6b61..2fc027a81ea8cf 100644 --- a/x-pack/test/functional/services/machine_learning/api.ts +++ b/x-pack/test/functional/services/machine_learning/api.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { JOB_STATE, DATAFEED_STATE } from '../../../../legacy/plugins/ml/common/constants/states'; export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const log = getService('log'); const retry = getService('retry'); const esSupertest = getService('esSupertest'); diff --git a/x-pack/test/functional/services/transform_ui/api.ts b/x-pack/test/functional/services/transform_ui/api.ts index 9050b5944dee3e..a6756e5940d72b 100644 --- a/x-pack/test/functional/services/transform_ui/api.ts +++ b/x-pack/test/functional/services/transform_ui/api.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export function TransformAPIProvider({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const log = getService('log'); const retry = getService('retry'); diff --git a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts index 0a3b7f595c66d3..450f7b1a427dc4 100644 --- a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts +++ b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts @@ -362,7 +362,7 @@ export default function({ getService }: FtrProviderContext) { // Let's delete tokens from `.security-tokens` index directly to simulate the case when // Elasticsearch automatically removes access/refresh token document from the index after // some period of time. - const esResponse = await getService('es').deleteByQuery({ + const esResponse = await getService('legacyEs').deleteByQuery({ index: '.security-tokens', q: 'doc_type:token', refresh: true, diff --git a/x-pack/test/kerberos_api_integration/services.ts b/x-pack/test/kerberos_api_integration/services.ts index 42505994e06029..e2e7a5b8844a74 100644 --- a/x-pack/test/kerberos_api_integration/services.ts +++ b/x-pack/test/kerberos_api_integration/services.ts @@ -7,7 +7,7 @@ import { services as apiIntegrationServices } from '../api_integration/services'; export const services = { - es: apiIntegrationServices.es, + legacyEs: apiIntegrationServices.legacyEs, esSupertest: apiIntegrationServices.esSupertest, supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, }; diff --git a/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.js b/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.js index 7460b1f9e238c2..80ef6bd6df4ff1 100644 --- a/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.js +++ b/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.js @@ -482,7 +482,7 @@ export default function ({ getService }) { // Let's delete tokens from `.security-tokens` index directly to simulate the case when // Elasticsearch automatically removes access/refresh token document from the index // after some period of time. - const esResponse = await getService('es').deleteByQuery({ + const esResponse = await getService('legacyEs').deleteByQuery({ index: '.security-tokens', q: 'doc_type:token', refresh: true, diff --git a/x-pack/test/oidc_api_integration/services.ts b/x-pack/test/oidc_api_integration/services.ts index e4ff6048a8cce3..dda9f1d1a88863 100644 --- a/x-pack/test/oidc_api_integration/services.ts +++ b/x-pack/test/oidc_api_integration/services.ts @@ -7,6 +7,6 @@ import { services as apiIntegrationServices } from '../api_integration/services'; export const services = { - es: apiIntegrationServices.es, + legacyEs: apiIntegrationServices.legacyEs, supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, }; diff --git a/x-pack/test/plugin_api_integration/test_suites/encrypted_saved_objects/encrypted_saved_objects_api.ts b/x-pack/test/plugin_api_integration/test_suites/encrypted_saved_objects/encrypted_saved_objects_api.ts index 98d653d71b5ec3..ab9f7d2cdd3395 100644 --- a/x-pack/test/plugin_api_integration/test_suites/encrypted_saved_objects/encrypted_saved_objects_api.ts +++ b/x-pack/test/plugin_api_integration/test_suites/encrypted_saved_objects/encrypted_saved_objects_api.ts @@ -9,7 +9,7 @@ import { SavedObject } from 'src/core/server'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const randomness = getService('randomness'); const supertest = getService('supertest'); diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js index a8ff03dc71d247..9b4297e995cbd8 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js @@ -12,7 +12,7 @@ import supertestAsPromised from 'supertest-as-promised'; const { task: { properties: taskManagerIndexMapping } } = require('../../../../legacy/plugins/task_manager/mappings.json'); export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const log = getService('log'); const retry = getService('retry'); const config = getService('config'); diff --git a/x-pack/test/saml_api_integration/apis/security/saml_login.ts b/x-pack/test/saml_api_integration/apis/security/saml_login.ts index 276b42423860cb..d512894fbb1f24 100644 --- a/x-pack/test/saml_api_integration/apis/security/saml_login.ts +++ b/x-pack/test/saml_api_integration/apis/security/saml_login.ts @@ -622,7 +622,7 @@ export default function({ getService }: FtrProviderContext) { // Let's delete tokens from `.security` index directly to simulate the case when // Elasticsearch automatically removes access/refresh token document from the index // after some period of time. - const esResponse = await getService('es').deleteByQuery({ + const esResponse = await getService('legacyEs').deleteByQuery({ index: '.security-tokens', q: 'doc_type:token', refresh: true, diff --git a/x-pack/test/saml_api_integration/config.ts b/x-pack/test/saml_api_integration/config.ts index 9d3029db013d3c..6ea29b0d9e56e3 100644 --- a/x-pack/test/saml_api_integration/config.ts +++ b/x-pack/test/saml_api_integration/config.ts @@ -21,7 +21,7 @@ export default async function({ readConfigFile }: FtrConfigProviderContext) { servers: xPackAPITestsConfig.get('servers'), services: { randomness: kibanaAPITestsConfig.get('services.randomness'), - es: kibanaAPITestsConfig.get('services.es'), + legacyEs: kibanaAPITestsConfig.get('services.legacyEs'), supertestWithoutAuth: xPackAPITestsConfig.get('services.supertestWithoutAuth'), }, junit: { diff --git a/x-pack/test/saml_api_integration/services.ts b/x-pack/test/saml_api_integration/services.ts index 307108fa097f40..d207112f6e81fa 100644 --- a/x-pack/test/saml_api_integration/services.ts +++ b/x-pack/test/saml_api_integration/services.ts @@ -8,6 +8,6 @@ import { services as apiIntegrationServices } from '../api_integration/services' export const services = { randomness: apiIntegrationServices.randomness, - es: apiIntegrationServices.es, + legacyEs: apiIntegrationServices.legacyEs, supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, }; diff --git a/x-pack/test/saved_object_api_integration/common/services/index.ts b/x-pack/test/saved_object_api_integration/common/services/index.ts index 1ea312714fc1e9..aba605fee89471 100644 --- a/x-pack/test/saved_object_api_integration/common/services/index.ts +++ b/x-pack/test/saved_object_api_integration/common/services/index.ts @@ -12,7 +12,7 @@ import { services as kibanaApiIntegrationServices } from '../../../../../test/ap import { services as kibanaFunctionalServices } from '../../../../../test/functional/services'; export const services = { - es: LegacyEsProvider, + legacyEs: LegacyEsProvider, esSupertestWithoutAuth: apiIntegrationServices.esSupertestWithoutAuth, supertest: kibanaApiIntegrationServices.supertest, supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts index 7e00d0a9d7f759..7768665f3b941a 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts @@ -12,7 +12,7 @@ import { bulkCreateTestSuiteFactory } from '../../common/suites/bulk_create'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { bulkCreateTest, diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts index 4cc94bf21f235d..e4adaa580c1dbe 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts @@ -11,7 +11,7 @@ import { createTestSuiteFactory } from '../../common/suites/create'; export default function({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const { diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts index f9048d1493cc63..58859c292ce359 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts @@ -12,7 +12,7 @@ import { importTestSuiteFactory } from '../../common/suites/import'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { importTest, diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts index 1b1e9762a54e5d..bb42c5422ece51 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts @@ -8,7 +8,7 @@ import { createUsersAndRoles } from '../../common/lib/create_users_and_roles'; import { FtrProviderContext } from '../../common/ftr_provider_context'; export default function({ getService, loadTestFile }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); describe('saved objects security and spaces enabled', function() { diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts index fa070ac76ce572..6c91fe6310170d 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts @@ -12,7 +12,7 @@ import { resolveImportErrorsTestSuiteFactory } from '../../common/suites/resolve export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { resolveImportErrorsTest, diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts index 2a5757fb0cc579..943a22c4399c77 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts @@ -11,7 +11,7 @@ import { bulkCreateTestSuiteFactory } from '../../common/suites/bulk_create'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { bulkCreateTest, diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/create.ts b/x-pack/test/saved_object_api_integration/security_only/apis/create.ts index bb2bf7e0e0d7ad..60a9fa0a86aa65 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/create.ts @@ -10,7 +10,7 @@ import { createTestSuiteFactory } from '../../common/suites/create'; export default function({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const { diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/import.ts b/x-pack/test/saved_object_api_integration/security_only/apis/import.ts index 8ad7e070edf546..770410dcfed819 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/import.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/import.ts @@ -11,7 +11,7 @@ import { importTestSuiteFactory } from '../../common/suites/import'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { importTest, diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/index.ts b/x-pack/test/saved_object_api_integration/security_only/apis/index.ts index 6e930338a11845..bb637a9bc4c90e 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/index.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/index.ts @@ -8,7 +8,7 @@ import { createUsersAndRoles } from '../../common/lib/create_users_and_roles'; import { FtrProviderContext } from '../../common/ftr_provider_context'; export default function({ getService, loadTestFile }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); describe('saved objects security only enabled', function() { diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts index e1d72f8641e936..59d50c16c259a8 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts @@ -11,7 +11,7 @@ import { resolveImportErrorsTestSuiteFactory } from '../../common/suites/resolve export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { resolveImportErrorsTest, diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts index 6b67c63ed349ae..d89e3b4f8605be 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts @@ -25,7 +25,7 @@ const expectNamespaceSpecifiedBadRequest = (resp: { [key: string]: any }) => { export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { bulkCreateTest, diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts index d6bd0b497759fc..cf34f7505cdb20 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts @@ -23,7 +23,7 @@ const expectNamespaceSpecifiedBadRequest = (resp: { [key: string]: any }) => { export default function({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const { diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts index c8b2e68291dc39..c78a0e1cc2ccec 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts @@ -11,7 +11,7 @@ import { importTestSuiteFactory } from '../../common/suites/import'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { importTest, diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts index 93d60ebbf4d6d4..22a7ab81e5530f 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts @@ -11,7 +11,7 @@ import { resolveImportErrorsTestSuiteFactory } from '../../common/suites/resolve export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { resolveImportErrorsTest, diff --git a/x-pack/test/spaces_api_integration/common/config.ts b/x-pack/test/spaces_api_integration/common/config.ts index 23514c635d3562..dffc6c524cc6ec 100644 --- a/x-pack/test/spaces_api_integration/common/config.ts +++ b/x-pack/test/spaces_api_integration/common/config.ts @@ -34,7 +34,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) testFiles: [require.resolve(`../${name}/apis/`)], servers: config.xpack.api.get('servers'), services: { - es: LegacyEsProvider, + legacyEs: LegacyEsProvider, esSupertestWithoutAuth: config.xpack.api.get('services.esSupertestWithoutAuth'), supertest: config.kibana.api.get('services.supertest'), supertestWithoutAuth: config.xpack.api.get('services.supertestWithoutAuth'), diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts index c6c41f7cd3a977..1c4ca2fe206628 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts @@ -13,7 +13,7 @@ import { copyToSpaceTestSuiteFactory } from '../../common/suites/copy_to_space'; export default function copyToSpaceSpacesAndSecuritySuite({ getService }: TestInvoker) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { copyToSpaceTest, diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/delete.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/delete.ts index 25d7317d7dd906..df4a2f51b4872a 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/delete.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/delete.ts @@ -13,7 +13,7 @@ import { deleteTestSuiteFactory } from '../../common/suites/delete'; export default function deleteSpaceTestSuite({ getService }: TestInvoker) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { deleteTest, diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts index 300949f41f0369..e918ab0b538418 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts @@ -9,7 +9,7 @@ import { TestInvoker } from '../../common/lib/types'; // eslint-disable-next-line import/no-default-export export default function({ loadTestFile, getService }: TestInvoker) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); describe('spaces api with security', function() { diff --git a/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts b/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts index b1427a9b77be06..4781c4bea9b30d 100644 --- a/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts +++ b/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts @@ -11,7 +11,7 @@ import { copyToSpaceTestSuiteFactory } from '../../common/suites/copy_to_space'; export default function copyToSpacesOnlySuite({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { copyToSpaceTest, diff --git a/x-pack/test/spaces_api_integration/spaces_only/apis/delete.ts b/x-pack/test/spaces_api_integration/spaces_only/apis/delete.ts index 350b6824297784..64cbb7a02776c1 100644 --- a/x-pack/test/spaces_api_integration/spaces_only/apis/delete.ts +++ b/x-pack/test/spaces_api_integration/spaces_only/apis/delete.ts @@ -12,7 +12,7 @@ import { deleteTestSuiteFactory } from '../../common/suites/delete'; export default function deleteSpaceTestSuite({ getService }: TestInvoker) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { deleteTest, diff --git a/x-pack/test/token_api_integration/auth/header.js b/x-pack/test/token_api_integration/auth/header.js index 2317f62e638091..4b27fd5db31663 100644 --- a/x-pack/test/token_api_integration/auth/header.js +++ b/x-pack/test/token_api_integration/auth/header.js @@ -6,7 +6,7 @@ export default function ({ getService }) { const supertest = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); async function createToken() { const { access_token: accessToken } = await es.shield.getAccessToken({ diff --git a/x-pack/test/token_api_integration/auth/session.js b/x-pack/test/token_api_integration/auth/session.js index 60450218948230..8a9f1d7a3f2295 100644 --- a/x-pack/test/token_api_integration/auth/session.js +++ b/x-pack/test/token_api_integration/auth/session.js @@ -132,7 +132,7 @@ export default function ({ getService }) { // Let's delete tokens from `.security` index directly to simulate the case when // Elasticsearch automatically removes access/refresh token document from the index // after some period of time. - const esResponse = await getService('es').deleteByQuery({ + const esResponse = await getService('legacyEs').deleteByQuery({ index: '.security-tokens', q: 'doc_type:token', refresh: true, diff --git a/x-pack/test/token_api_integration/config.js b/x-pack/test/token_api_integration/config.js index 44086245a90c0b..8cf9bc329a3744 100644 --- a/x-pack/test/token_api_integration/config.js +++ b/x-pack/test/token_api_integration/config.js @@ -11,7 +11,7 @@ export default async function ({ readConfigFile }) { testFiles: [require.resolve('./auth')], servers: xPackAPITestsConfig.get('servers'), services: { - es: xPackAPITestsConfig.get('services.es'), + legacyEs: xPackAPITestsConfig.get('services.legacyEs'), supertestWithoutAuth: xPackAPITestsConfig.get('services.supertestWithoutAuth'), }, junit: { diff --git a/x-pack/test/upgrade_assistant_integration/config.js b/x-pack/test/upgrade_assistant_integration/config.js index 4cd4ca78d3a588..3a43d43543b61b 100644 --- a/x-pack/test/upgrade_assistant_integration/config.js +++ b/x-pack/test/upgrade_assistant_integration/config.js @@ -20,9 +20,9 @@ export default async function ({ readConfigFile }) { testFiles: [require.resolve('./upgrade_assistant')], servers: xPackFunctionalTestsConfig.get('servers'), services: { + ...kibanaCommonConfig.get('services'), supertest: kibanaAPITestsConfig.get('services.supertest'), - es: LegacyEsProvider, - esArchiver: kibanaCommonConfig.get('services.esArchiver'), + legacyEs: LegacyEsProvider, }, esArchiver: xPackFunctionalTestsConfig.get('esArchiver'), junit: { diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js index 233336c722611b..137de18fc98d9b 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js @@ -12,7 +12,7 @@ import { ReindexStatus, REINDEX_OP_TYPE } from '../../../legacy/plugins/upgrade_ export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); // Utility function that keeps polling API until reindex operation has completed or failed. const waitForReindexToComplete = async (indexName) => { From 052745e0c92233b47efaf5e29e56f212a4523bb3 Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Wed, 20 Nov 2019 17:56:52 +0200 Subject: [PATCH 12/29] Deprecate filter-bar directive (#51149) * Deprecate filter bar directive * fix tsvb \ metric \ timelion tests --- .../public/filter/filter_bar/filter_bar.tsx | 42 ++--------------- .../data/public/shim/legacy_module.ts | 47 ------------------- .../public/dashboard/dashboard_app.html | 3 +- .../public/discover/angular/context_app.html | 13 +++-- .../public/visualize/editor/editor.html | 18 +++++-- .../kibana/public/visualize/editor/editor.js | 6 +++ 6 files changed, 34 insertions(+), 95 deletions(-) diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx index 5b389f5b98aba1..23c9c9ffc94bbe 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx @@ -21,13 +21,12 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiPopover } from '@elastic/ import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import classNames from 'classnames'; import React, { useState } from 'react'; -import { CoreStart } from 'src/core/public'; import { IndexPattern } from '../../index_patterns'; import { FilterEditor } from './filter_editor'; import { FilterItem } from './filter_item'; import { FilterOptions } from './filter_options'; -import { useKibana, KibanaContextProvider } from '../../../../../../plugins/kibana_react/public'; -import { DataPublicPluginStart, esFilters } from '../../../../../../plugins/data/public'; +import { useKibana } from '../../../../../../plugins/kibana_react/public'; +import { esFilters } from '../../../../../../plugins/data/public'; interface Props { filters: esFilters.Filter[]; @@ -35,48 +34,15 @@ interface Props { className: string; indexPatterns: IndexPattern[]; intl: InjectedIntl; - - // TODO: Only for filter-bar directive! - uiSettings?: CoreStart['uiSettings']; - docLinks?: CoreStart['docLinks']; - pluginDataStart?: DataPublicPluginStart; } function FilterBarUI(props: Props) { const [isAddFilterPopoverOpen, setIsAddFilterPopoverOpen] = useState(false); const kibana = useKibana(); - const uiSettings = kibana.services.uiSettings || props.uiSettings; + const uiSettings = kibana.services.uiSettings; if (!uiSettings) return null; - function hasContext() { - return Boolean(kibana.services.uiSettings); - } - - function wrapInContextIfMissing(content: JSX.Element) { - // TODO: Relevant only as long as directives are used! - if (!hasContext()) { - if (props.docLinks && props.uiSettings && props.pluginDataStart) { - return ( - - {content} - - ); - } else { - throw new Error( - 'Rending filter bar requires providing sufficient context: uiSettings, docLinks and NP data plugin' - ); - } - } - return content; - } - function onFiltersUpdated(filters: esFilters.Filter[]) { if (props.onFiltersUpdated) { props.onFiltersUpdated(filters); @@ -119,7 +85,7 @@ function FilterBarUI(props: Props) { ); - return wrapInContextIfMissing( + return ( { - uiModules - .get('app/kibana', ['react']) - .directive('filterBar', () => { - return { - restrict: 'E', - template: '', - compile: (elem: any) => { - const child = document.createElement('filter-bar-helper'); - - // Copy attributes to the child directive - for (const attr of elem[0].attributes) { - child.setAttribute(attr.name, attr.value); - } - - child.setAttribute('ui-settings', 'uiSettings'); - child.setAttribute('doc-links', 'docLinks'); - child.setAttribute('plugin-data-start', 'pluginDataStart'); - - // Append helper directive - elem.append(child); - - const linkFn = ($scope: any) => { - $scope.uiSettings = npStart.core.uiSettings; - $scope.docLinks = npStart.core.docLinks; - $scope.pluginDataStart = npStart.plugins.data; - }; - - return linkFn; - }, - }; - }) - .directive('filterBarHelper', (reactDirective: any) => { - return reactDirective(wrapInI18nContext(FilterBar), [ - ['uiSettings', { watchDepth: 'reference' }], - ['docLinks', { watchDepth: 'reference' }], - ['onFiltersUpdated', { watchDepth: 'reference' }], - ['indexPatterns', { watchDepth: 'collection' }], - ['filters', { watchDepth: 'collection' }], - ['className', { watchDepth: 'reference' }], - ['pluginDataStart', { watchDepth: 'reference' }], - ]); - }); - uiModules.get('kibana/index_patterns').value('indexPatterns', indexPatterns); }); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html index a94fd500257d92..b645bb408300f1 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html @@ -36,8 +36,7 @@ --> +> + +

@@ -33,6 +33,7 @@ show-query-bar is set to "true". -->
{ + $scope.$evalAsync(() => { + $scope.isVisible = isVisible; + }); + })); + // update the searchSource when query updates $scope.fetch = function () { $state.save(); From 35b03621777f600b6eedf19768c1d31d184c1cad Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Wed, 20 Nov 2019 10:30:37 -0600 Subject: [PATCH 13/29] [APM] Performance comparison charts by user agent (browser) (#49582) Show a chart with average page load broken down by user agent name on the RUM overview. I tested this by setting up a RUM agent on a sample app on my test cloud cluster. On the internal APM dev cluster you'll need to set the time range to about 90 days then look at the "client" app and find the time range where there are requests. Unfortunately with this sample data the only series you see is "Other" because there aren't a lot of requests. Also factor out the color selection into a common helper. Fixes #43342 --- .../elasticsearch_fieldnames.test.ts.snap | 6 ++ .../common/elasticsearch_fieldnames.test.ts | 1 + .../apm/common/elasticsearch_fieldnames.ts | 1 + .../plugins/apm/common/processor_event.ts | 6 +- .../plugins/apm/common/transaction_types.ts | 2 +- .../legacy/plugins/apm/common/viz_colors.ts | 27 +++++++ .../BrowserLineChart.test.tsx | 17 ++++ .../TransactionCharts/BrowserLineChart.tsx | 45 +++++++++++ .../DurationByCountryMap/index.tsx | 35 ++++----- .../shared/charts/TransactionCharts/index.tsx | 58 ++++++++------ .../context/UrlParamsContext/helpers.ts | 10 +-- .../hooks/useAvgDurationByBrowser.test.ts | 33 ++++++++ .../public/hooks/useAvgDurationByBrowser.ts | 60 ++++++++++++++ .../java/gc/fetchAndTransformGcMetrics.ts | 13 +--- .../lib/metrics/transform_metrics_chart.ts | 14 +--- .../__fixtures__/responses.ts | 74 ++++++++++++++++++ .../avg_duration_by_browser/fetcher.test.ts | 23 ++++++ .../avg_duration_by_browser/fetcher.ts | 78 +++++++++++++++++++ .../avg_duration_by_browser/index.test.ts | 33 ++++++++ .../avg_duration_by_browser/index.ts | 24 ++++++ .../transformer.test.ts | 29 +++++++ .../avg_duration_by_browser/transformer.ts | 55 +++++++++++++ .../lib/transactions/breakdown/constants.ts | 14 ---- .../lib/transactions/breakdown/index.ts | 5 +- .../apm/server/routes/create_apm_api.ts | 4 +- .../apm/server/routes/transaction_groups.ts | 27 +++++++ 26 files changed, 605 insertions(+), 89 deletions(-) create mode 100644 x-pack/legacy/plugins/apm/common/viz_colors.ts create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx create mode 100644 x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts create mode 100644 x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.ts create mode 100644 x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts create mode 100644 x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts create mode 100644 x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts create mode 100644 x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts create mode 100644 x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts create mode 100644 x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts create mode 100644 x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.ts diff --git a/x-pack/legacy/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap b/x-pack/legacy/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap index 0521270a7ba743..9d82cd6b5455c4 100644 --- a/x-pack/legacy/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap +++ b/x-pack/legacy/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap @@ -102,6 +102,8 @@ exports[`Error TRANSACTION_TYPE 1`] = `"request"`; exports[`Error URL_FULL 1`] = `undefined`; +exports[`Error USER_AGENT_NAME 1`] = `undefined`; + exports[`Error USER_ID 1`] = `undefined`; exports[`Span CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`; @@ -206,6 +208,8 @@ exports[`Span TRANSACTION_TYPE 1`] = `undefined`; exports[`Span URL_FULL 1`] = `undefined`; +exports[`Span USER_AGENT_NAME 1`] = `undefined`; + exports[`Span USER_ID 1`] = `undefined`; exports[`Transaction CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`; @@ -310,4 +314,6 @@ exports[`Transaction TRANSACTION_TYPE 1`] = `"transaction type"`; exports[`Transaction URL_FULL 1`] = `"http://www.elastic.co"`; +exports[`Transaction USER_AGENT_NAME 1`] = `"Other"`; + exports[`Transaction USER_ID 1`] = `"1337"`; diff --git a/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.test.ts b/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.test.ts index 52471e08b1b4d4..82a679ccdd32e3 100644 --- a/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.test.ts +++ b/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.test.ts @@ -34,6 +34,7 @@ describe('Transaction', () => { timestamp: { us: 1337 }, trace: { id: 'trace id' }, user: { id: '1337' }, + user_agent: { name: 'Other', original: 'test original' }, parent: { id: 'parentId' }, diff --git a/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.ts b/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.ts index 552c149ce62146..d0830337e0d351 100644 --- a/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.ts +++ b/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.ts @@ -10,6 +10,7 @@ export const SERVICE_NODE_NAME = 'service.node.name'; export const URL_FULL = 'url.full'; export const HTTP_REQUEST_METHOD = 'http.request.method'; export const USER_ID = 'user.id'; +export const USER_AGENT_NAME = 'user_agent.name'; export const OBSERVER_VERSION_MAJOR = 'observer.version_major'; export const OBSERVER_LISTENING = 'observer.listening'; diff --git a/x-pack/legacy/plugins/apm/common/processor_event.ts b/x-pack/legacy/plugins/apm/common/processor_event.ts index a513f620927675..83dadfc21da902 100644 --- a/x-pack/legacy/plugins/apm/common/processor_event.ts +++ b/x-pack/legacy/plugins/apm/common/processor_event.ts @@ -4,4 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -export type ProcessorEvent = 'transaction' | 'error' | 'metric'; +export enum ProcessorEvent { + transaction = 'transaction', + error = 'error', + metric = 'metric' +} diff --git a/x-pack/legacy/plugins/apm/common/transaction_types.ts b/x-pack/legacy/plugins/apm/common/transaction_types.ts index 4dd59af63047d5..1226e926b1ee32 100644 --- a/x-pack/legacy/plugins/apm/common/transaction_types.ts +++ b/x-pack/legacy/plugins/apm/common/transaction_types.ts @@ -5,5 +5,5 @@ */ export const TRANSACTION_PAGE_LOAD = 'page-load'; -export const TRANSACTION_ROUTE_CHANGE = 'route-change'; export const TRANSACTION_REQUEST = 'request'; +export const TRANSACTION_ROUTE_CHANGE = 'route-change'; diff --git a/x-pack/legacy/plugins/apm/common/viz_colors.ts b/x-pack/legacy/plugins/apm/common/viz_colors.ts new file mode 100644 index 00000000000000..cc070005409b66 --- /dev/null +++ b/x-pack/legacy/plugins/apm/common/viz_colors.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import lightTheme from '@elastic/eui/dist/eui_theme_light.json'; + +function getVizColorsForTheme(theme = lightTheme) { + return [ + theme.euiColorVis0, + theme.euiColorVis1, + theme.euiColorVis2, + theme.euiColorVis3, + theme.euiColorVis4, + theme.euiColorVis5, + theme.euiColorVis6, + theme.euiColorVis7, + theme.euiColorVis8, + theme.euiColorVis9 + ]; +} + +export function getVizColorForIndex(index = 0, theme = lightTheme) { + const colors = getVizColorsForTheme(theme); + return colors[index % colors.length]; +} diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx new file mode 100644 index 00000000000000..e95f733fb4bc85 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; +import { BrowserLineChart } from './BrowserLineChart'; + +describe('BrowserLineChart', () => { + describe('render', () => { + it('renders', () => { + expect(() => shallow()).not.toThrowError(); + }); + }); +}); diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx new file mode 100644 index 00000000000000..58bc4655f730cb --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiTitle } from '@elastic/eui'; +import { TransactionLineChart } from './TransactionLineChart'; +import { + getMaxY, + getResponseTimeTickFormatter, + getResponseTimeTooltipFormatter +} from '.'; +import { getDurationFormatter } from '../../../../utils/formatters'; +import { useAvgDurationByBrowser } from '../../../../hooks/useAvgDurationByBrowser'; + +export function BrowserLineChart() { + const { data } = useAvgDurationByBrowser(); + const maxY = getMaxY(data); + const formatter = getDurationFormatter(maxY); + const formatTooltipValue = getResponseTimeTooltipFormatter(formatter); + const tickFormatY = getResponseTimeTickFormatter(formatter); + + return ( + <> + + + {i18n.translate( + 'xpack.apm.metrics.pageLoadCharts.avgPageLoadByBrowser', + { + defaultMessage: 'Avg. page load duration distribution by browser' + } + )} + + + + + ); +} diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx index 6176397170797c..bea858d1358c58 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx @@ -4,33 +4,30 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexGrid, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; +import { EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { useAvgDurationByCountry } from '../../../../../hooks/useAvgDurationByCountry'; + import { ChoroplethMap } from '../ChoroplethMap'; export const DurationByCountryMap: React.SFC = () => { const { data } = useAvgDurationByCountry(); return ( - - - - - - {i18n.translate( - 'xpack.apm.metrics.durationByCountryMap.avgPageLoadByCountryLabel', - { - defaultMessage: - 'Avg. page load duration distribution by country' - } - )} - - - - - - + <> + {' '} + + + {i18n.translate( + 'xpack.apm.metrics.durationByCountryMap.avgPageLoadByCountryLabel', + { + defaultMessage: 'Avg. page load duration distribution by country' + } + )} + + + + ); }; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx index c032d603599031..97794bf66687b5 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx @@ -33,6 +33,7 @@ import { MLJobLink } from '../../Links/MachineLearningLinks/MLJobLink'; import { LicenseContext } from '../../../../context/LicenseContext'; import { TransactionLineChart } from './TransactionLineChart'; import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue'; +import { BrowserLineChart } from './BrowserLineChart'; import { DurationByCountryMap } from './DurationByCountryMap'; import { TRANSACTION_PAGE_LOAD, @@ -59,31 +60,29 @@ const ShiftedEuiText = styled(EuiText)` top: 5px; `; -export class TransactionCharts extends Component { - public getMaxY = (responseTimeSeries: TimeSeries[]) => { - const coordinates = flatten( - responseTimeSeries.map((serie: TimeSeries) => serie.data as Coordinate[]) - ); - - const numbers: number[] = coordinates.map((c: Coordinate) => - c.y ? c.y : 0 - ); +export function getResponseTimeTickFormatter(formatter: TimeFormatter) { + return (t: number) => formatter(t).formatted; +} - return Math.max(...numbers, 0); +export function getResponseTimeTooltipFormatter(formatter: TimeFormatter) { + return (p: Coordinate) => { + return isValidCoordinateValue(p.y) + ? formatter(p.y).formatted + : NOT_AVAILABLE_LABEL; }; +} - public getResponseTimeTickFormatter = (formatter: TimeFormatter) => { - return (t: number) => formatter(t).formatted; - }; +export function getMaxY(responseTimeSeries: TimeSeries[]) { + const coordinates = flatten( + responseTimeSeries.map((serie: TimeSeries) => serie.data as Coordinate[]) + ); - public getResponseTimeTooltipFormatter = (formatter: TimeFormatter) => { - return (p: Coordinate) => { - return isValidCoordinateValue(p.y) - ? formatter(p.y).formatted - : NOT_AVAILABLE_LABEL; - }; - }; + const numbers: number[] = coordinates.map((c: Coordinate) => (c.y ? c.y : 0)); + return Math.max(...numbers, 0); +} + +export class TransactionCharts extends Component { public getTPMFormatter = (t: number) => { const { urlParams } = this.props; const unit = tpmUnit(urlParams.transactionType); @@ -154,7 +153,7 @@ export class TransactionCharts extends Component { const { charts, urlParams } = this.props; const { responseTimeSeries, tpmSeries } = charts; const { transactionType } = urlParams; - const maxY = this.getMaxY(responseTimeSeries); + const maxY = getMaxY(responseTimeSeries); const formatter = getDurationFormatter(maxY); return ( @@ -177,8 +176,8 @@ export class TransactionCharts extends Component { @@ -205,7 +204,18 @@ export class TransactionCharts extends Component { {transactionType === TRANSACTION_PAGE_LOAD && ( <> - + + + + + + + + + + + + )} diff --git a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts index 5fa9294a95dfd3..1806e7395a8cce 100644 --- a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts +++ b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts @@ -83,24 +83,24 @@ export function getPathParams(pathname: string = ''): PathParams { switch (servicePageName) { case 'transactions': return { - processorEvent: 'transaction', + processorEvent: ProcessorEvent.transaction, serviceName }; case 'errors': return { - processorEvent: 'error', + processorEvent: ProcessorEvent.error, serviceName, errorGroupId: paths[3] }; case 'metrics': return { - processorEvent: 'metric', + processorEvent: ProcessorEvent.metric, serviceName, serviceNodeName }; case 'nodes': return { - processorEvent: 'metric', + processorEvent: ProcessorEvent.metric, serviceName }; case 'service-map': @@ -113,7 +113,7 @@ export function getPathParams(pathname: string = ''): PathParams { case 'traces': return { - processorEvent: 'transaction' + processorEvent: ProcessorEvent.transaction }; default: return {}; diff --git a/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts b/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts new file mode 100644 index 00000000000000..38f26c2ba9fbd7 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { renderHook } from 'react-hooks-testing-library'; +import theme from '@elastic/eui/dist/eui_theme_light.json'; +import * as useFetcherModule from './useFetcher'; +import { useAvgDurationByBrowser } from './useAvgDurationByBrowser'; + +describe('useAvgDurationByBrowser', () => { + it('returns data', () => { + const data = [ + { title: 'Other', data: [{ x: 1572530100000, y: 130010.8947368421 }] } + ]; + jest.spyOn(useFetcherModule, 'useFetcher').mockReturnValueOnce({ + data, + refetch: () => {}, + status: 'success' as useFetcherModule.FETCH_STATUS + }); + const { result } = renderHook(() => useAvgDurationByBrowser()); + + expect(result.current.data).toEqual([ + { + color: theme.euiColorVis0, + data: [{ x: 1572530100000, y: 130010.8947368421 }], + title: 'Other', + type: 'linemark' + } + ]); + }); +}); diff --git a/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.ts b/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.ts new file mode 100644 index 00000000000000..a1e9294455d548 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import theme from '@elastic/eui/dist/eui_theme_light.json'; +import { useFetcher } from './useFetcher'; +import { useUrlParams } from './useUrlParams'; +import { AvgDurationByBrowserAPIResponse } from '../../server/lib/transactions/avg_duration_by_browser'; +import { TimeSeries } from '../../typings/timeseries'; +import { getVizColorForIndex } from '../../common/viz_colors'; + +function toTimeSeries(data?: AvgDurationByBrowserAPIResponse): TimeSeries[] { + if (!data) { + return []; + } + + return data.map((item, index) => { + return { + ...item, + color: getVizColorForIndex(index, theme), + type: 'linemark' + }; + }); +} + +export function useAvgDurationByBrowser() { + const { + urlParams: { serviceName, start, end, transactionName }, + uiFilters + } = useUrlParams(); + + const { data, error, status } = useFetcher( + callApmApi => { + if (serviceName && start && end) { + return callApmApi({ + pathname: + '/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_browser', + params: { + path: { serviceName }, + query: { + start, + end, + transactionName, + uiFilters: JSON.stringify(uiFilters) + } + } + }); + } + }, + [serviceName, start, end, transactionName, uiFilters] + ); + + return { + data: toTimeSeries(data), + status, + error + }; +} diff --git a/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts b/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts index 180537d68a2a2c..8cff6e5d3aa805 100644 --- a/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts +++ b/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts @@ -23,16 +23,7 @@ import { METRIC_JAVA_GC_TIME } from '../../../../../../common/elasticsearch_fieldnames'; import { getBucketSize } from '../../../../helpers/get_bucket_size'; - -const colors = [ - theme.euiColorVis0, - theme.euiColorVis1, - theme.euiColorVis2, - theme.euiColorVis3, - theme.euiColorVis4, - theme.euiColorVis5, - theme.euiColorVis6 -]; +import { getVizColorForIndex } from '../../../../../../common/viz_colors'; export async function fetchAndTransformGcMetrics({ setup, @@ -148,7 +139,7 @@ export async function fetchAndTransformGcMetrics({ title: label, key: label, type: chartBase.type, - color: colors[i], + color: getVizColorForIndex(i, theme), overallValue, data }; diff --git a/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts b/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts index 1e7f197435a677..03f21e4f26e7be 100644 --- a/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts +++ b/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts @@ -11,16 +11,7 @@ import { ESSearchRequest } from '../../../typings/elasticsearch'; import { AggregationOptionsByType } from '../../../typings/elasticsearch/aggregations'; - -const colors = [ - theme.euiColorVis0, - theme.euiColorVis1, - theme.euiColorVis2, - theme.euiColorVis3, - theme.euiColorVis4, - theme.euiColorVis5, - theme.euiColorVis6 -]; +import { getVizColorForIndex } from '../../../common/viz_colors'; export type GenericMetricsChart = ReturnType< typeof transformDataToMetricsChart @@ -66,7 +57,8 @@ export function transformDataToMetricsChart( title: chartBase.series[seriesKey].title, key: seriesKey, type: chartBase.type, - color: chartBase.series[seriesKey].color || colors[i], + color: + chartBase.series[seriesKey].color || getVizColorForIndex(i, theme), overallValue, data: timeseriesData?.buckets.map(bucket => { diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts new file mode 100644 index 00000000000000..3f0f8a84dc62ff --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + ESSearchResponse, + ESSearchRequest +} from '../../../../../typings/elasticsearch'; + +export const response = ({ + hits: { + total: 599, + max_score: 0, + hits: [] + }, + took: 4, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0 + }, + aggregations: { + user_agent_keys: { + buckets: [{ key: 'Firefox' }, { key: 'Other' }] + }, + browsers: { + buckets: [ + { + key_as_string: '2019-10-21T04:38:20.000-05:00', + key: 1571650700000, + doc_count: 0, + user_agent: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [] + } + }, + { + key_as_string: '2019-10-21T04:40:00.000-05:00', + key: 1571650800000, + doc_count: 1, + user_agent: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'Other', + doc_count: 1, + avg_duration: { + value: 860425.0 + } + }, + { + key: 'Firefox', + doc_count: 10, + avg_duration: { + value: 86425.1 + } + } + ] + } + } + ] + } + } +} as unknown) as ESSearchResponse< + unknown, + ESSearchRequest, + { restTotalHitsAsInt: false } +>; diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts new file mode 100644 index 00000000000000..f2227524db0813 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Setup } from '../../helpers/setup_request'; +import { fetcher } from './fetcher'; + +describe('fetcher', () => { + it('performs a search', async () => { + const search = jest.fn(); + const setup = ({ + client: { search }, + indices: {}, + uiFiltersES: [] + } as unknown) as Setup; + + await fetcher({ serviceName: 'testServiceName', setup }); + + expect(search).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts new file mode 100644 index 00000000000000..8a96a25aef50e3 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ESFilter } from '../../../../typings/elasticsearch'; +import { PromiseReturnType } from '../../../../typings/common'; +import { + PROCESSOR_EVENT, + SERVICE_NAME, + TRANSACTION_TYPE, + USER_AGENT_NAME, + TRANSACTION_DURATION +} from '../../../../common/elasticsearch_fieldnames'; +import { rangeFilter } from '../../helpers/range_filter'; +import { getBucketSize } from '../../helpers/get_bucket_size'; +import { Options } from '.'; +import { TRANSACTION_PAGE_LOAD } from '../../../../common/transaction_types'; +import { ProcessorEvent } from '../../../../common/processor_event'; + +export type ESResponse = PromiseReturnType; + +export function fetcher(options: Options) { + const { end, client, indices, start, uiFiltersES } = options.setup; + const { serviceName } = options; + const { intervalString } = getBucketSize(start, end, 'auto'); + + const filter: ESFilter[] = [ + { term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } }, + { term: { [SERVICE_NAME]: serviceName } }, + { term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } }, + { range: rangeFilter(start, end) }, + ...uiFiltersES + ]; + + const params = { + index: indices['apm_oss.transactionIndices'], + body: { + size: 0, + query: { bool: { filter } }, + aggs: { + user_agent_keys: { + terms: { + field: USER_AGENT_NAME + } + }, + browsers: { + date_histogram: { + extended_bounds: { + max: end, + min: start + }, + field: '@timestamp', + fixed_interval: intervalString, + min_doc_count: 0 + }, + aggs: { + user_agent: { + terms: { + field: USER_AGENT_NAME + }, + aggs: { + avg_duration: { + avg: { + field: TRANSACTION_DURATION + } + } + } + } + } + } + } + } + }; + + return client.search(params); +} diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts new file mode 100644 index 00000000000000..fe103ade24161d --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + getTransactionAvgDurationByBrowser, + Options, + AvgDurationByBrowserAPIResponse +} from '.'; +import * as transformerModule from './transformer'; +import * as fetcherModule from './fetcher'; +import { response } from './__fixtures__/responses'; + +describe('getAvgDurationByBrowser', () => { + it('returns a transformed response', async () => { + const transformer = jest + .spyOn(transformerModule, 'transformer') + .mockReturnValueOnce(({} as unknown) as AvgDurationByBrowserAPIResponse); + const search = () => {}; + const options = ({ + setup: { client: { search }, indices: {}, uiFiltersES: [] } + } as unknown) as Options; + jest + .spyOn<{ fetcher: any }, 'fetcher'>(fetcherModule, 'fetcher') + .mockResolvedValueOnce(response); + + await getTransactionAvgDurationByBrowser(options); + + expect(transformer).toHaveBeenCalledWith({ response }); + }); +}); diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts new file mode 100644 index 00000000000000..57b3c8cbe9f937 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Coordinate } from '../../../../typings/timeseries'; +import { Setup } from '../../helpers/setup_request'; +import { fetcher } from './fetcher'; +import { transformer } from './transformer'; + +export interface Options { + serviceName: string; + setup: Setup; +} + +export type AvgDurationByBrowserAPIResponse = Array<{ + data: Coordinate[]; + title: string; +}>; + +export async function getTransactionAvgDurationByBrowser(options: Options) { + return transformer({ response: await fetcher(options) }); +} diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts new file mode 100644 index 00000000000000..5caec12c81d5d3 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { transformer } from './transformer'; +import { response } from './__fixtures__/responses'; + +describe('transformer', () => { + it('transforms', () => { + expect(transformer({ response })).toEqual([ + { + data: [ + { x: 1571650700000, y: undefined }, + { x: 1571650800000, y: 86425.1 } + ], + title: 'Firefox' + }, + { + data: [ + { x: 1571650700000, y: undefined }, + { x: 1571650800000, y: 860425.0 } + ], + title: 'Other' + } + ]); + }); +}); diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.ts new file mode 100644 index 00000000000000..805f8f192bdb19 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ESResponse } from './fetcher'; +import { AvgDurationByBrowserAPIResponse } from '.'; +import { Coordinate } from '../../../../typings/timeseries'; + +export function transformer({ + response +}: { + response: ESResponse; +}): AvgDurationByBrowserAPIResponse { + const allUserAgentKeys = new Set( + // TODO(TS-3.7-ESLINT) + // eslint-disable-next-line @typescript-eslint/camelcase + (response.aggregations?.user_agent_keys?.buckets ?? []).map(({ key }) => + key.toString() + ) + ); + const buckets = response.aggregations?.browsers?.buckets ?? []; + + const series = buckets.reduce<{ [key: string]: Coordinate[] }>( + (acc, next) => { + const userAgentBuckets = next.user_agent?.buckets ?? []; + const x = next.key; + const seenUserAgentKeys = new Set(); + + userAgentBuckets.map(userAgentBucket => { + const key = userAgentBucket.key; + const y = userAgentBucket.avg_duration?.value; + + seenUserAgentKeys.add(key.toString()); + acc[key] = (acc[key] || []).concat({ x, y }); + }); + + const emptyUserAgents = new Set( + [...allUserAgentKeys].filter(key => !seenUserAgentKeys.has(key)) + ); + + // If no user agent requests exist for this bucked, fill in the data with + // undefined + [...emptyUserAgents].map(key => { + acc[key] = (acc[key] || []).concat({ x, y: undefined }); + }); + + return acc; + }, + {} + ); + + return Object.entries(series).map(([title, data]) => ({ title, data })); +} diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/constants.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/constants.ts index 0e288de1e4600d..dcf6e8e07c45bd 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/constants.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/constants.ts @@ -3,19 +3,5 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import theme from '@elastic/eui/dist/eui_theme_light.json'; export const MAX_KPIS = 20; - -export const COLORS = [ - theme.euiColorVis0, - theme.euiColorVis1, - theme.euiColorVis2, - theme.euiColorVis3, - theme.euiColorVis4, - theme.euiColorVis5, - theme.euiColorVis6, - theme.euiColorVis7, - theme.euiColorVis8, - theme.euiColorVis9 -]; diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts index 3166938090d8f7..12f66941169502 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts @@ -18,7 +18,8 @@ import { import { Setup } from '../../helpers/setup_request'; import { rangeFilter } from '../../helpers/range_filter'; import { getMetricsDateHistogramParams } from '../../helpers/metrics'; -import { MAX_KPIS, COLORS } from './constants'; +import { MAX_KPIS } from './constants'; +import { getVizColorForIndex } from '../../../../common/viz_colors'; export async function getTransactionBreakdown({ setup, @@ -142,7 +143,7 @@ export async function getTransactionBreakdown({ const kpis = sortByOrder(visibleKpis, 'name').map((kpi, index) => { return { ...kpi, - color: COLORS[index % COLORS.length] + color: getVizColorForIndex(index) }; }); diff --git a/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts b/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts index c35b66b4536342..1735aa9da7dca3 100644 --- a/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts @@ -42,7 +42,8 @@ import { transactionGroupsChartsRoute, transactionGroupsDistributionRoute, transactionGroupsRoute, - transactionGroupsAvgDurationByCountry + transactionGroupsAvgDurationByCountry, + transactionGroupsAvgDurationByBrowser } from './transaction_groups'; import { errorGroupsLocalFiltersRoute, @@ -102,6 +103,7 @@ const createApmApi = () => { .add(transactionGroupsChartsRoute) .add(transactionGroupsDistributionRoute) .add(transactionGroupsRoute) + .add(transactionGroupsAvgDurationByBrowser) .add(transactionGroupsAvgDurationByCountry) // UI filters diff --git a/x-pack/legacy/plugins/apm/server/routes/transaction_groups.ts b/x-pack/legacy/plugins/apm/server/routes/transaction_groups.ts index 0b5c29fc298578..269f5fee9738c9 100644 --- a/x-pack/legacy/plugins/apm/server/routes/transaction_groups.ts +++ b/x-pack/legacy/plugins/apm/server/routes/transaction_groups.ts @@ -12,6 +12,7 @@ import { getTransactionBreakdown } from '../lib/transactions/breakdown'; import { getTransactionGroupList } from '../lib/transaction_groups'; import { createRoute } from './create_route'; import { uiFiltersRt, rangeRt } from './default_api_types'; +import { getTransactionAvgDurationByBrowser } from '../lib/transactions/avg_duration_by_browser'; import { getTransactionAvgDurationByCountry } from '../lib/transactions/avg_duration_by_country'; export const transactionGroupsRoute = createRoute(() => ({ @@ -144,6 +145,32 @@ export const transactionGroupsBreakdownRoute = createRoute(() => ({ } })); +export const transactionGroupsAvgDurationByBrowser = createRoute(() => ({ + path: `/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_browser`, + params: { + path: t.type({ + serviceName: t.string + }), + query: t.intersection([ + t.partial({ + transactionType: t.string, + transactionName: t.string + }), + uiFiltersRt, + rangeRt + ]) + }, + handler: async (req, { path }) => { + const setup = await setupRequest(req); + const { serviceName } = path; + + return getTransactionAvgDurationByBrowser({ + serviceName, + setup + }); + } +})); + export const transactionGroupsAvgDurationByCountry = createRoute(() => ({ path: `/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_country`, params: { From 5a93c13420e092c508cd7680c8d071ed9f8728f2 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Wed, 20 Nov 2019 18:07:18 +0100 Subject: [PATCH 14/29] fix src/core/public/application react/no-danger violations (#51146) --- .eslintrc.js | 6 ------ .../application/integration_tests/router.test.tsx | 10 ++-------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index daf49d9d08281d..5b7dd6d6d03791 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -64,12 +64,6 @@ module.exports = { 'jsx-a11y/no-onchange': 'off', }, }, - { - files: ['src/core/public/application/**/*.{js,ts,tsx}'], - rules: { - 'react/no-danger': 'off', - }, - }, { files: ['src/legacy/core_plugins/console/**/*.{js,ts,tsx}'], rules: { diff --git a/src/core/public/application/integration_tests/router.test.tsx b/src/core/public/application/integration_tests/router.test.tsx index e6a1070e1a6847..593858851d3872 100644 --- a/src/core/public/application/integration_tests/router.test.tsx +++ b/src/core/public/application/integration_tests/router.test.tsx @@ -18,7 +18,6 @@ */ import React from 'react'; -import ReactDOM from 'react-dom'; import { mount, ReactWrapper } from 'enzyme'; import { createMemoryHistory, History } from 'history'; import { BehaviorSubject } from 'rxjs'; @@ -31,13 +30,8 @@ import { AppRouter, AppNotFound } from '../ui'; const createMountHandler = (htmlString: string) => jest.fn(async ({ appBasePath: basename, element: el }: AppMountParameters) => { - ReactDOM.render( -
, - el - ); - return jest.fn(() => ReactDOM.unmountComponentAtNode(el)); + el.innerHTML = `
\nbasename: ${basename}\nhtml: ${htmlString}\n
`; + return jest.fn(() => (el.innerHTML = '')); }); describe('AppContainer', () => { From 21b83a84701f583ab1640cf7d2f05f515c4009de Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Wed, 20 Nov 2019 12:30:46 -0500 Subject: [PATCH 15/29] Security - honor configured base path when logging out (#50946) * honor configured base path * updating tests * auth providers should redirect to logged out page using server base path --- .../server/authentication/providers/kerberos.test.ts | 2 +- .../server/authentication/providers/kerberos.ts | 2 +- .../server/authentication/providers/oidc.test.ts | 2 +- .../security/server/authentication/providers/oidc.ts | 4 +++- .../server/authentication/providers/pki.test.ts | 2 +- .../security/server/authentication/providers/pki.ts | 2 +- .../server/authentication/providers/saml.test.ts | 12 ++++++------ .../security/server/authentication/providers/saml.ts | 4 +++- 8 files changed, 17 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts index 4ab47cb95b9a31..27105793fc9664 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts @@ -574,7 +574,7 @@ describe('KerberosAuthenticationProvider', () => { sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, tokenPair); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.ts index 0e31dd3d51abaf..767eab7b4311d9 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.ts @@ -107,7 +107,7 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.failed(err); } - return DeauthenticationResult.redirectTo('/logged_out'); + return DeauthenticationResult.redirectTo(`${this.options.basePath.serverBasePath}/logged_out`); } /** diff --git a/x-pack/plugins/security/server/authentication/providers/oidc.test.ts b/x-pack/plugins/security/server/authentication/providers/oidc.test.ts index 7e00d8f282f621..c1d7dcca4c78ff 100644 --- a/x-pack/plugins/security/server/authentication/providers/oidc.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/oidc.test.ts @@ -598,7 +598,7 @@ describe('OIDCAuthenticationProvider', () => { }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/base-path/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects user to the OpenID Connect Provider if RP initiated SLO is supported.', async () => { diff --git a/x-pack/plugins/security/server/authentication/providers/oidc.ts b/x-pack/plugins/security/server/authentication/providers/oidc.ts index 824189fa77a264..37371236453796 100644 --- a/x-pack/plugins/security/server/authentication/providers/oidc.ts +++ b/x-pack/plugins/security/server/authentication/providers/oidc.ts @@ -431,7 +431,9 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.redirectTo(redirect); } - return DeauthenticationResult.redirectTo(`${this.options.basePath.get(request)}/logged_out`); + return DeauthenticationResult.redirectTo( + `${this.options.basePath.serverBasePath}/logged_out` + ); } catch (err) { this.logger.debug(`Failed to deauthenticate user: ${err.message}`); return DeauthenticationResult.failed(err); diff --git a/x-pack/plugins/security/server/authentication/providers/pki.test.ts b/x-pack/plugins/security/server/authentication/providers/pki.test.ts index 35d827c3a9bd19..76442733e7368e 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.test.ts @@ -583,7 +583,7 @@ describe('PKIAuthenticationProvider', () => { expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ accessToken: 'foo' }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/pki.ts b/x-pack/plugins/security/server/authentication/providers/pki.ts index fa3e1959ba7de1..c7d431422a2485 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.ts @@ -111,7 +111,7 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.failed(err); } - return DeauthenticationResult.redirectTo('/logged_out'); + return DeauthenticationResult.redirectTo(`${this.options.basePath.serverBasePath}/logged_out`); } /** diff --git a/x-pack/plugins/security/server/authentication/providers/saml.test.ts b/x-pack/plugins/security/server/authentication/providers/saml.test.ts index 7ef1d934a7d130..27702f70865ea6 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.test.ts @@ -1045,7 +1045,7 @@ describe('SAMLAuthenticationProvider', () => { }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects to /logged_out if `redirect` field in SAML logout response is not defined.', async () => { @@ -1069,7 +1069,7 @@ describe('SAMLAuthenticationProvider', () => { }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('relies on SAML logout if query string is not empty, but does not include SAMLRequest.', async () => { @@ -1095,7 +1095,7 @@ describe('SAMLAuthenticationProvider', () => { }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('relies on SAML invalidate call even if access token is presented.', async () => { @@ -1119,7 +1119,7 @@ describe('SAMLAuthenticationProvider', () => { ); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects to /logged_out if `redirect` field in SAML invalidate response is null.', async () => { @@ -1139,7 +1139,7 @@ describe('SAMLAuthenticationProvider', () => { ); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects to /logged_out if `redirect` field in SAML invalidate response is not defined.', async () => { @@ -1159,7 +1159,7 @@ describe('SAMLAuthenticationProvider', () => { ); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects user to the IdP if SLO is supported by IdP in case of SP initiated logout.', async () => { diff --git a/x-pack/plugins/security/server/authentication/providers/saml.ts b/x-pack/plugins/security/server/authentication/providers/saml.ts index a8683796293afe..faa19239fcc3b1 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.ts @@ -228,7 +228,9 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.redirectTo(redirect); } - return DeauthenticationResult.redirectTo('/logged_out'); + return DeauthenticationResult.redirectTo( + `${this.options.basePath.serverBasePath}/logged_out` + ); } catch (err) { this.logger.debug(`Failed to deauthenticate user: ${err.message}`); return DeauthenticationResult.failed(err); From f20647a30fb681940c22fa5bad24458af53731ff Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Wed, 20 Nov 2019 19:44:10 +0200 Subject: [PATCH 16/29] Move IDataPluginServices and stubs to NP (#51152) * Move IDataPluginServices interface to NP * Move stubs to NP * Fix eslint * code review import change --- .../lib/filter_editor_utils.test.ts | 13 ++++++++----- .../filter_editor/lib/filter_label.test.js | 5 ++++- .../filter_editor/phrase_suggestor.tsx | 2 +- .../query_bar/components/query_bar_input.tsx | 2 +- .../query_bar/components/query_bar_top_row.tsx | 2 +- .../search_bar/components/search_bar.tsx | 2 +- .../es_query/filters/stubs}/exists_filter.ts | 2 +- .../common/es_query/filters/stubs/index.ts} | 17 ++++------------- .../es_query/filters/stubs}/phrase_filter.ts | 2 +- .../es_query/filters/stubs}/phrases_filter.ts | 2 +- .../es_query/filters/stubs}/range_filter.ts | 2 +- src/plugins/data/public/stubs.ts | 1 + src/plugins/data/public/types.ts | 18 +++++++++++++----- .../guidance_panel/guidance_panel.tsx | 2 +- .../graph/public/components/search_bar.tsx | 3 +-- 15 files changed, 40 insertions(+), 35 deletions(-) rename src/{legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures => plugins/data/common/es_query/filters/stubs}/exists_filter.ts (93%) rename src/{legacy/core_plugins/data/public/types.ts => plugins/data/common/es_query/filters/stubs/index.ts} (61%) rename src/{legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures => plugins/data/common/es_query/filters/stubs}/phrase_filter.ts (93%) rename src/{legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures => plugins/data/common/es_query/filters/stubs}/phrases_filter.ts (93%) rename src/{legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures => plugins/data/common/es_query/filters/stubs}/range_filter.ts (93%) diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts index 7ee3e375c0967e..577861db38faf9 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts @@ -18,7 +18,14 @@ */ /* eslint-disable @kbn/eslint/no-restricted-paths */ -import { stubIndexPattern, stubFields } from '../../../../../../../../plugins/data/public/stubs'; +import { + existsFilter, + phraseFilter, + phrasesFilter, + rangeFilter, + stubIndexPattern, + stubFields, +} from '../../../../../../../../plugins/data/public/stubs'; import { IndexPattern, Field } from '../../../../index'; import { buildFilter, @@ -38,10 +45,6 @@ import { isOneOfOperator, isOperator, } from './filter_operators'; -import { existsFilter } from './fixtures/exists_filter'; -import { phraseFilter } from './fixtures/phrase_filter'; -import { phrasesFilter } from './fixtures/phrases_filter'; -import { rangeFilter } from './fixtures/range_filter'; import { esFilters } from '../../../../../../../../plugins/data/public'; jest.mock('ui/new_platform'); diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_label.test.js b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_label.test.js index 042a353031c33e..0f45a33a79ebbc 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_label.test.js +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_label.test.js @@ -19,9 +19,12 @@ import React from 'react'; import { FilterLabel } from './filter_label'; -import { phraseFilter } from './fixtures/phrase_filter'; import { shallow } from 'enzyme'; +/* eslint-disable @kbn/eslint/no-restricted-paths */ +import { phraseFilter } from '../../../../../../../../plugins/data/public/stubs'; +/* eslint-enable @kbn/eslint/no-restricted-paths */ + test('alias', () => { const filter = { ...phraseFilter, diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx index 426c21c99ccdbd..c8b36d84f440e1 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx @@ -24,7 +24,7 @@ import { withKibana, KibanaReactContextValue, } from '../../../../../../../plugins/kibana_react/public'; -import { IDataPluginServices } from '../../../types'; +import { IDataPluginServices } from '../../../../../../../plugins/data/public'; export interface PhraseSuggestorProps { kibana: KibanaReactContextValue; diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx index 31a17315db7dd3..dce245e0ccb242 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx @@ -37,6 +37,7 @@ import { Toast } from 'src/core/public'; import { AutocompleteSuggestion, AutocompleteSuggestionType, + IDataPluginServices, PersistedLog, toUser, fromUser, @@ -52,7 +53,6 @@ import { import { IndexPattern, StaticIndexPattern } from '../../../index_patterns'; import { QueryLanguageSwitcher } from './language_switcher'; import { SuggestionsComponent } from './typeahead/suggestions_component'; -import { IDataPluginServices } from '../../../types'; import { fetchIndexPatterns } from './fetch_index_patterns'; interface Props { diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx index 2730f7665308f4..1bf8ac086d3411 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx @@ -36,6 +36,7 @@ import { EuiSuperUpdateButton, OnRefreshProps } from '@elastic/eui'; import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import { Toast } from 'src/core/public'; import { + IDataPluginServices, TimeRange, TimeHistoryContract, Query, @@ -46,7 +47,6 @@ import { useKibana, toMountPoint } from '../../../../../../../plugins/kibana_rea import { IndexPattern } from '../../../index_patterns'; import { QueryBarInput } from './query_bar_input'; -import { IDataPluginServices } from '../../../types'; interface Props { query?: Query; diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx index e29908bf537642..c8b76c9cda99db 100644 --- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx +++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx @@ -35,8 +35,8 @@ import { withKibana, KibanaReactContextValue, } from '../../../../../../../plugins/kibana_react/public'; -import { IDataPluginServices } from '../../../types'; import { + IDataPluginServices, TimeRange, Query, esFilters, diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts b/src/plugins/data/common/es_query/filters/stubs/exists_filter.ts similarity index 93% rename from src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts rename to src/plugins/data/common/es_query/filters/stubs/exists_filter.ts index 5af97818f9bfbd..13b8189b6e22f7 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts +++ b/src/plugins/data/common/es_query/filters/stubs/exists_filter.ts @@ -17,7 +17,7 @@ * under the License. */ -import { esFilters } from '../../../../../../../../../plugins/data/public'; +import { esFilters } from '../../..'; export const existsFilter: esFilters.ExistsFilter = { meta: { diff --git a/src/legacy/core_plugins/data/public/types.ts b/src/plugins/data/common/es_query/filters/stubs/index.ts similarity index 61% rename from src/legacy/core_plugins/data/public/types.ts rename to src/plugins/data/common/es_query/filters/stubs/index.ts index b6c9c47cc0ae69..4f4c11f2e5ab74 100644 --- a/src/legacy/core_plugins/data/public/types.ts +++ b/src/plugins/data/common/es_query/filters/stubs/index.ts @@ -17,16 +17,7 @@ * under the License. */ -import { UiSettingsClientContract, CoreStart } from 'src/core/public'; -import { DataPublicPluginStart } from 'src/plugins/data/public'; -import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; - -export interface IDataPluginServices extends Partial { - appName: string; - uiSettings: UiSettingsClientContract; - savedObjects: CoreStart['savedObjects']; - notifications: CoreStart['notifications']; - http: CoreStart['http']; - storage: IStorageWrapper; - data: DataPublicPluginStart; -} +export * from './exists_filter'; +export * from './phrase_filter'; +export * from './phrases_filter'; +export * from './range_filter'; diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts b/src/plugins/data/common/es_query/filters/stubs/phrase_filter.ts similarity index 93% rename from src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts rename to src/plugins/data/common/es_query/filters/stubs/phrase_filter.ts index b6c8b9905e6b33..7456e056a02b17 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts +++ b/src/plugins/data/common/es_query/filters/stubs/phrase_filter.ts @@ -17,7 +17,7 @@ * under the License. */ -import { esFilters } from '../../../../../../../../../plugins/data/public'; +import { esFilters } from '../../..'; export const phraseFilter: esFilters.PhraseFilter = { meta: { diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts b/src/plugins/data/common/es_query/filters/stubs/phrases_filter.ts similarity index 93% rename from src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts rename to src/plugins/data/common/es_query/filters/stubs/phrases_filter.ts index 2e2ba4f798bddf..4bd70b85e186ae 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts +++ b/src/plugins/data/common/es_query/filters/stubs/phrases_filter.ts @@ -17,7 +17,7 @@ * under the License. */ -import { esFilters } from '../../../../../../../../../plugins/data/public'; +import { esFilters } from '../../..'; export const phrasesFilter: esFilters.PhrasesFilter = { meta: { diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts b/src/plugins/data/common/es_query/filters/stubs/range_filter.ts similarity index 93% rename from src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts rename to src/plugins/data/common/es_query/filters/stubs/range_filter.ts index c6438e30ecec61..5a6d245e2ef6ff 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts +++ b/src/plugins/data/common/es_query/filters/stubs/range_filter.ts @@ -17,7 +17,7 @@ * under the License. */ -import { esFilters } from '../../../../../../../../../plugins/data/public'; +import { esFilters } from '../../..'; export const rangeFilter: esFilters.RangeFilter = { meta: { diff --git a/src/plugins/data/public/stubs.ts b/src/plugins/data/public/stubs.ts index 40a5e7d18f8d9f..01e68288bd6556 100644 --- a/src/plugins/data/public/stubs.ts +++ b/src/plugins/data/public/stubs.ts @@ -19,3 +19,4 @@ export { stubIndexPattern } from './index_patterns/index_pattern.stub'; export { stubFields } from './index_patterns/field.stub'; +export * from '../common/es_query/filters/stubs'; diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index 5102eb2d7f0d12..a59e7f3de35888 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -17,11 +17,9 @@ * under the License. */ -import { - AutocompletePublicPluginSetup, - AutocompletePublicPluginStart, -} from './autocomplete_provider/types'; - +import { CoreStart } from 'src/core/public'; +import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; +import { AutocompletePublicPluginSetup, AutocompletePublicPluginStart } from '.'; import { FieldFormatsSetup, FieldFormatsStart } from './field_formats_provider'; import { ISearchSetup, ISearchStart } from './search'; import { IGetSuggestions } from './suggestions_provider/types'; @@ -44,3 +42,13 @@ export interface DataPublicPluginStart { export * from './autocomplete_provider/types'; export { IGetSuggestions } from './suggestions_provider/types'; + +export interface IDataPluginServices extends Partial { + appName: string; + uiSettings: CoreStart['uiSettings']; + savedObjects: CoreStart['savedObjects']; + notifications: CoreStart['notifications']; + http: CoreStart['http']; + storage: IStorageWrapper; + data: DataPublicPluginStart; +} diff --git a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx index 8dede207b803c7..5fae9720db39a5 100644 --- a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx +++ b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx @@ -18,7 +18,7 @@ import { i18n } from '@kbn/i18n'; import classNames from 'classnames'; import { FormattedMessage } from '@kbn/i18n/react'; import { connect } from 'react-redux'; -import { IDataPluginServices } from 'src/legacy/core_plugins/data/public/types'; +import { IDataPluginServices } from 'src/plugins/data/public'; import { GraphState, hasDatasourceSelector, diff --git a/x-pack/legacy/plugins/graph/public/components/search_bar.tsx b/x-pack/legacy/plugins/graph/public/components/search_bar.tsx index b6200d831b248c..82e50c702997f5 100644 --- a/x-pack/legacy/plugins/graph/public/components/search_bar.tsx +++ b/x-pack/legacy/plugins/graph/public/components/search_bar.tsx @@ -10,8 +10,7 @@ import React, { useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { connect } from 'react-redux'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; -import { IDataPluginServices } from 'src/legacy/core_plugins/data/public/types'; -import { Query } from 'src/plugins/data/public'; +import { IDataPluginServices, Query } from 'src/plugins/data/public'; import { IndexPatternSavedObject, IndexPatternProvider } from '../types'; import { QueryBarInput, IndexPattern } from '../../../../../../src/legacy/core_plugins/data/public'; import { openSourceModal } from '../services/source_modal'; From 76c70a4ad19c3dff536c36c6ae88429740cea230 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2019 18:28:32 +0000 Subject: [PATCH 17/29] Bump angular from 1.7.8 to 1.7.9 (#51174) Bumps [angular](https://github.com/angular/angular.js) from 1.7.8 to 1.7.9. - [Release notes](https://github.com/angular/angular.js/releases) - [Changelog](https://github.com/angular/angular.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/angular/angular.js/compare/v1.7.8...v1.7.9) Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index ac06753d7d0464..24735b50b15f3b 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "@types/recompose": "^0.30.5", "JSONStream": "1.3.5", "abortcontroller-polyfill": "^1.3.0", - "angular": "^1.7.8", + "angular": "^1.7.9", "angular-aria": "^1.7.8", "angular-elastic": "^2.5.1", "angular-recursion": "^1.0.5", diff --git a/yarn.lock b/yarn.lock index 150e7a98796fe9..b27a1e23943c3c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4875,15 +4875,10 @@ angular-ui-ace@0.2.3: resolved "https://registry.yarnpkg.com/angular-ui-ace/-/angular-ui-ace-0.2.3.tgz#3cb903428100621a367fc7f641440e97a42a26d0" integrity sha1-PLkDQoEAYho2f8f2QUQOl6QqJtA= -angular@>=1.0.6: - version "1.6.9" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.6.9.tgz#bc812932e18909038412d594a5990f4bb66c0619" - integrity sha512-6igWH2GIsxV+J38wNWCh8oyjaZsrIPIDO35twloIUyjlF2Yit6UyLAWujHP05ma/LFxTsx4NtYibRoMNBXPR1A== - -angular@^1.7.8: - version "1.7.8" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.7.8.tgz#b77ede272ce1b261e3be30c1451a0b346905a3c9" - integrity sha512-wtef/y4COxM7ZVhddd7JtAAhyYObq9YXKar9tsW7558BImeVYteJiTxCKeJOL45lJ/+7B4wrAC49j8gTFYEthg== +angular@>=1.0.6, angular@^1.7.9: + version "1.7.9" + resolved "https://registry.yarnpkg.com/angular/-/angular-1.7.9.tgz#e52616e8701c17724c3c238cfe4f9446fd570bc4" + integrity sha512-5se7ZpcOtu0MBFlzGv5dsM1quQDoDeUTwZrWjGtTNA7O88cD8TEk5IEKCTDa3uECV9XnvKREVUr7du1ACiWGFQ== ansi-align@^2.0.0: version "2.0.0" @@ -20648,7 +20643,7 @@ one-time@0.0.4: onetime@^1.0.0: version "1.1.0" - resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + resolved "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= onetime@^2.0.0: From 825d1eb85af4ce0ad8b0a70ba5c885af12b2d6b3 Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Wed, 20 Nov 2019 13:08:27 -0600 Subject: [PATCH 18/29] [DOCS] Fixes moment.js link (#51210) --- docs/management/managing-fields.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/management/managing-fields.asciidoc b/docs/management/managing-fields.asciidoc index 6bfd36bc1c067b..308e61abf70e55 100644 --- a/docs/management/managing-fields.asciidoc +++ b/docs/management/managing-fields.asciidoc @@ -29,7 +29,7 @@ include::field-formatters/url-formatter.asciidoc[] Date fields support the `Date`, `Url`, and `String` formatters. -The `Date` formatter enables you to choose the display format of date stamps using the http://moment.js[moment.js] +The `Date` formatter enables you to choose the display format of date stamps using the https://momentjs.com/[moment.js] standard format definitions. include::field-formatters/string-formatter.asciidoc[] @@ -65,7 +65,7 @@ the https://adamwdraper.github.io/Numeral-js/[numeral.js] standard format defini Scripted fields compute data on the fly from the data in your Elasticsearch indices. Scripted field data is shown on the Discover tab as part of the document data, and you can use scripted fields in your visualizations. Scripted field values are computed at query time so they aren't indexed and cannot be searched using Kibana's default -query language. However they can be queried using Kibana's new <>. Scripted +query language. However they can be queried using Kibana's new <>. Scripted fields are also supported in the filter bar. WARNING: Computing data on the fly with scripted fields can be very resource intensive and can have a direct impact on From 3561029f1f2cc06de55d8182cb098e948b74de78 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 20 Nov 2019 14:32:00 -0500 Subject: [PATCH 19/29] [Security] tests for API keys app (#48560) --- .../api_keys_grid_page.test.tsx.snap | 250 +++++++++++++++++ .../components/api_keys_grid_page.test.tsx | 180 +++++++++++++ .../components/api_keys_grid_page.tsx | 6 +- .../lib/__tests__/__fixtures__/server.ts | 3 + .../server/routes/api/v1/api_keys/get.test.js | 166 ++++++++++++ .../routes/api/v1/api_keys/invalidate.test.js | 200 ++++++++++++++ .../routes/api/v1/api_keys/privileges.test.js | 254 ++++++++++++++++++ 7 files changed, 1057 insertions(+), 2 deletions(-) create mode 100644 x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap create mode 100644 x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx create mode 100644 x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/get.test.js create mode 100644 x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/invalidate.test.js create mode 100644 x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/privileges.test.js diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap new file mode 100644 index 00000000000000..350e28123c29b8 --- /dev/null +++ b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap @@ -0,0 +1,250 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ApiKeysGridPage renders a callout when API keys are not enabled 1`] = ` + + + } + > +
+ + +`; + +exports[`ApiKeysGridPage renders permission denied if user does not have required permissions 1`] = ` + + +
+ + +
+ + +

+ } + iconType="securityApp" + title={ +

+ +

+ } + > +
+ + + + + + + + + +
+ + + + +

+ + You need permission to manage API keys + +

+
+ +
+ + +
+

+ + Contact your system administrator. + +

+
+
+ + +
+ +
+ + +
+ + +`; diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx new file mode 100644 index 00000000000000..19ac3881f78d93 --- /dev/null +++ b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx @@ -0,0 +1,180 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +let mockSimulate403 = false; +let mockSimulate500 = false; +let mockAreApiKeysEnabled = true; +let mockIsAdmin = true; + +const mock403 = () => ({ body: { statusCode: 403 } }); +const mock500 = () => ({ body: { error: 'Internal Server Error', message: '', statusCode: 500 } }); + +jest.mock('../../../../lib/api_keys_api', () => { + return { + ApiKeysApi: { + async checkPrivileges() { + if (mockSimulate403) { + throw mock403(); + } + + return { + isAdmin: mockIsAdmin, + areApiKeysEnabled: mockAreApiKeysEnabled, + }; + }, + async getApiKeys() { + if (mockSimulate500) { + throw mock500(); + } + + return { + apiKeys: [ + { + creation: 1571322182082, + expiration: 1571408582082, + id: '0QQZ2m0BO2XZwgJFuWTT', + invalidated: false, + name: 'my-api-key', + realm: 'reserved', + username: 'elastic', + }, + ], + }; + }, + }, + }; +}); + +import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { ApiKeysGridPage } from './api_keys_grid_page'; +import React from 'react'; +import { ReactWrapper } from 'enzyme'; +import { EuiCallOut } from '@elastic/eui'; + +import { NotEnabled } from './not_enabled'; +import { PermissionDenied } from './permission_denied'; + +const waitForRender = async ( + wrapper: ReactWrapper, + condition: (wrapper: ReactWrapper) => boolean +) => { + return new Promise((resolve, reject) => { + const interval = setInterval(async () => { + await Promise.resolve(); + wrapper.update(); + if (condition(wrapper)) { + resolve(); + } + }, 10); + + setTimeout(() => { + clearInterval(interval); + reject(new Error('waitForRender timeout after 2000ms')); + }, 2000); + }); +}; + +describe('ApiKeysGridPage', () => { + beforeEach(() => { + mockSimulate403 = false; + mockSimulate500 = false; + mockAreApiKeysEnabled = true; + mockIsAdmin = true; + }); + + it('renders a loading state when fetching API keys', async () => { + const wrapper = mountWithIntl(); + + expect(wrapper.find('[data-test-subj="apiKeysSectionLoading"]')).toHaveLength(1); + }); + + it('renders a callout when API keys are not enabled', async () => { + mockAreApiKeysEnabled = false; + const wrapper = mountWithIntl(); + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(NotEnabled).length > 0; + }); + + expect(wrapper.find(NotEnabled)).toMatchSnapshot(); + }); + + it('renders permission denied if user does not have required permissions', async () => { + mockSimulate403 = true; + const wrapper = mountWithIntl(); + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(PermissionDenied).length > 0; + }); + + expect(wrapper.find(PermissionDenied)).toMatchSnapshot(); + }); + + it('renders error callout if error fetching API keys', async () => { + mockSimulate500 = true; + const wrapper = mountWithIntl(); + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(EuiCallOut).length > 0; + }); + + expect(wrapper.find('EuiCallOut[data-test-subj="apiKeysError"]')).toHaveLength(1); + }); + + describe('Admin view', () => { + const wrapper = mountWithIntl(); + + it('renders a callout indicating the user is an administrator', async () => { + const calloutEl = 'EuiCallOut[data-test-subj="apiKeyAdminDescriptionCallOut"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(calloutEl).length > 0; + }); + + expect(wrapper.find(calloutEl).text()).toEqual('You are an API Key administrator.'); + }); + + it('renders the correct description text', async () => { + const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(descriptionEl).length > 0; + }); + + expect(wrapper.find(descriptionEl).text()).toEqual( + 'View and invalidate API keys. An API key sends requests on behalf of a user.' + ); + }); + }); + + describe('Non-admin view', () => { + mockIsAdmin = false; + const wrapper = mountWithIntl(); + + it('does NOT render a callout indicating the user is an administrator', async () => { + const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; + const calloutEl = 'EuiCallOut[data-test-subj="apiKeyAdminDescriptionCallOut"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(descriptionEl).length > 0; + }); + + expect(wrapper.find(calloutEl).length).toEqual(0); + }); + + it('renders the correct description text', async () => { + const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(descriptionEl).length > 0; + }); + + expect(wrapper.find(descriptionEl).text()).toEqual( + 'View and invalidate your API keys. An API key sends requests on your behalf.' + ); + }); + }); +}); diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx index 6bebf17c943a49..37838cfdb950d9 100644 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx +++ b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx @@ -86,7 +86,7 @@ export class ApiKeysGridPage extends Component { if (isLoadingApp) { return ( - + { } color="danger" iconType="alert" + data-test-subj="apiKeysError" > {statusCode}: {errorTitle} - {message} @@ -136,7 +137,7 @@ export class ApiKeysGridPage extends Component { } const description = ( - +

{isAdmin ? ( { color="success" iconType="user" size="s" + data-test-subj="apiKeyAdminDescriptionCallOut" /> diff --git a/x-pack/legacy/plugins/security/server/lib/__tests__/__fixtures__/server.ts b/x-pack/legacy/plugins/security/server/lib/__tests__/__fixtures__/server.ts index 82f91483dc60de..55b6f735cfced8 100644 --- a/x-pack/legacy/plugins/security/server/lib/__tests__/__fixtures__/server.ts +++ b/x-pack/legacy/plugins/security/server/lib/__tests__/__fixtures__/server.ts @@ -37,6 +37,9 @@ export function serverFixture() { getUser: stub(), authenticate: stub(), deauthenticate: stub(), + authorization: { + application: stub(), + }, }, xpack_main: { diff --git a/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/get.test.js b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/get.test.js new file mode 100644 index 00000000000000..400e5b705aeb2a --- /dev/null +++ b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/get.test.js @@ -0,0 +1,166 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import Hapi from 'hapi'; +import Boom from 'boom'; + +import { initGetApiKeysApi } from './get'; +import { INTERNAL_API_BASE_PATH } from '../../../../../common/constants'; + +const createMockServer = () => new Hapi.Server({ debug: false, port: 8080 }); + +describe('GET API keys', () => { + const getApiKeysTest = ( + description, + { + preCheckLicenseImpl = () => null, + callWithRequestImpl, + asserts, + isAdmin = true, + } + ) => { + test(description, async () => { + const mockServer = createMockServer(); + const pre = jest.fn().mockImplementation(preCheckLicenseImpl); + const mockCallWithRequest = jest.fn(); + + if (callWithRequestImpl) { + mockCallWithRequest.mockImplementation(callWithRequestImpl); + } + + initGetApiKeysApi(mockServer, mockCallWithRequest, pre); + + const headers = { + authorization: 'foo', + }; + + const request = { + method: 'GET', + url: `${INTERNAL_API_BASE_PATH}/api_key?isAdmin=${isAdmin}`, + headers, + }; + + const { result, statusCode } = await mockServer.inject(request); + + expect(pre).toHaveBeenCalled(); + + if (callWithRequestImpl) { + expect(mockCallWithRequest).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + authorization: headers.authorization, + }), + }), + 'shield.getAPIKeys', + { + owner: !isAdmin, + }, + ); + } else { + expect(mockCallWithRequest).not.toHaveBeenCalled(); + } + + expect(statusCode).toBe(asserts.statusCode); + expect(result).toEqual(asserts.result); + }); + }; + + describe('failure', () => { + getApiKeysTest('returns result of routePreCheckLicense', { + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), + asserts: { + statusCode: 403, + result: { + error: 'Forbidden', + statusCode: 403, + message: 'test forbidden message', + }, + }, + }); + + getApiKeysTest('returns error from callWithRequest', { + callWithRequestImpl: async () => { + throw Boom.notAcceptable('test not acceptable message'); + }, + asserts: { + statusCode: 406, + result: { + error: 'Not Acceptable', + statusCode: 406, + message: 'test not acceptable message', + }, + }, + }); + }); + + describe('success', () => { + getApiKeysTest('returns API keys', { + callWithRequestImpl: async () => ({ + api_keys: + [{ + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + }), + asserts: { + statusCode: 200, + result: { + apiKeys: + [{ + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + }, + }, + }); + getApiKeysTest('returns only valid API keys', { + callWithRequestImpl: async () => ({ + api_keys: + [{ + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key1', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: true, + username: 'elastic', + realm: 'reserved' + }, { + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key2', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }], + }), + asserts: { + statusCode: 200, + result: { + apiKeys: + [{ + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key2', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + }, + }, + }); + }); +}); diff --git a/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/invalidate.test.js b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/invalidate.test.js new file mode 100644 index 00000000000000..3ed7ca94eb782a --- /dev/null +++ b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/invalidate.test.js @@ -0,0 +1,200 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import Hapi from 'hapi'; +import Boom from 'boom'; + +import { initInvalidateApiKeysApi } from './invalidate'; +import { INTERNAL_API_BASE_PATH } from '../../../../../common/constants'; + +const createMockServer = () => new Hapi.Server({ debug: false, port: 8080 }); + +describe('POST invalidate', () => { + const postInvalidateTest = ( + description, + { + preCheckLicenseImpl = () => null, + callWithRequestImpls = [], + asserts, + payload, + } + ) => { + test(description, async () => { + const mockServer = createMockServer(); + const pre = jest.fn().mockImplementation(preCheckLicenseImpl); + const mockCallWithRequest = jest.fn(); + + for (const impl of callWithRequestImpls) { + mockCallWithRequest.mockImplementationOnce(impl); + } + + initInvalidateApiKeysApi(mockServer, mockCallWithRequest, pre); + + const headers = { + authorization: 'foo', + }; + + const request = { + method: 'POST', + url: `${INTERNAL_API_BASE_PATH}/api_key/invalidate`, + headers, + payload, + }; + + const { result, statusCode } = await mockServer.inject(request); + + expect(pre).toHaveBeenCalled(); + + if (asserts.callWithRequests) { + for (const args of asserts.callWithRequests) { + expect(mockCallWithRequest).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + authorization: headers.authorization, + }), + }), + ...args + ); + } + } else { + expect(mockCallWithRequest).not.toHaveBeenCalled(); + } + + expect(statusCode).toBe(asserts.statusCode); + expect(result).toEqual(asserts.result); + }); + }; + + describe('failure', () => { + postInvalidateTest('returns result of routePreCheckLicense', { + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), + payload: { + apiKeys: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key' }], + isAdmin: true + }, + asserts: { + statusCode: 403, + result: { + error: 'Forbidden', + statusCode: 403, + message: 'test forbidden message', + }, + }, + }); + + postInvalidateTest('returns errors array from callWithRequest', { + callWithRequestImpls: [async () => { + throw Boom.notAcceptable('test not acceptable message'); + }], + payload: { + apiKeys: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key', }], + isAdmin: true + }, + asserts: { + callWithRequests: [ + ['shield.invalidateAPIKey', { + body: { + id: 'si8If24B1bKsmSLTAhJV', + }, + }], + ], + statusCode: 200, + result: { + itemsInvalidated: [], + errors: [{ + id: 'si8If24B1bKsmSLTAhJV', + name: 'my-api-key', + error: Boom.notAcceptable('test not acceptable message'), + }] + }, + }, + }); + }); + + describe('success', () => { + postInvalidateTest('invalidates API keys', { + callWithRequestImpls: [async () => null], + payload: { + apiKeys: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key', }], + isAdmin: true + }, + asserts: { + callWithRequests: [ + ['shield.invalidateAPIKey', { + body: { + id: 'si8If24B1bKsmSLTAhJV', + }, + }], + ], + statusCode: 200, + result: { + itemsInvalidated: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key', }], + errors: [], + }, + }, + }); + + postInvalidateTest('adds "owner" to body if isAdmin=false', { + callWithRequestImpls: [async () => null], + payload: { + apiKeys: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key', }], + isAdmin: false + }, + asserts: { + callWithRequests: [ + ['shield.invalidateAPIKey', { + body: { + id: 'si8If24B1bKsmSLTAhJV', + owner: true, + }, + }], + ], + statusCode: 200, + result: { + itemsInvalidated: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key' }], + errors: [], + }, + }, + }); + + postInvalidateTest('returns only successful invalidation requests', { + callWithRequestImpls: [ + async () => null, + async () => { + throw Boom.notAcceptable('test not acceptable message'); + }], + payload: { + apiKeys: [ + { id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key1' }, + { id: 'ab8If24B1bKsmSLTAhNC', name: 'my-api-key2' } + ], + isAdmin: true + }, + asserts: { + callWithRequests: [ + ['shield.invalidateAPIKey', { + body: { + id: 'si8If24B1bKsmSLTAhJV', + }, + }], + ['shield.invalidateAPIKey', { + body: { + id: 'ab8If24B1bKsmSLTAhNC', + }, + }], + ], + statusCode: 200, + result: { + itemsInvalidated: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key1' }], + errors: [{ + id: 'ab8If24B1bKsmSLTAhNC', + name: 'my-api-key2', + error: Boom.notAcceptable('test not acceptable message'), + }] + }, + }, + }); + }); +}); diff --git a/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/privileges.test.js b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/privileges.test.js new file mode 100644 index 00000000000000..2a6f935e005950 --- /dev/null +++ b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/privileges.test.js @@ -0,0 +1,254 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import Hapi from 'hapi'; +import Boom from 'boom'; + +import { initCheckPrivilegesApi } from './privileges'; +import { INTERNAL_API_BASE_PATH } from '../../../../../common/constants'; + +const createMockServer = () => new Hapi.Server({ debug: false, port: 8080 }); + +describe('GET privileges', () => { + const getPrivilegesTest = ( + description, + { + preCheckLicenseImpl = () => null, + callWithRequestImpls = [], + asserts, + } + ) => { + test(description, async () => { + const mockServer = createMockServer(); + const pre = jest.fn().mockImplementation(preCheckLicenseImpl); + const mockCallWithRequest = jest.fn(); + + for (const impl of callWithRequestImpls) { + mockCallWithRequest.mockImplementationOnce(impl); + } + + initCheckPrivilegesApi(mockServer, mockCallWithRequest, pre); + + const headers = { + authorization: 'foo', + }; + + const request = { + method: 'GET', + url: `${INTERNAL_API_BASE_PATH}/api_key/privileges`, + headers, + }; + + const { result, statusCode } = await mockServer.inject(request); + + expect(pre).toHaveBeenCalled(); + + if (asserts.callWithRequests) { + for (const args of asserts.callWithRequests) { + expect(mockCallWithRequest).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + authorization: headers.authorization, + }), + }), + ...args + ); + } + } else { + expect(mockCallWithRequest).not.toHaveBeenCalled(); + } + + expect(statusCode).toBe(asserts.statusCode); + expect(result).toEqual(asserts.result); + }); + }; + + describe('failure', () => { + getPrivilegesTest('returns result of routePreCheckLicense', { + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), + asserts: { + statusCode: 403, + result: { + error: 'Forbidden', + statusCode: 403, + message: 'test forbidden message', + }, + }, + }); + + getPrivilegesTest('returns error from first callWithRequest', { + callWithRequestImpls: [async () => { + throw Boom.notAcceptable('test not acceptable message'); + }, async () => { }], + asserts: { + callWithRequests: [ + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ['shield.getAPIKeys', { owner: true }], + ], + statusCode: 406, + result: { + error: 'Not Acceptable', + statusCode: 406, + message: 'test not acceptable message', + }, + }, + }); + + getPrivilegesTest('returns error from second callWithRequest', { + callWithRequestImpls: [async () => { }, async () => { + throw Boom.notAcceptable('test not acceptable message'); + }], + asserts: { + callWithRequests: [ + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ['shield.getAPIKeys', { owner: true }], + ], + statusCode: 406, + result: { + error: 'Not Acceptable', + statusCode: 406, + message: 'test not acceptable message', + }, + }, + }); + }); + + describe('success', () => { + getPrivilegesTest('returns areApiKeysEnabled and isAdmin', { + callWithRequestImpls: [ + async () => ({ + username: 'elastic', + has_all_requested: true, + cluster: { manage_api_key: true, manage_security: true }, + index: {}, + application: {} + }), + async () => ( + { + api_keys: + [{ + id: 'si8If24B1bKsmSLTAhJV', + name: 'my-api-key', + creation: 1574089261632, + expiration: 1574175661632, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + } + ), + ], + asserts: { + callWithRequests: [ + ['shield.getAPIKeys', { owner: true }], + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ], + statusCode: 200, + result: { + areApiKeysEnabled: true, + isAdmin: true, + }, + }, + }); + + getPrivilegesTest('returns areApiKeysEnabled=false when getAPIKeys error message includes "api keys are not enabled"', { + callWithRequestImpls: [ + async () => ({ + username: 'elastic', + has_all_requested: true, + cluster: { manage_api_key: true, manage_security: true }, + index: {}, + application: {} + }), + async () => { + throw Boom.unauthorized('api keys are not enabled'); + }, + ], + asserts: { + callWithRequests: [ + ['shield.getAPIKeys', { owner: true }], + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ], + statusCode: 200, + result: { + areApiKeysEnabled: false, + isAdmin: true, + }, + }, + }); + + getPrivilegesTest('returns isAdmin=false when user has insufficient privileges', { + callWithRequestImpls: [ + async () => ({ + username: 'elastic', + has_all_requested: true, + cluster: { manage_api_key: false, manage_security: false }, + index: {}, + application: {} + }), + async () => ( + { + api_keys: + [{ + id: 'si8If24B1bKsmSLTAhJV', + name: 'my-api-key', + creation: 1574089261632, + expiration: 1574175661632, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + } + ), + ], + asserts: { + callWithRequests: [ + ['shield.getAPIKeys', { owner: true }], + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ], + statusCode: 200, + result: { + areApiKeysEnabled: true, + isAdmin: false, + }, + }, + }); + }); +}); From efbf012a70cdd4db9550c60e79a6ea6371101c1e Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Wed, 20 Nov 2019 14:32:48 -0500 Subject: [PATCH 20/29] Change pipeline timeout from 3 hours to 2 hours (#51098) --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index c002832d4d51a3..6030f2b4a021d8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -4,7 +4,7 @@ library 'kibana-pipeline-library' kibanaLibrary.load() stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a little bit - timeout(time: 180, unit: 'MINUTES') { + timeout(time: 120, unit: 'MINUTES') { timestamps { ansiColor('xterm') { catchError { From 87e77e96381c8d18202ee7af7fd5836be723f9dd Mon Sep 17 00:00:00 2001 From: Caroline Horn <549577+cchaos@users.noreply.github.com> Date: Wed, 20 Nov 2019 14:39:33 -0500 Subject: [PATCH 21/29] [Chrome] More Help Menu extensions with semantic links (#50736) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update help menu util to allow common types of links - Github, Docs, and custom * Fix test? * Updating API docs? * Quick layout fix * Kibana core apps updated (Visualize, Dashboard, Discover) * Updated Canvas usage * Updated Maps usage * Added a `discuss` link type * Updated Logs and Metrics usage * Update APM usage * Update Uptime usage * Update SIEM usage * Removing old Uptime file * Update Lens usage * Update API doc * [Uptime] Remove test for file that no longer exists * One more snap and i18n tokens * PR feedback - Wrap feedbackText in method - Use `rel: noopener` on external links - Rename HeaderHelpMenuUIExtraLink -> ChromeHelpExtensionMenuExtraLink and export * [APM] Use ‘custom’ style link for Upgrade assistant * API docs * i18n * Fix link * Documented ChromeHelpExtension props * Use heading levels * Update names of props, document prop, and update API docs * Remove `ae-missing-release-tag` warnings --- ...ugin-public.chromehelpextension.appname.md | 13 ++ ...ugin-public.chromehelpextension.content.md | 13 ++ ...plugin-public.chromehelpextension.links.md | 13 ++ ...ibana-plugin-public.chromehelpextension.md | 13 +- ...ublic.chromehelpextensionmenucustomlink.md | 15 ++ ...blic.chromehelpextensionmenudiscusslink.md | 15 ++ ...hromehelpextensionmenudocumentationlink.md | 15 ++ ...ublic.chromehelpextensionmenugithublink.md | 16 ++ ...ugin-public.chromehelpextensionmenulink.md | 12 ++ .../core/public/kibana-plugin-public.md | 7 +- src/core/public/chrome/chrome_service.test.ts | 17 +- src/core/public/chrome/chrome_service.tsx | 16 +- src/core/public/chrome/index.ts | 7 + src/core/public/chrome/ui/header/header.tsx | 8 - .../chrome/ui/header/header_help_menu.tsx | 183 +++++++++++++++++- src/core/public/chrome/ui/header/index.ts | 7 + src/core/public/chrome/ui/index.ts | 10 +- src/core/public/index.ts | 10 + src/core/public/public.api.md | 36 +++- .../public/dashboard/help_menu/help_menu.js | 46 ----- .../dashboard/help_menu/help_menu_util.js | 22 ++- .../components/help_menu/help_menu.js | 43 ---- .../components/help_menu/help_menu_util.js | 21 +- .../public/visualize/help_menu/help_menu.js | 45 ----- .../visualize/help_menu/help_menu_util.js | 21 +- .../app/GlobalHelpExtension/index.tsx | 49 ----- x-pack/legacy/plugins/apm/public/index.tsx | 38 ++-- .../legacy/plugins/canvas/i18n/components.ts | 4 +- x-pack/legacy/plugins/canvas/public/app.js | 17 +- .../public/components/help_menu/help_menu.js | 22 +-- .../keyboard_shortcuts_doc.examples.storyshot | 2 +- .../public/components/help_center_content.tsx | 33 ++-- .../public/pages/infrastructure/index.tsx | 7 +- .../plugins/infra/public/pages/logs/index.tsx | 6 +- .../plugins/lens/public/help_menu_util.tsx | 59 ++---- .../maps/public/components/help_menu.js | 39 ---- .../plugins/maps/public/help_menu_util.js | 22 ++- .../public/components/help_menu/help_menu.tsx | 43 ---- .../public/components/help_menu/index.tsx | 21 +- .../kibana_global_help.test.tsx.snap | 43 ---- .../__tests__/kibana_global_help.test.tsx | 13 -- .../adapters/framework/kibana_global_help.tsx | 48 ----- .../framework/new_platform_adapter.tsx | 22 ++- .../translations/translations/ja-JP.json | 13 -- .../translations/translations/zh-CN.json | 13 -- 45 files changed, 555 insertions(+), 583 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md delete mode 100644 src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js delete mode 100644 src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js delete mode 100644 src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu.js delete mode 100644 x-pack/legacy/plugins/apm/public/components/app/GlobalHelpExtension/index.tsx delete mode 100644 x-pack/legacy/plugins/maps/public/components/help_menu.js delete mode 100644 x-pack/legacy/plugins/siem/public/components/help_menu/help_menu.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/__snapshots__/kibana_global_help.test.tsx.snap delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/kibana_global_help.test.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/adapters/framework/kibana_global_help.tsx diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md new file mode 100644 index 00000000000000..d817238c9287d3 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [appName](./kibana-plugin-public.chromehelpextension.appname.md) + +## ChromeHelpExtension.appName property + +Provide your plugin's name to create a header for separation + +Signature: + +```typescript +appName: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md new file mode 100644 index 00000000000000..b51d4928e991dc --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [content](./kibana-plugin-public.chromehelpextension.content.md) + +## ChromeHelpExtension.content property + +Custom content to occur below the list of links + +Signature: + +```typescript +content?: (element: HTMLDivElement) => () => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md new file mode 100644 index 00000000000000..de17ca8d86e379 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [links](./kibana-plugin-public.chromehelpextension.links.md) + +## ChromeHelpExtension.links property + +Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button + +Signature: + +```typescript +links?: ChromeHelpExtensionMenuLink[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.md index 82e7ba9bec4a37..6f0007335c5558 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextension.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.md @@ -2,11 +2,20 @@ [Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) -## ChromeHelpExtension type +## ChromeHelpExtension interface Signature: ```typescript -export declare type ChromeHelpExtension = (element: HTMLDivElement) => () => void; +export interface ChromeHelpExtension ``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [appName](./kibana-plugin-public.chromehelpextension.appname.md) | string | Provide your plugin's name to create a header for separation | +| [content](./kibana-plugin-public.chromehelpextension.content.md) | (element: HTMLDivElement) => () => void | Custom content to occur below the list of links | +| [links](./kibana-plugin-public.chromehelpextension.links.md) | ChromeHelpExtensionMenuLink[] | Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button | + diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md new file mode 100644 index 00000000000000..daca70f3b79c1e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) + +## ChromeHelpExtensionMenuCustomLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuCustomLink = EuiButtonEmptyProps & { + linkType: 'custom'; + content: React.ReactNode; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md new file mode 100644 index 00000000000000..8dd1c796bebf17 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) + +## ChromeHelpExtensionMenuDiscussLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuDiscussLink = EuiButtonEmptyProps & { + linkType: 'discuss'; + href: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md new file mode 100644 index 00000000000000..0114cc245a8747 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) + +## ChromeHelpExtensionMenuDocumentationLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuDocumentationLink = EuiButtonEmptyProps & { + linkType: 'documentation'; + href: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md new file mode 100644 index 00000000000000..5dd33f1a05a7fa --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) + +## ChromeHelpExtensionMenuGitHubLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuGitHubLink = EuiButtonEmptyProps & { + linkType: 'github'; + labels: string[]; + title?: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md new file mode 100644 index 00000000000000..072ce165e23c5e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) + +## ChromeHelpExtensionMenuLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuLink = ExclusiveUnion>>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md index cec307032094ec..22794ca9455401 100644 --- a/docs/development/core/public/kibana-plugin-public.md +++ b/docs/development/core/public/kibana-plugin-public.md @@ -33,6 +33,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeBadge](./kibana-plugin-public.chromebadge.md) | | | [ChromeBrand](./kibana-plugin-public.chromebrand.md) | | | [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) | APIs for accessing and updating the document title. | +| [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | | | [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) | | | [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | | [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) | | @@ -98,7 +99,11 @@ The plugin integrates with the core system via lifecycle events: `setup` | --- | --- | | [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. | | [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) | | -| [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | | +| [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) | | +| [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) | | +| [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) | | +| [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) | | +| [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) | | | [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. | | [HandlerFunction](./kibana-plugin-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts index 3390480e56bdd4..96567394216869 100644 --- a/src/core/public/chrome/chrome_service.test.ts +++ b/src/core/public/chrome/chrome_service.test.ts @@ -418,17 +418,20 @@ describe('start', () => { .pipe(toArray()) .toPromise(); - chrome.setHelpExtension(() => () => undefined); + chrome.setHelpExtension({ appName: 'App name', content: () => () => undefined }); chrome.setHelpExtension(undefined); service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - undefined, - [Function], - undefined, - ] - `); + Array [ + undefined, + Object { + "appName": "App name", + "content": [Function], + }, + undefined, + ] + `); }); }); }); diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index e686f03413dd52..cc23b79e1c621d 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -36,6 +36,7 @@ import { NavControlsService, ChromeNavControls } from './nav_controls'; import { DocTitleService, ChromeDocTitle } from './doc_title'; import { LoadingIndicator, HeaderWrapper as Header } from './ui'; import { DocLinksStart } from '../doc_links'; +import { ChromeHelpExtensionMenuLink } from './ui/header/header_help_menu'; export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle }; @@ -58,7 +59,20 @@ export interface ChromeBrand { export type ChromeBreadcrumb = EuiBreadcrumb; /** @public */ -export type ChromeHelpExtension = (element: HTMLDivElement) => () => void; +export interface ChromeHelpExtension { + /** + * Provide your plugin's name to create a header for separation + */ + appName: string; + /** + * Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button + */ + links?: ChromeHelpExtensionMenuLink[]; + /** + * Custom content to occur below the list of links + */ + content?: (element: HTMLDivElement) => () => void; +} interface ConstructorParams { browserSupportsCsp: boolean; diff --git a/src/core/public/chrome/index.ts b/src/core/public/chrome/index.ts index b220a81f775f8d..4a500836990a7a 100644 --- a/src/core/public/chrome/index.ts +++ b/src/core/public/chrome/index.ts @@ -26,6 +26,13 @@ export { ChromeBrand, ChromeHelpExtension, } from './chrome_service'; +export { + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, +} from './ui/header/header_help_menu'; export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields } from './nav_links'; export { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem } from './recently_accessed'; export { ChromeNavControl, ChromeNavControls } from './nav_controls'; diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 1e97899be5854e..904618651201f4 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -24,21 +24,13 @@ import * as Rx from 'rxjs'; import { // TODO: add type annotations - // @ts-ignore EuiHeader, - // @ts-ignore EuiHeaderLogo, - // @ts-ignore EuiHeaderSection, - // @ts-ignore EuiHeaderSectionItem, - // @ts-ignore EuiHeaderSectionItemButton, - // @ts-ignore - EuiHideFor, EuiHorizontalRule, EuiIcon, - // @ts-ignore EuiImage, // @ts-ignore EuiNavDrawer, diff --git a/src/core/public/chrome/ui/header/header_help_menu.tsx b/src/core/public/chrome/ui/header/header_help_menu.tsx index c04fbaa07ba712..50659a777eccbd 100644 --- a/src/core/public/chrome/ui/header/header_help_menu.tsx +++ b/src/core/public/chrome/ui/header/header_help_menu.tsx @@ -18,11 +18,12 @@ */ import * as Rx from 'rxjs'; -import { FormattedMessage } from '@kbn/i18n/react'; import React, { Component, Fragment } from 'react'; -import { InjectedIntl, injectI18n } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { InjectedIntl, injectI18n, FormattedMessage } from '@kbn/i18n/react'; import { EuiButtonEmpty, + EuiButtonEmptyProps, EuiFlexGroup, EuiFlexItem, EuiHeaderSectionItemButton, @@ -30,8 +31,11 @@ import { EuiPopover, EuiPopoverTitle, EuiSpacer, + EuiTitle, + EuiHorizontalRule, } from '@elastic/eui'; +import { ExclusiveUnion } from '@elastic/eui'; import { HeaderExtension } from './header_extension'; import { ChromeHelpExtension } from '../../chrome_service'; import { @@ -41,6 +45,69 @@ import { KIBANA_FEEDBACK_LINK, } from '../../constants'; +/** @public */ +export type ChromeHelpExtensionMenuGitHubLink = EuiButtonEmptyProps & { + /** + * Creates a link to a new github issue in the Kibana repo + */ + linkType: 'github'; + /** + * Include at least one app-specific label to be applied to the new github issue + */ + labels: string[]; + /** + * Provides initial text for the title of the issue + */ + title?: string; +}; + +/** @public */ +export type ChromeHelpExtensionMenuDiscussLink = EuiButtonEmptyProps & { + /** + * Creates a generic give feedback link with comment icon + */ + linkType: 'discuss'; + /** + * URL to discuss page. + * i.e. `https://discuss.elastic.co/c/${appName}` + */ + href: string; +}; + +/** @public */ +export type ChromeHelpExtensionMenuDocumentationLink = EuiButtonEmptyProps & { + /** + * Creates a deep-link to app-specific documentation + */ + linkType: 'documentation'; + /** + * URL to documentation page. + * i.e. `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/${appName}.html`, + */ + href: string; +}; + +/** @public */ +export type ChromeHelpExtensionMenuCustomLink = EuiButtonEmptyProps & { + /** + * Extend EuiButtonEmpty to provide extra functionality + */ + linkType: 'custom'; + /** + * Content of the button (in lieu of `children`) + */ + content: React.ReactNode; +}; + +/** @public */ +export type ChromeHelpExtensionMenuLink = ExclusiveUnion< + ChromeHelpExtensionMenuGitHubLink, + ExclusiveUnion< + ChromeHelpExtensionMenuDiscussLink, + ExclusiveUnion + > +>; + interface Props { helpExtension$: Rx.Observable; intl: InjectedIntl; @@ -84,6 +151,36 @@ class HeaderHelpMenuUI extends Component { } } + createGithubUrl = (labels: string[], title?: string) => { + const url = new URL('https://github.com/elastic/kibana/issues/new?'); + + if (labels.length) { + url.searchParams.set('labels', labels.join(',')); + } + + if (title) { + url.searchParams.set('title', title); + } + + return url.toString(); + }; + + createCustomLink = ( + index: number, + text: React.ReactNode, + addSpacer?: boolean, + buttonProps?: EuiButtonEmptyProps + ) => { + return ( + + + {text} + + {addSpacer && } + + ); + }; + public render() { const { intl, kibanaVersion, useDefaultContent, kibanaDocLink } = this.props; const { helpExtension } = this.state; @@ -137,6 +234,74 @@ class HeaderHelpMenuUI extends Component { ) : null; + let customContent; + if (helpExtension) { + const { appName, links, content } = helpExtension; + + const getFeedbackText = () => + i18n.translate('core.ui.chrome.headerGlobalNav.helpMenuGiveFeedbackOnApp', { + defaultMessage: 'Give feedback on {appName}', + values: { appName: helpExtension.appName }, + }); + + const customLinks = + links && + links.map((link, index) => { + const { linkType, title, labels = [], content: text, ...rest } = link; + switch (linkType) { + case 'documentation': + return this.createCustomLink( + index, + , + index < links.length - 1, + { + target: '_blank', + rel: 'noopener', + ...rest, + } + ); + case 'github': + return this.createCustomLink(index, getFeedbackText(), index < links.length - 1, { + iconType: 'logoGithub', + href: this.createGithubUrl(labels, title), + target: '_blank', + rel: 'noopener', + ...rest, + }); + case 'discuss': + return this.createCustomLink(index, getFeedbackText(), index < links.length - 1, { + iconType: 'editorComment', + target: '_blank', + rel: 'noopener', + ...rest, + }); + case 'custom': + return this.createCustomLink(index, text, index < links.length - 1, { ...rest }); + default: + break; + } + }); + + customContent = ( + <> + +

{appName}

+ + + {customLinks} + {content && ( + <> + {customLinks && } + + + )} + + ); + } + const button = ( { - +

+ +

{
{defaultContent} - {defaultContent && helpExtension && } - {helpExtension && } + {defaultContent && customContent && } + {customContent}
); diff --git a/src/core/public/chrome/ui/header/index.ts b/src/core/public/chrome/ui/header/index.ts index f9c122b864dce2..6d59fc6d9433b8 100644 --- a/src/core/public/chrome/ui/header/index.ts +++ b/src/core/public/chrome/ui/header/index.ts @@ -19,3 +19,10 @@ export { Header, HeaderProps } from './header'; export { HeaderWrapper } from './header_wrapper'; +export { + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, +} from './header_help_menu'; diff --git a/src/core/public/chrome/ui/index.ts b/src/core/public/chrome/ui/index.ts index 69582f6f1ed52a..81b2fdfb0fcc0e 100644 --- a/src/core/public/chrome/ui/index.ts +++ b/src/core/public/chrome/ui/index.ts @@ -18,4 +18,12 @@ */ export { LoadingIndicator } from './loading_indicator'; -export { Header, HeaderWrapper } from './header'; +export { + Header, + HeaderWrapper, + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, +} from './header'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index e040b29814900a..c723c282a7caa1 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -40,6 +40,11 @@ import { ChromeBrand, ChromeBreadcrumb, ChromeHelpExtension, + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, ChromeNavControl, ChromeNavControls, ChromeNavLink, @@ -242,6 +247,11 @@ export { ChromeBrand, ChromeBreadcrumb, ChromeHelpExtension, + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, ChromeNavControl, ChromeNavControls, ChromeNavLink, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 7abbbcd32fbb8b..c3ce3743938bd4 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -5,7 +5,9 @@ ```ts import { Breadcrumb } from '@elastic/eui'; +import { EuiButtonEmptyProps } from '@elastic/eui'; import { EuiGlobalToastListToast } from '@elastic/eui'; +import { ExclusiveUnion } from '@elastic/eui'; import { IconType } from '@elastic/eui'; import { Observable } from 'rxjs'; import React from 'react'; @@ -119,7 +121,39 @@ export interface ChromeDocTitle { } // @public (undocumented) -export type ChromeHelpExtension = (element: HTMLDivElement) => () => void; +export interface ChromeHelpExtension { + appName: string; + content?: (element: HTMLDivElement) => () => void; + links?: ChromeHelpExtensionMenuLink[]; +} + +// @public (undocumented) +export type ChromeHelpExtensionMenuCustomLink = EuiButtonEmptyProps & { + linkType: 'custom'; + content: React.ReactNode; +}; + +// @public (undocumented) +export type ChromeHelpExtensionMenuDiscussLink = EuiButtonEmptyProps & { + linkType: 'discuss'; + href: string; +}; + +// @public (undocumented) +export type ChromeHelpExtensionMenuDocumentationLink = EuiButtonEmptyProps & { + linkType: 'documentation'; + href: string; +}; + +// @public (undocumented) +export type ChromeHelpExtensionMenuGitHubLink = EuiButtonEmptyProps & { + linkType: 'github'; + labels: string[]; + title?: string; +}; + +// @public (undocumented) +export type ChromeHelpExtensionMenuLink = ExclusiveUnion>>; // @public (undocumented) export interface ChromeNavControl { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js deleted file mode 100644 index 1b1a7f84c81310..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { PureComponent } from 'react'; -import { EuiButton, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; - -export class HelpMenu extends PureComponent { - render() { - return ( - - <> - - - - - - - - ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js index 2dc8ce523a7da6..55abfa179b56d8 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js @@ -17,15 +17,19 @@ * under the License. */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { HelpMenu } from './help_menu'; +import { i18n } from '@kbn/i18n'; +import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; -export function addHelpMenuToAppChrome(chrome, docLinks) { - chrome.setHelpExtension(domElement => { - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; +export function addHelpMenuToAppChrome(chrome) { + chrome.setHelpExtension({ + appName: i18n.translate('kbn.dashboard.helpMenu.appName', { + defaultMessage: 'Dashboards', + }), + links: [ + { + linkType: 'documentation', + href: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/dashboard.html`, + }, + ], }); } diff --git a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js b/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js deleted file mode 100644 index ad68e55e71622c..00000000000000 --- a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { Fragment, PureComponent } from 'react'; -import { EuiButton, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { getServices } from '../../kibana_services'; -const { docLinks } = getServices(); - -export class HelpMenu extends PureComponent { - render() { - return ( - - - - - - - - ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu_util.js b/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu_util.js index 58a92193de63e8..eb40130137e007 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu_util.js +++ b/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu_util.js @@ -17,15 +17,20 @@ * under the License. */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { HelpMenu } from './help_menu'; +import { i18n } from '@kbn/i18n'; +import { getServices } from '../../kibana_services'; +const { docLinks } = getServices(); export function addHelpMenuToAppChrome(chrome) { - chrome.setHelpExtension(domElement => { - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; + chrome.setHelpExtension({ + appName: i18n.translate('kbn.discover.helpMenu.appName', { + defaultMessage: 'Discover', + }), + links: [ + { + linkType: 'documentation', + href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/discover.html`, + }, + ], }); } diff --git a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu.js b/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu.js deleted file mode 100644 index 40a1b79ea35203..00000000000000 --- a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { Fragment, PureComponent } from 'react'; -import { EuiButton, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { getServices } from '../kibana_services'; - -const { docLinks } = getServices(); - -export class HelpMenu extends PureComponent { - render() { - return ( - - - - - - - - ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js b/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js index 58a92193de63e8..d27003f39d4c08 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js +++ b/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js @@ -17,15 +17,20 @@ * under the License. */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { HelpMenu } from './help_menu'; +import { i18n } from '@kbn/i18n'; +import { getServices } from '../kibana_services'; +const { docLinks } = getServices(); export function addHelpMenuToAppChrome(chrome) { - chrome.setHelpExtension(domElement => { - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; + chrome.setHelpExtension({ + appName: i18n.translate('kbn.visualize.helpMenu.appName', { + defaultMessage: 'Visualize', + }), + links: [ + { + linkType: 'documentation', + href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/visualize.html`, + }, + ], }); } diff --git a/x-pack/legacy/plugins/apm/public/components/app/GlobalHelpExtension/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/GlobalHelpExtension/index.tsx deleted file mode 100644 index 57a0e5ad9ddc4d..00000000000000 --- a/x-pack/legacy/plugins/apm/public/components/app/GlobalHelpExtension/index.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EuiLink } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React, { Fragment } from 'react'; -import styled from 'styled-components'; -import url from 'url'; -import { px, units } from '../../../style/variables'; -import { useKibanaCore } from '../../../../../observability/public'; - -const Container = styled.div` - margin: ${px(units.minus)} 0; -`; - -export const GlobalHelpExtension: React.SFC = () => { - const core = useKibanaCore(); - - return ( - - - - {i18n.translate('xpack.apm.feedbackMenu.provideFeedbackTitle', { - defaultMessage: 'Provide feedback for APM' - })} - - - - - {i18n.translate('xpack.apm.helpMenu.upgradeAssistantLink', { - defaultMessage: 'Upgrade assistant' - })} - - - - ); -}; diff --git a/x-pack/legacy/plugins/apm/public/index.tsx b/x-pack/legacy/plugins/apm/public/index.tsx index 7d6fa70f025aae..8fd3cb0893dea2 100644 --- a/x-pack/legacy/plugins/apm/public/index.tsx +++ b/x-pack/legacy/plugins/apm/public/index.tsx @@ -4,33 +4,43 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import ReactDOM from 'react-dom'; import { npStart } from 'ui/new_platform'; import 'react-vis/dist/style.css'; import 'ui/autoload/all'; import chrome from 'ui/chrome'; +import { i18n } from '@kbn/i18n'; +import url from 'url'; + // @ts-ignore import { uiModules } from 'ui/modules'; -import { GlobalHelpExtension } from './components/app/GlobalHelpExtension'; import { plugin } from './new-platform'; import { REACT_APP_ROOT_ID } from './new-platform/plugin'; import './style/global_overrides.css'; import template from './templates/index.html'; -import { KibanaCoreContextProvider } from '../../observability/public'; + const { core } = npStart; // render APM feedback link in global help menu -core.chrome.setHelpExtension(domElement => { - ReactDOM.render( - - - , - domElement - ); - return () => { - ReactDOM.unmountComponentAtNode(domElement); - }; +core.chrome.setHelpExtension({ + appName: i18n.translate('xpack.apm.feedbackMenu.appName', { + defaultMessage: 'APM' + }), + links: [ + { + linkType: 'discuss', + href: 'https://discuss.elastic.co/c/apm' + }, + { + linkType: 'custom', + href: url.format({ + pathname: core.http.basePath.prepend('/app/kibana'), + hash: '/management/elasticsearch/upgrade_assistant' + }), + content: i18n.translate('xpack.apm.helpMenu.upgradeAssistantLink', { + defaultMessage: 'Upgrade assistant' + }) + } + ] }); // @ts-ignore diff --git a/x-pack/legacy/plugins/canvas/i18n/components.ts b/x-pack/legacy/plugins/canvas/i18n/components.ts index 5b9f6f00940f4b..c898db7467b445 100644 --- a/x-pack/legacy/plugins/canvas/i18n/components.ts +++ b/x-pack/legacy/plugins/canvas/i18n/components.ts @@ -531,7 +531,7 @@ export const ComponentStrings = { }), getKeyboardShortcutsLinkLabel: () => i18n.translate('xpack.canvas.helpMenu.keyboardShortcutsLinkLabel', { - defaultMessage: 'Keyboard Shortcuts', + defaultMessage: 'Keyboard shortcuts', }), }, KeyboardShortcutsDoc: { @@ -547,7 +547,7 @@ export const ComponentStrings = { }), getTitle: () => i18n.translate('xpack.canvas.keyboardShortcutsDoc.flyoutHeaderTitle', { - defaultMessage: 'Keyboard Shortcuts', + defaultMessage: 'Keyboard shortcuts', }), }, Link: { diff --git a/x-pack/legacy/plugins/canvas/public/app.js b/x-pack/legacy/plugins/canvas/public/app.js index 9faa92a02a9eff..760bb7a46f9552 100644 --- a/x-pack/legacy/plugins/canvas/public/app.js +++ b/x-pack/legacy/plugins/canvas/public/app.js @@ -9,7 +9,9 @@ import './angular/config'; import './angular/services'; import React from 'react'; import ReactDOM from 'react-dom'; +import { i18n } from '@kbn/i18n'; import chrome from 'ui/chrome'; +import { documentationLinks } from './lib/documentation_links'; import { CanvasRootController } from './angular/controllers'; // Import the uiExports that the application uses @@ -33,6 +35,17 @@ import { HelpMenu } from './components/help_menu/help_menu'; chrome.setRootController('canvas', CanvasRootController); // add Canvas docs to help menu in global nav -chrome.helpExtension.set(domNode => { - ReactDOM.render(, domNode); +chrome.helpExtension.set({ + appName: i18n.translate('xpack.canvas.helpMenu.appName', { + defaultMessage: 'Canvas', + }), + links: [ + { + linkType: 'documentation', + href: documentationLinks.canvas, + }, + ], + content: domNode => { + ReactDOM.render(, domNode); + }, }); diff --git a/x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js b/x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js index 6e1de129e84c6b..4512ce2b4992e7 100644 --- a/x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js +++ b/x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js @@ -5,8 +5,7 @@ */ import React, { Fragment, PureComponent } from 'react'; -import { EuiButton, EuiHorizontalRule, EuiText, EuiSpacer, EuiPortal } from '@elastic/eui'; -import { documentationLinks } from '../../lib/documentation_links'; +import { EuiButtonEmpty, EuiPortal } from '@elastic/eui'; import { KeyboardShortcutsDoc } from '../keyboard_shortcuts_doc'; import { ComponentStrings } from '../../../i18n'; @@ -26,19 +25,14 @@ export class HelpMenu extends PureComponent { render() { return ( - - - -

{strings.getHelpMenuDescription()}

-
- - - {strings.getDocumentationLinkLabel()} - - - + {strings.getKeyboardShortcutsLinkLabel()} - + {this.state.isFlyoutVisible && ( diff --git a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot index cf37481d8ad7cb..9d1525788b3a66 100644 --- a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot @@ -72,7 +72,7 @@ exports[`Storyshots components/KeyboardShortcutsDoc default 1`] = `

- Keyboard Shortcuts + Keyboard shortcuts

= ({ feedbackLink, feedbackLinkText }) => ( - - {feedbackLinkText} - -); - -export const HelpCenterContent: React.FC = ({ - feedbackLink, - feedbackLinkText, -}) => { +export const HelpCenterContent: React.FC = ({ feedbackLink, appName }) => { useEffect(() => { - chrome.helpExtension.set(domElement => { - ReactDOM.render( - , - domElement - ); - return () => { - ReactDOM.unmountComponentAtNode(domElement); - }; + chrome.helpExtension.set({ + appName, + links: [ + { + linkType: 'discuss', + href: feedbackLink, + }, + ], }); - }, [feedbackLink, feedbackLinkText]); + }, [feedbackLink, appName]); return null; }; diff --git a/x-pack/legacy/plugins/infra/public/pages/infrastructure/index.tsx b/x-pack/legacy/plugins/infra/public/pages/infrastructure/index.tsx index 6affcae1805b3c..fe48fcc62f77d3 100644 --- a/x-pack/legacy/plugins/infra/public/pages/infrastructure/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/infrastructure/index.tsx @@ -41,10 +41,9 @@ export const InfrastructurePage = injectUICapabilities(
- +
{ - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; + chrome.setHelpExtension({ + appName: 'Lens', + links: [ + { + linkType: 'documentation', + href: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/lens.html`, + }, + { + linkType: 'github', + title: '[Lens]', + labels: ['Feature:Lens'], + }, + ], }); } - -function HelpMenu() { - return ( - <> - - {docsPage && ( - <> - - - - - - )} - - - -   - - {i18n.translate('xpack.lens.helpMenu.feedbackLinkText', { - defaultMessage: 'Provide feedback for the Lens application', - })} - - - - ); -} diff --git a/x-pack/legacy/plugins/maps/public/components/help_menu.js b/x-pack/legacy/plugins/maps/public/components/help_menu.js deleted file mode 100644 index 34cb66eb7bd835..00000000000000 --- a/x-pack/legacy/plugins/maps/public/components/help_menu.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Fragment, PureComponent } from 'react'; -import { EuiButton, EuiHorizontalRule, EuiSpacer, EuiLink, EuiText, EuiIcon } from '@elastic/eui'; -import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -export class HelpMenu extends PureComponent { - render() { - return ( - - - - - - - - -   - - {i18n.translate('xpack.maps.helpMenu.feedbackLinkText', { - defaultMessage: 'Provide feedback for the Maps application', - })} - - - - ); - } -} diff --git a/x-pack/legacy/plugins/maps/public/help_menu_util.js b/x-pack/legacy/plugins/maps/public/help_menu_util.js index c81261554004a5..72d51cc180eb37 100644 --- a/x-pack/legacy/plugins/maps/public/help_menu_util.js +++ b/x-pack/legacy/plugins/maps/public/help_menu_util.js @@ -3,15 +3,21 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { HelpMenu } from './components/help_menu'; +import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; export function addHelpMenuToAppChrome(chrome) { - chrome.helpExtension.set(domElement => { - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; + chrome.helpExtension.set({ + appName: 'Maps', + links: [ + { + linkType: 'documentation', + href: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/maps.html`, + }, + { + linkType: 'github', + title: '[Maps]', + labels: ['Team:Geo'], + }, + ], }); } diff --git a/x-pack/legacy/plugins/siem/public/components/help_menu/help_menu.tsx b/x-pack/legacy/plugins/siem/public/components/help_menu/help_menu.tsx deleted file mode 100644 index b59753e8add6a7..00000000000000 --- a/x-pack/legacy/plugins/siem/public/components/help_menu/help_menu.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { EuiButton, EuiHorizontalRule, EuiIcon, EuiTitle, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; -import styled from 'styled-components'; - -export const Icon = styled(EuiIcon)` - margin-right: ${theme.euiSizeS}; -`; - -Icon.displayName = 'Icon'; - -export const HelpMenuComponent = React.memo(() => ( - <> - - - - - -
- - -
-
- - - - - - - -)); - -HelpMenuComponent.displayName = 'HelpMenuComponent'; diff --git a/x-pack/legacy/plugins/siem/public/components/help_menu/index.tsx b/x-pack/legacy/plugins/siem/public/components/help_menu/index.tsx index d145769319d5bd..43fd8e653f3d8d 100644 --- a/x-pack/legacy/plugins/siem/public/components/help_menu/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/help_menu/index.tsx @@ -4,20 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ -import { render, unmountComponentAtNode } from 'react-dom'; -import React, { useEffect } from 'react'; +import { useEffect } from 'react'; import { pure } from 'recompose'; import chrome from 'ui/chrome'; - -import { HelpMenuComponent } from './help_menu'; +import { i18n } from '@kbn/i18n'; export const HelpMenu = pure<{}>(() => { useEffect(() => { - chrome.helpExtension.set(domNode => { - render(, domNode); - return () => { - unmountComponentAtNode(domNode); - }; + chrome.helpExtension.set({ + appName: i18n.translate('xpack.siem.chrome.help.appName', { + defaultMessage: 'SIEM', + }), + links: [ + { + linkType: 'discuss', + href: 'https://discuss.elastic.co/c/siem', + }, + ], }); }, []); diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/__snapshots__/kibana_global_help.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/__snapshots__/kibana_global_help.test.tsx.snap deleted file mode 100644 index b3f749b12d9d14..00000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/__snapshots__/kibana_global_help.test.tsx.snap +++ /dev/null @@ -1,43 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renderUptimeKibanaGlobalHelp renders links with expected urls 1`] = ` - - - - - For Uptime specific information - - - - - - - - - - -`; diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/kibana_global_help.test.tsx b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/kibana_global_help.test.tsx deleted file mode 100644 index a4791a41e03478..00000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/kibana_global_help.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { renderUptimeKibanaGlobalHelp } from '../kibana_global_help'; - -describe('renderUptimeKibanaGlobalHelp', () => { - it('renders links with expected urls', () => { - expect(renderUptimeKibanaGlobalHelp('https://elastic.co/', 'master')).toMatchSnapshot(); - }); -}); diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/kibana_global_help.tsx b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/kibana_global_help.tsx deleted file mode 100644 index 8e730dcc293104..00000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/kibana_global_help.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EuiLink, EuiSpacer, EuiHorizontalRule, EuiButton, EuiText } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; - -export const renderUptimeKibanaGlobalHelp = (docsSiteUrl: string, docLinkVersion: string) => ( - - - - For Uptime specific information - - - - - - - - - -); diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx index 44191d7e61e0d6..94bfe79a6ca6e4 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx +++ b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx @@ -9,12 +9,12 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { get } from 'lodash'; import { AutocompleteProviderRegister } from 'src/plugins/data/public'; +import { i18n as i18nFormatter } from '@kbn/i18n'; import { CreateGraphQLClient } from './framework_adapter_types'; import { UptimeApp, UptimeAppProps } from '../../../uptime_app'; import { getIntegratedAppAvailability } from './capabilities_adapter'; import { INTEGRATED_SOLUTIONS, PLUGIN } from '../../../../common/constants'; import { getTelemetryMonitorPageLogger, getTelemetryOverviewPageLogger } from '../telemetry'; -import { renderUptimeKibanaGlobalHelp } from './kibana_global_help'; import { UMFrameworkAdapter, BootstrapUptimeApp } from '../../lib'; import { createApolloClient } from './apollo_client_adapter'; @@ -52,12 +52,20 @@ export const getKibanaFrameworkAdapter = ( logMonitorPageLoad: getTelemetryMonitorPageLogger('true', basePath.get()), logOverviewPageLoad: getTelemetryOverviewPageLogger('true', basePath.get()), renderGlobalHelpControls: () => - setHelpExtension((element: HTMLElement) => { - ReactDOM.render( - renderUptimeKibanaGlobalHelp(ELASTIC_WEBSITE_URL, DOC_LINK_VERSION), - element - ); - return () => ReactDOM.unmountComponentAtNode(element); + setHelpExtension({ + appName: i18nFormatter.translate('xpack.uptime.header.appName', { + defaultMessage: 'Uptime', + }), + links: [ + { + linkType: 'documentation', + href: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/xpack-uptime.html`, + }, + { + linkType: 'discuss', + href: 'https://discuss.elastic.co/c/uptime', + }, + ], }), routerBasename: basePath.prepend(PLUGIN.ROUTER_BASE_NAME), setBadge, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 5b59036b89f49b..8312ba3d0c83fc 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3359,7 +3359,6 @@ "xpack.apm.errorsTable.occurrencesColumnLabel": "オカレンス", "xpack.apm.errorsTable.unhandledLabel": "未対応", "xpack.apm.featureRegistry.apmFeatureName": "APM", - "xpack.apm.feedbackMenu.provideFeedbackTitle": "APM のフィードバックを提供", "xpack.apm.filter.environment.allLabel": "すべて", "xpack.apm.filter.environment.label": "環境", "xpack.apm.filter.environment.notDefinedLabel": "未定義", @@ -5845,7 +5844,6 @@ "xpack.infra.homePage.noMetricsIndicesTitle": "メトリックインデックスがないようです。", "xpack.infra.homePage.toolbar.kqlSearchFieldPlaceholder": "インフラストラクチャーデータを検索… (例: host.name:host-1)", "xpack.infra.homePage.toolbar.showingLastOneMinuteDataText": "指定期間の最後の 1 分間のデータを表示中", - "xpack.infra.infrastructure.infrastructureHelpContent.feedbackLinkText": "インフラストラクチャーのフィードバックを提供", "xpack.infra.infrastructureDescription": "インフラストラクチャーを閲覧します", "xpack.infra.infrastructureMetricsExplorerPage.documentTitle": "{previousTitle} | メトリックエクスプローラー", "xpack.infra.infrastructureSnapshotPage.documentTitle": "{previousTitle} | インベントリ", @@ -5896,7 +5894,6 @@ "xpack.infra.logs.stopStreamingButtonLabel": "ストリーム停止", "xpack.infra.logs.streamingDescription": "新しいエントリーをストリーム中...", "xpack.infra.logs.streamingNewEntriesText": "新しいエントリーをストリーム中", - "xpack.infra.logsPage.logsHelpContent.feedbackLinkText": "ログのフィードバックを提供", "xpack.infra.logsPage.noLoggingIndicesDescription": "追加しましょう!", "xpack.infra.logsPage.noLoggingIndicesInstructionsActionLabel": "セットアップの手順を表示", "xpack.infra.logsPage.noLoggingIndicesTitle": "ログインデックスがないようです。", @@ -6420,8 +6417,6 @@ "xpack.maps.heatmap.colorRampLabel": "色の範囲", "xpack.maps.heatmapLegend.coldLabel": "コールド", "xpack.maps.heatmapLegend.hotLabel": "ホット", - "xpack.maps.helpMenu.docLabel": "Maps ドキュメンテーション", - "xpack.maps.helpMenu.feedbackLinkText": "Maps アプリケーションに関するフィードバックを提供", "xpack.maps.inspector.centerLatLabel": "中央緯度", "xpack.maps.inspector.centerLonLabel": "中央経度", "xpack.maps.inspector.mapboxStyleTitle": "マップボックススタイル", @@ -10367,8 +10362,6 @@ "xpack.siem.certificate.fingerprint.clientCertLabel": "クライアント証明書", "xpack.siem.certificate.fingerprint.serverCertLabel": "サーバー証明書", "xpack.siem.chart.dataNotAvailableTitle": "チャートデータが利用できません", - "xpack.siem.chrome.help.feedback": "フィードバックを送信", - "xpack.siem.chrome.help.title": "SIEM アプリケーションのヘルプ", "xpack.siem.clipboard.copied": "コピー完了", "xpack.siem.clipboard.copy": "コピー", "xpack.siem.clipboard.to.the.clipboard": "クリップボードに", @@ -11799,8 +11792,6 @@ "xpack.uptime.filterBar.options.location.name": "場所", "xpack.uptime.filterBar.options.portLabel": "ポート", "xpack.uptime.filterBar.options.schemeLabel": "スキーム", - "xpack.uptime.header.helpLinkAriaLabel": "ディスカッションページへ移動", - "xpack.uptime.header.helpLinkText": "アップタイムのフィードバックを提供", "xpack.uptime.integrationLink.missingDataMessage": "この統合に必要なデータが見つかりませんでした。", "xpack.uptime.monitorCharts.checkStatus.series.downCountLabel": "ダウンカウント", "xpack.uptime.monitorCharts.checkStatus.series.upCountLabel": "アップカウント", @@ -11862,8 +11853,6 @@ "xpack.uptime.snapshotHistogram.series.upLabel": "アップ", "xpack.uptime.uptimeFeatureCatalogueTitle": "起動時間", "xpack.uptime.emptyState.noDataMessage": "アップタイムデータが見つかりませんでした", - "xpack.uptime.header.docsLinkAriaLabel": "アップタイムドキュメンテーションに移動", - "xpack.uptime.header.documentationLinkText": "アップタイムドキュメンテーション", "xpack.uptime.pingList.collapseRow": "縮小", "xpack.uptime.pingList.durationMsColumnFormatting": "{millis}ミリ秒", "xpack.uptime.pingList.expandedRow.bodySize": "本文サイズは {bodyBytes} です。", @@ -12666,8 +12655,6 @@ "xpack.lens.functions.mergeTables.help": "いくつかの Kibana 表を 1 つの表に結合するのをアシストします", "xpack.lens.functions.renameColumns.help": "データベースの列の名前の変更をアシストします", "xpack.lens.functions.renameColumns.idMap.help": "キーが古い列 ID で値が対応する新しい列 ID となるように JSON エンコーディングされたオブジェクトです。他の列 ID はすべてのそのままです。", - "xpack.lens.helpMenu.docLabel": "レンズドキュメンテーション", - "xpack.lens.helpMenu.feedbackLinkText": "レンズアプリケーションに関するフィードバックを提供", "xpack.lens.indexPattern.avg": "平均", "xpack.lens.indexPattern.avgOf": "{name} の平均", "xpack.lens.indexPattern.cardinality": "ユニークカウント", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2b3c788125e6ab..f90d2f9522c311 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3360,7 +3360,6 @@ "xpack.apm.errorsTable.occurrencesColumnLabel": "发生次数", "xpack.apm.errorsTable.unhandledLabel": "未处理", "xpack.apm.featureRegistry.apmFeatureName": "APM", - "xpack.apm.feedbackMenu.provideFeedbackTitle": "提供 APM 的反馈", "xpack.apm.filter.environment.allLabel": "全部", "xpack.apm.filter.environment.label": "环境", "xpack.apm.filter.environment.notDefinedLabel": "未定义", @@ -5847,7 +5846,6 @@ "xpack.infra.homePage.noMetricsIndicesTitle": "似乎您没有任何指标索引。", "xpack.infra.homePage.toolbar.kqlSearchFieldPlaceholder": "搜索基础设施数据……(例如 host.name:host-1)", "xpack.infra.homePage.toolbar.showingLastOneMinuteDataText": "在选定时间显示过去 1 分钟的数据", - "xpack.infra.infrastructure.infrastructureHelpContent.feedbackLinkText": "提供 Infrastructure 的反馈", "xpack.infra.infrastructureDescription": "浏览您的基础设施", "xpack.infra.infrastructureMetricsExplorerPage.documentTitle": "{previousTitle} | 指标浏览器", "xpack.infra.infrastructureSnapshotPage.documentTitle": "{previousTitle} | 库存", @@ -5898,7 +5896,6 @@ "xpack.infra.logs.stopStreamingButtonLabel": "停止流式传输", "xpack.infra.logs.streamingDescription": "正在流式传输新条目……", "xpack.infra.logs.streamingNewEntriesText": "正在流式传输新条目", - "xpack.infra.logsPage.logsHelpContent.feedbackLinkText": "提供 Logs 的反馈", "xpack.infra.logsPage.noLoggingIndicesDescription": "让我们添加一些!", "xpack.infra.logsPage.noLoggingIndicesInstructionsActionLabel": "查看设置说明", "xpack.infra.logsPage.noLoggingIndicesTitle": "似乎您没有任何日志索引。", @@ -6422,8 +6419,6 @@ "xpack.maps.heatmap.colorRampLabel": "颜色范围", "xpack.maps.heatmapLegend.coldLabel": "冷", "xpack.maps.heatmapLegend.hotLabel": "热", - "xpack.maps.helpMenu.docLabel": "地图文档", - "xpack.maps.helpMenu.feedbackLinkText": "提供 Maps 应用程序的反馈", "xpack.maps.inspector.centerLatLabel": "中心纬度", "xpack.maps.inspector.centerLonLabel": "中心经度", "xpack.maps.inspector.mapboxStyleTitle": "Mapbox 样式", @@ -10457,8 +10452,6 @@ "xpack.siem.certificate.fingerprint.clientCertLabel": "客户端证书", "xpack.siem.certificate.fingerprint.serverCertLabel": "服务器证书", "xpack.siem.chart.dataNotAvailableTitle": "图表数据不可用", - "xpack.siem.chrome.help.feedback": "提交反馈", - "xpack.siem.chrome.help.title": "SIEM 应用程序帮助", "xpack.siem.clipboard.copied": "已复制", "xpack.siem.clipboard.copy": "复制", "xpack.siem.clipboard.to.the.clipboard": "至剪贴板", @@ -11889,8 +11882,6 @@ "xpack.uptime.filterBar.options.location.name": "位置", "xpack.uptime.filterBar.options.portLabel": "端口", "xpack.uptime.filterBar.options.schemeLabel": "方案", - "xpack.uptime.header.helpLinkAriaLabel": "前往我们的讨论页", - "xpack.uptime.header.helpLinkText": "提供运行时间反馈", "xpack.uptime.integrationLink.missingDataMessage": "未找到此集成的所需数据。", "xpack.uptime.monitorCharts.checkStatus.series.downCountLabel": "关闭计数", "xpack.uptime.monitorCharts.checkStatus.series.upCountLabel": "运行计数", @@ -11952,8 +11943,6 @@ "xpack.uptime.snapshotHistogram.series.upLabel": "运行", "xpack.uptime.uptimeFeatureCatalogueTitle": "运行时间", "xpack.uptime.emptyState.noDataMessage": "未找到任何运行时间数据", - "xpack.uptime.header.docsLinkAriaLabel": "前往 Uptime 文档", - "xpack.uptime.header.documentationLinkText": "Uptime 文档", "xpack.uptime.pingList.collapseRow": "折叠", "xpack.uptime.pingList.durationMsColumnFormatting": "{millis} 毫秒", "xpack.uptime.pingList.expandedRow.bodySize": "正文大小为 {bodyBytes}。", @@ -12756,8 +12745,6 @@ "xpack.lens.functions.mergeTables.help": "将任何数目的 kibana 表合并成单个表的助手", "xpack.lens.functions.renameColumns.help": "用于重命名数据表列的助手", "xpack.lens.functions.renameColumns.idMap.help": "旧列 ID 为键且相应新列 ID 为值的 JSON 编码对象。所有其他列 ID 都将保留。", - "xpack.lens.helpMenu.docLabel": "Lens 文档", - "xpack.lens.helpMenu.feedbackLinkText": "提供 Lens 应用程序的反馈", "xpack.lens.indexPattern.avg": "平均值", "xpack.lens.indexPattern.avgOf": "{name} 的平均值", "xpack.lens.indexPattern.cardinality": "唯一计数", From 1fdf423be42d937f970aae174b09c93000ea18b7 Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Wed, 20 Nov 2019 13:10:10 -0700 Subject: [PATCH 22/29] Updates dev docs for creating a new tutorial (#51073) * Partially updates the dev docs for registering a new tutorial. Adds comments on further changes that will be needed at a later stage * Fixes broken link to the tutorial schema --- docs/developer/add-data-guide.asciidoc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/developer/add-data-guide.asciidoc b/docs/developer/add-data-guide.asciidoc index 9c44ae9c9ded30..aec44a9537ee8b 100644 --- a/docs/developer/add-data-guide.asciidoc +++ b/docs/developer/add-data-guide.asciidoc @@ -11,10 +11,13 @@ Each tutorial contains three sets of instructions: [float] === Creating a new tutorial +// TODO: update path to where the directory must be created on the new platform 1. Create a new directory in the link:https://github.com/elastic/kibana/tree/master/src/legacy/core_plugins/kibana/server/tutorials[tutorials directory]. 2. In the new directory, create a file called `index.js` that exports a function. -The function must return a JavaScript object that conforms to the link:https://github.com/elastic/kibana/blob/master/src/legacy/core_plugins/kibana/common/tutorials/tutorial_schema.js[tutorial schema]. -3. Register the tutorial in link:https://github.com/elastic/kibana/blob/master/src/legacy/core_plugins/kibana/server/tutorials/register.js[register.js] by calling `server.registerTutorial(myFuncImportedFromIndexJs)`. +The function must return a JavaScript object that conforms to the link:https://github.com/elastic/kibana/blob/master/src/plugins/home/server/services/tutorials/lib/tutorial_schema.ts[tutorial schema]. +// TODO: update path to where the tutorial must be registered on the new platform +3. Register the tutorial in link:https://github.com/elastic/kibana/blob/master/src/legacy/core_plugins/kibana/server/tutorials/register.js[register.js] by calling `server.newPlatform.setup.plugins.home.tutorials.registerTutorial(myFuncImportedFromIndexJs)`. +// TODO: update path to where the image assets must be added on the new platform 4. Add image assets to the link:https://github.com/elastic/kibana/tree/master/src/legacy/core_plugins/kibana/public/home/tutorial_resources[tutorial_resources directory]. 5. Run Kibana locally to preview the tutorial. 6. Create a PR and go through the review process to get the changes approved. From e16e3e3f639290a86026389b14cfbfe114523a34 Mon Sep 17 00:00:00 2001 From: Court Ewing Date: Wed, 20 Nov 2019 15:20:50 -0500 Subject: [PATCH 23/29] Remove @elastic/ctags-langserver dependency (#51097) This was only used by the code plugin, which was removed in 7.5.0. --- src/dev/build/tasks/clean_tasks.js | 1 - x-pack/package.json | 1 - yarn.lock | 37 ++---------------------------- 3 files changed, 2 insertions(+), 37 deletions(-) diff --git a/src/dev/build/tasks/clean_tasks.js b/src/dev/build/tasks/clean_tasks.js index 3ec1d6b6967e9d..c33dfe62621282 100644 --- a/src/dev/build/tasks/clean_tasks.js +++ b/src/dev/build/tasks/clean_tasks.js @@ -169,7 +169,6 @@ export const CleanExtraFilesFromModulesTask = { await scanDelete({ directory: build.resolvePath('node_modules'), regularExpressions, - excludePaths: [build.resolvePath('node_modules/@elastic/ctags-langserver/vendor')], }) ); diff --git a/x-pack/package.json b/x-pack/package.json index 402c3e95159f3b..ff8bff0fec6346 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -176,7 +176,6 @@ "@babel/core": "^7.5.5", "@babel/register": "^7.5.5", "@babel/runtime": "^7.5.5", - "@elastic/ctags-langserver": "^0.1.11", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", "@elastic/eui": "14.9.0", diff --git a/yarn.lock b/yarn.lock index b27a1e23943c3c..71c09a6ed4b0f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1126,21 +1126,6 @@ ts-debounce "^1.0.0" uuid "^3.3.2" -"@elastic/ctags-langserver@^0.1.11": - version "0.1.11" - resolved "https://registry.yarnpkg.com/@elastic/ctags-langserver/-/ctags-langserver-0.1.11.tgz#e4725a6a763a2ff61fd02bbe2b42aa70db5d0f3f" - integrity sha512-ODNcD+zFmuhMm649/4fGQXD1msafvBaHKsk9PDXTjLrUMozrCWj99tGKqR5HcwrdkoMr/3YRBre2r4cyomtoBw== - dependencies: - "@elastic/lsp-extension" "^0.1.1" - "@elastic/node-ctags" "1.0.2" - commander "^2.11.0" - find-root "^1.1.0" - line-column "^1.0.2" - minimatch "3.0.4" - mz "^2.7.0" - parse-gitignore "1.0.1" - vscode-languageserver "^5.2.1" - "@elastic/elasticsearch@^7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@elastic/elasticsearch/-/elasticsearch-7.4.0.tgz#57f4066acf25e9d4e9b4f6376088433aae6f25d4" @@ -1267,7 +1252,7 @@ vscode-languageserver-types "^3.0.3" yarn "^1.12.3" -"@elastic/lsp-extension@^0.1.1", "@elastic/lsp-extension@^0.1.2": +"@elastic/lsp-extension@^0.1.2": version "0.1.2" resolved "https://registry.yarnpkg.com/@elastic/lsp-extension/-/lsp-extension-0.1.2.tgz#7356d951d272e833d02a81e13a0ef710f9474195" integrity sha512-yDj5Ht5KCHDwBlgrlusmLtV/Yxa5z2f3vMSYbNFotoRMup8345/ZwlFp/zmyl04iFOVpT8ouB34+Ttpzbpd3vA== @@ -1304,11 +1289,6 @@ resolved "https://registry.yarnpkg.com/@elastic/node-crypto/-/node-crypto-1.0.0.tgz#4d325df333fe1319556bb4d54214098ada1171d4" integrity sha512-bbjbEyILPRTRt0xnda18OttLtlkJBPuXx3CjISUSn9jhWqHoFMzfOaZ73D5jxZE2SaFZUrJYfPpqXP6qqPufAQ== -"@elastic/node-ctags@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@elastic/node-ctags/-/node-ctags-1.0.2.tgz#447d7694a5598f9413fe2b6f356d56f64f612dfd" - integrity sha512-EHhJ0NPlCvYy+gbzBMU4/Z/55hftfdwlAG8JwOy7g0ITmH6rFPanEnzg1WL3/L+pp8OlYHyvDLwmyg0+06y8LQ== - "@elastic/numeral@2.3.3": version "2.3.3" resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.3.3.tgz#94d38a35bd315efa7a6918b22695128fc40a885e" @@ -17830,14 +17810,6 @@ liftoff@^3.1.0: rechoir "^0.6.2" resolve "^1.1.7" -line-column@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" - integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI= - dependencies: - isarray "^1.0.0" - isobject "^2.0.0" - linebreak@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/linebreak/-/linebreak-0.3.0.tgz#0526480a62c05bd679f3e9d99830e09c6a7d0ed6" @@ -19700,7 +19672,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -mz@^2.6.0, mz@^2.7.0: +mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== @@ -21187,11 +21159,6 @@ parse-git-config@^1.1.1: git-config-path "^1.0.1" ini "^1.3.4" -parse-gitignore@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-gitignore/-/parse-gitignore-1.0.1.tgz#8b9dc57f17b810d495c5dfa62eb07caffe7758c7" - integrity sha512-UGyowyjtx26n65kdAMWhm6/3uy5uSrpcuH7tt+QEVudiBoVS+eqHxD5kbi9oWVRwj7sCzXqwuM+rUGw7earl6A== - parse-headers@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" From d61cef41bb45cb104af5937ba332e049af8a18c4 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Wed, 20 Nov 2019 21:39:06 +0100 Subject: [PATCH 24/29] NP Licensing service info endpoint (#51188) * add NP licensing service info endpoint * call licensing/info and mark it as system to prevent session update * add integration api test for licensing/info endpoint * readonly for static data! --- .../plugins/licensing/public/plugin.test.ts | 21 +++++++++- x-pack/plugins/licensing/public/plugin.ts | 40 +++++++++++-------- x-pack/plugins/licensing/server/plugin.ts | 3 ++ .../plugins/licensing/server/routes/index.ts | 11 +++++ .../plugins/licensing/server/routes/info.ts | 14 +++++++ x-pack/test/api_integration/apis/index.js | 1 + .../api_integration/apis/licensing/index.ts | 13 ++++++ .../api_integration/apis/licensing/info.ts | 24 +++++++++++ 8 files changed, 110 insertions(+), 17 deletions(-) create mode 100644 x-pack/plugins/licensing/server/routes/index.ts create mode 100644 x-pack/plugins/licensing/server/routes/info.ts create mode 100644 x-pack/test/api_integration/apis/licensing/index.ts create mode 100644 x-pack/test/api_integration/apis/licensing/info.ts diff --git a/x-pack/plugins/licensing/public/plugin.test.ts b/x-pack/plugins/licensing/public/plugin.test.ts index 8ede881cad47e3..60dfd1f6cb260a 100644 --- a/x-pack/plugins/licensing/public/plugin.test.ts +++ b/x-pack/plugins/licensing/public/plugin.test.ts @@ -38,6 +38,25 @@ describe('licensing plugin', () => { expect(license.uid).toBe('fetched'); }); + + it('data re-fetch call marked as a system api', async () => { + const sessionStorage = coreMock.createStorage(); + plugin = new LicensingPlugin(coreMock.createPluginInitializerContext(), sessionStorage); + + const coreSetup = coreMock.createSetup(); + const fetchedLicense = licenseMock.create(); + coreSetup.http.get.mockResolvedValue(fetchedLicense); + + const { refresh } = await plugin.setup(coreSetup); + + refresh(); + + expect(coreSetup.http.get.mock.calls[0][1]).toMatchObject({ + headers: { + 'kbn-system-api': 'true', + }, + }); + }); }); describe('#license$', () => { @@ -238,7 +257,7 @@ describe('licensing plugin', () => { }, }, request: { - url: 'http://10.10.10.10:5601/api/xpack/v1/info', + url: 'http://10.10.10.10:5601/api/licensing/info', }, }; expect(coreSetup.http.get).toHaveBeenCalledTimes(0); diff --git a/x-pack/plugins/licensing/public/plugin.ts b/x-pack/plugins/licensing/public/plugin.ts index c1b13418aa3e71..79ad6f289b67e6 100644 --- a/x-pack/plugins/licensing/public/plugin.ts +++ b/x-pack/plugins/licensing/public/plugin.ts @@ -5,7 +5,7 @@ */ import { Subject, Subscription, merge } from 'rxjs'; -import { takeUntil, tap } from 'rxjs/operators'; +import { takeUntil } from 'rxjs/operators'; import { CoreSetup, Plugin, PluginInitializerContext } from 'src/core/public'; @@ -31,8 +31,9 @@ export class LicensingPlugin implements Plugin { */ private removeInterceptor?: () => void; private licenseFetchSubscription?: Subscription; + private storageSubscription?: Subscription; - private infoEndpoint = '/api/xpack/v1/info'; + private readonly infoEndpoint = '/api/licensing/info'; private prevSignature?: string; constructor( @@ -76,18 +77,16 @@ export class LicensingPlugin implements Plugin { ); this.licenseFetchSubscription = fetchSubscription; - const license$ = update$.pipe( - tap(license => { - if (license.error) { - this.prevSignature = undefined; - // Prevent reusing stale license if the fetch operation fails - this.removeSaved(); - } else { - this.prevSignature = license.signature; - this.save(license); - } - }) - ); + this.storageSubscription = update$.subscribe(license => { + if (license.isAvailable) { + this.prevSignature = license.signature; + this.save(license); + } else { + this.prevSignature = undefined; + // Prevent reusing stale license if the fetch operation fails + this.removeSaved(); + } + }); this.removeInterceptor = core.http.intercept({ response: async httpResponse => { @@ -107,7 +106,7 @@ export class LicensingPlugin implements Plugin { refresh: () => { manualRefresh$.next(); }, - license$, + license$: update$, }; } @@ -124,11 +123,20 @@ export class LicensingPlugin implements Plugin { this.licenseFetchSubscription.unsubscribe(); this.licenseFetchSubscription = undefined; } + if (this.storageSubscription !== undefined) { + this.storageSubscription.unsubscribe(); + this.storageSubscription = undefined; + } } private fetchLicense = async (core: CoreSetup): Promise => { try { - const response = await core.http.get(this.infoEndpoint); + const response = await core.http.get(this.infoEndpoint, { + headers: { + 'kbn-system-api': 'true', + }, + }); + return new License({ license: response.license, features: response.features, diff --git a/x-pack/plugins/licensing/server/plugin.ts b/x-pack/plugins/licensing/server/plugin.ts index 3c93b55723787c..d3dc84c05e25c8 100644 --- a/x-pack/plugins/licensing/server/plugin.ts +++ b/x-pack/plugins/licensing/server/plugin.ts @@ -24,6 +24,8 @@ import { License } from '../common/license'; import { createLicenseUpdate } from '../common/license_update'; import { ElasticsearchError, RawLicense, RawFeatures } from './types'; +import { registerRoutes } from './routes'; + import { LicenseConfigType } from './licensing_config'; import { createRouteHandlerContext } from './licensing_route_handler_context'; @@ -92,6 +94,7 @@ export class LicensingPlugin implements Plugin { const { refresh, license$ } = this.createLicensePoller(dataClient, config.pollingFrequency); core.http.registerRouteHandlerContext('licensing', createRouteHandlerContext(license$)); + registerRoutes(core.http.createRouter()); return { refresh, diff --git a/x-pack/plugins/licensing/server/routes/index.ts b/x-pack/plugins/licensing/server/routes/index.ts new file mode 100644 index 00000000000000..26b3bc6292dd62 --- /dev/null +++ b/x-pack/plugins/licensing/server/routes/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { IRouter } from 'src/core/server'; +import { registerInfoRoute } from './info'; + +export function registerRoutes(router: IRouter) { + registerInfoRoute(router); +} diff --git a/x-pack/plugins/licensing/server/routes/info.ts b/x-pack/plugins/licensing/server/routes/info.ts new file mode 100644 index 00000000000000..cad873014e2715 --- /dev/null +++ b/x-pack/plugins/licensing/server/routes/info.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { IRouter } from 'src/core/server'; + +export function registerInfoRoute(router: IRouter) { + router.get({ path: '/api/licensing/info', validate: false }, (context, request, response) => { + return response.ok({ + body: context.licensing.license, + }); + }); +} diff --git a/x-pack/test/api_integration/apis/index.js b/x-pack/test/api_integration/apis/index.js index 86ef4458990390..ca339e9f407f22 100644 --- a/x-pack/test/api_integration/apis/index.js +++ b/x-pack/test/api_integration/apis/index.js @@ -27,5 +27,6 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./siem')); loadTestFile(require.resolve('./short_urls')); loadTestFile(require.resolve('./lens')); + loadTestFile(require.resolve('./licensing')); }); } diff --git a/x-pack/test/api_integration/apis/licensing/index.ts b/x-pack/test/api_integration/apis/licensing/index.ts new file mode 100644 index 00000000000000..f14d5102f6f4e2 --- /dev/null +++ b/x-pack/test/api_integration/apis/licensing/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function licensingIntegrationTests({ loadTestFile }: FtrProviderContext) { + describe('Licensing', () => { + loadTestFile(require.resolve('./info')); + }); +} diff --git a/x-pack/test/api_integration/apis/licensing/info.ts b/x-pack/test/api_integration/apis/licensing/info.ts new file mode 100644 index 00000000000000..0b48080616fb98 --- /dev/null +++ b/x-pack/test/api_integration/apis/licensing/info.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('Info', () => { + describe('GET /api/licensing/info', () => { + it('returns licensing information', async () => { + const response = await supertest.get('/api/licensing/info').expect(200); + + expect(response.body).property('features'); + expect(response.body).property('license'); + expect(response.body).property('signature'); + }); + }); + }); +} From 093121f94e138c791c1e24c48722a8864b35e1a6 Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Wed, 20 Nov 2019 21:51:39 +0100 Subject: [PATCH 25/29] removes skips (#51206) --- .../ml_conditional_links.spec.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts index cec5d6d88d86db..a03ff0c1845f85 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts @@ -28,7 +28,7 @@ describe('ml conditional links', () => { return logout(); }); - it.skip('sets the KQL from a single IP with a value for the query', () => { + it('sets the KQL from a single IP with a value for the query', () => { loginAndWaitForPage(mlNetworkSingleIpKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -37,7 +37,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a multiple IPs with a null for the query', () => { + it('sets the KQL from a multiple IPs with a null for the query', () => { loginAndWaitForPage(mlNetworkMultipleIpNullKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -46,7 +46,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a multiple IPs with a value for the query', () => { + it('sets the KQL from a multiple IPs with a value for the query', () => { loginAndWaitForPage(mlNetworkMultipleIpKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -55,7 +55,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a $ip$ with a value for the query', () => { + it('sets the KQL from a $ip$ with a value for the query', () => { loginAndWaitForPage(mlNetworkKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -64,7 +64,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a single host name with a value for query', () => { + it('sets the KQL from a single host name with a value for query', () => { loginAndWaitForPage(mlHostSingleHostKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -73,7 +73,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a multiple host names with null for query', () => { + it('sets the KQL from a multiple host names with null for query', () => { loginAndWaitForPage(mlHostMultiHostNullKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -82,7 +82,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a multiple host names with a value for query', () => { + it('sets the KQL from a multiple host names with a value for query', () => { loginAndWaitForPage(mlHostMultiHostKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -91,7 +91,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a undefined/null host name but with a value for query', () => { + it('sets the KQL from a undefined/null host name but with a value for query', () => { loginAndWaitForPage(mlHostVariableHostKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -100,7 +100,7 @@ describe('ml conditional links', () => { ); }); - it.skip('redirects from a single IP with a null for the query', () => { + it('redirects from a single IP with a null for the query', () => { loginAndWaitForPage(mlNetworkSingleIpNullKqlQuery); cy.url().should( 'include', @@ -108,7 +108,7 @@ describe('ml conditional links', () => { ); }); - it.skip('redirects from a single IP with a value for the query', () => { + it('redirects from a single IP with a value for the query', () => { loginAndWaitForPage(mlNetworkSingleIpKqlQuery); cy.url().should( 'include', @@ -116,7 +116,7 @@ describe('ml conditional links', () => { ); }); - it.skip('redirects from a multiple IPs with a null for the query', () => { + it('redirects from a multiple IPs with a null for the query', () => { loginAndWaitForPage(mlNetworkMultipleIpNullKqlQuery); cy.url().should( 'include', From 7cbb072554f4028cf6feb0f9587ca660e517628e Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Wed, 20 Nov 2019 17:02:04 -0600 Subject: [PATCH 26/29] Upgrade EUI to 16.0.0 (#50779) * eui to 16.0.0 * type defs * card click * snapshot updates * time format test updates * ts return * integration fix * async * more time format fixes * more time format fixes * test updates * add uisettings dateformat timepicker test * after method to clear setting --- package.json | 2 +- .../flyout_service.test.tsx.snap | 4 +- .../__snapshots__/add_data.test.js.snap | 42 - .../__snapshots__/synopsis.test.js.snap | 8 - .../__snapshots__/metric_tiles.test.js.snap | 8 - test/accessibility/apps/discover.ts | 5 +- .../apps/context/_discover_navigation.js | 4 +- .../apps/dashboard/dashboard_time.js | 19 +- .../apps/dashboard/dashboard_time_picker.js | 19 +- .../apps/dashboard/embeddable_rendering.js | 16 +- test/functional/apps/dashboard/time_zones.js | 8 +- test/functional/apps/dashboard/view_edit.js | 10 +- test/functional/apps/discover/_date_nanos.js | 8 +- .../apps/discover/_date_nanos_mixed.js | 4 +- test/functional/apps/discover/_discover.js | 24 +- .../apps/discover/_doc_navigation.js | 4 +- test/functional/apps/discover/_field_data.js | 4 +- test/functional/apps/discover/_inspector.js | 2 +- .../apps/discover/_saved_queries.js | 16 +- .../functional/apps/discover/_shared_links.js | 5 +- test/functional/apps/discover/_sidebar.js | 4 +- .../apps/discover/_source_filters.js | 4 +- test/functional/apps/home/_navigation.ts | 4 +- test/functional/apps/home/_sample_data.js | 22 +- .../apps/management/_handle_alias.js | 4 +- .../apps/management/_kibana_settings.js | 4 +- .../apps/management/_scripted_fields.js | 18 +- .../apps/timelion/_expression_typeahead.js | 4 +- test/functional/apps/visualize/_area_chart.js | 8 +- test/functional/apps/visualize/_data_table.js | 23 +- .../apps/visualize/_embedding_chart.js | 5 +- .../functional/apps/visualize/_gauge_chart.js | 4 +- .../apps/visualize/_heatmap_chart.js | 4 +- .../visualize/_histogram_request_start.js | 4 +- test/functional/apps/visualize/_inspector.js | 4 +- test/functional/apps/visualize/_line_chart.js | 4 +- .../apps/visualize/_linked_saved_searches.js | 6 +- .../apps/visualize/_metric_chart.js | 4 +- test/functional/apps/visualize/_pie_chart.js | 22 +- .../apps/visualize/_point_series_options.js | 8 +- test/functional/apps/visualize/_region_map.js | 4 +- test/functional/apps/visualize/_tag_cloud.js | 6 +- test/functional/apps/visualize/_tile_map.js | 10 +- test/functional/apps/visualize/_tsvb_chart.ts | 4 +- .../apps/visualize/_tsvb_markdown.ts | 5 +- test/functional/apps/visualize/_tsvb_table.ts | 2 +- test/functional/apps/visualize/_vega_chart.js | 5 +- .../apps/visualize/_vertical_bar_chart.js | 8 +- .../input_control_options.js | 4 +- .../functional/page_objects/dashboard_page.js | 12 +- test/functional/page_objects/time_picker.js | 17 +- .../page_objects/visual_builder_page.ts | 4 +- .../plugins/kbn_tp_run_pipeline/package.json | 2 +- .../kbn_tp_custom_visualizations/package.json | 2 +- .../kbn_tp_embeddable_explorer/package.json | 2 +- .../kbn_tp_sample_panel_action/package.json | 2 +- .../tests/discover/chart_visualization.js | 6 +- .../__test__/__snapshots__/List.test.tsx.snap | 4 +- .../custom_element_modal.examples.storyshot | 52 +- .../element_card.examples.storyshot | 76 +- .../element_grid.examples.storyshot | 226 +- .../keyboard_shortcuts_doc.examples.storyshot | 3144 ++++++++--------- .../autoplay_settings.examples.storyshot | 6 +- .../toolbar_settings.examples.storyshot | 3 + .../__snapshots__/settings.test.tsx.snap | 5 +- x-pack/legacy/plugins/infra/types/eui.d.ts | 4 - .../__snapshots__/add_license.test.js.snap | 4 +- .../request_trial_extension.test.js.snap | 6 +- .../revert_to_basic.test.js.snap | 6 +- .../__snapshots__/start_trial.test.js.snap | 6 +- .../__snapshots__/top_nav.test.tsx.snap | 1 + .../remote_cluster_form.test.js.snap | 4 +- .../report_info_button.test.tsx.snap | 868 +++-- .../report_listing.test.tsx.snap | 4 +- .../views/components/space_card.test.tsx | 2 +- x-pack/package.json | 2 +- .../feature_controls/discover_security.ts | 4 +- .../feature_controls/discover_spaces.ts | 4 +- .../apps/monitoring/beats/beat_detail.js | 4 +- .../apps/monitoring/beats/cluster.js | 4 +- .../apps/monitoring/beats/listing.js | 4 +- .../apps/monitoring/beats/overview.js | 4 +- .../apps/monitoring/cluster/alerts.js | 12 +- .../apps/monitoring/cluster/list.js | 8 +- .../apps/monitoring/cluster/overview.js | 12 +- .../monitoring/elasticsearch/index_detail.js | 8 +- .../apps/monitoring/elasticsearch/indices.js | 4 +- .../monitoring/elasticsearch/node_detail.js | 8 +- .../apps/monitoring/elasticsearch/nodes.js | 8 +- .../apps/monitoring/elasticsearch/overview.js | 4 +- .../apps/monitoring/elasticsearch/shards.js | 4 +- .../apps/monitoring/kibana/instance.js | 4 +- .../apps/monitoring/kibana/instances.js | 4 +- .../apps/monitoring/kibana/overview.js | 4 +- .../apps/monitoring/logstash/pipelines.js | 4 +- .../functional/apps/monitoring/time_filter.js | 6 +- .../functional/apps/security/rbac_phase1.js | 8 +- x-pack/test/functional/apps/uptime/monitor.ts | 4 +- .../test/functional/apps/uptime/overview.ts | 4 +- .../apps/visualize/hybrid_visualization.ts | 4 +- .../test/functional/page_objects/lens_page.ts | 4 +- .../functional/page_objects/reporting_page.js | 8 +- yarn.lock | 64 +- 103 files changed, 2552 insertions(+), 2548 deletions(-) diff --git a/package.json b/package.json index 24735b50b15f3b..798073ef8a427c 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "@elastic/charts": "^14.0.0", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.3.3", diff --git a/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap b/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap index 94c11f01854270..626c91b6a9668e 100644 --- a/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap +++ b/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap @@ -31,7 +31,7 @@ Array [ ] `; -exports[`FlyoutService openFlyout() renders a flyout to the DOM 2`] = `"
Flyout content
"`; +exports[`FlyoutService openFlyout() renders a flyout to the DOM 2`] = `"
Flyout content
"`; exports[`FlyoutService openFlyout() with a currently active flyout replaces the current flyout with a new one 1`] = ` Array [ @@ -74,4 +74,4 @@ Array [ ] `; -exports[`FlyoutService openFlyout() with a currently active flyout replaces the current flyout with a new one 2`] = `"
Flyout content 2
"`; +exports[`FlyoutService openFlyout() with a currently active flyout replaces the current flyout with a new one 2`] = `"
Flyout content 2
"`; diff --git a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap index bbcb2096b6f64a..35a7216df8bc6c 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap @@ -67,10 +67,7 @@ exports[`apmUiEnabled 1`] = ` type="logoAPM" /> } - layout="vertical" - textAlign="center" title="APM" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Logs" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Metrics" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="SIEM" - titleElement="span" /> @@ -332,10 +320,7 @@ exports[`isNewKibanaInstance 1`] = ` type="logoLogging" /> } - layout="vertical" - textAlign="center" title="Logs" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Metrics" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="SIEM" - titleElement="span" /> @@ -560,10 +539,7 @@ exports[`mlEnabled 1`] = ` type="logoAPM" /> } - layout="vertical" - textAlign="center" title="APM" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Logs" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Metrics" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="SIEM" - titleElement="span" /> @@ -861,10 +828,7 @@ exports[`render 1`] = ` type="logoLogging" /> } - layout="vertical" - textAlign="center" title="Logs" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Metrics" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="SIEM" - titleElement="span" /> diff --git a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/synopsis.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/synopsis.test.js.snap index 1970d048be4fd7..34cc0eb9265ffa 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/synopsis.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/synopsis.test.js.snap @@ -14,9 +14,7 @@ exports[`props iconType 1`] = ` /> } layout="horizontal" - textAlign="center" title="Great tutorial" - titleElement="span" /> `; @@ -35,9 +33,7 @@ exports[`props iconUrl 1`] = ` /> } layout="horizontal" - textAlign="center" title="Great tutorial" - titleElement="span" /> `; @@ -49,9 +45,7 @@ exports[`props isBeta 1`] = ` description="this is a great tutorial about..." href="link_to_item" layout="horizontal" - textAlign="center" title="Great tutorial" - titleElement="span" /> `; @@ -63,8 +57,6 @@ exports[`render 1`] = ` description="this is a great tutorial about..." href="link_to_item" layout="horizontal" - textAlign="center" title="Great tutorial" - titleElement="span" /> `; diff --git a/src/legacy/core_plugins/status_page/public/components/__snapshots__/metric_tiles.test.js.snap b/src/legacy/core_plugins/status_page/public/components/__snapshots__/metric_tiles.test.js.snap index ce24ff89776c83..b88210758a00d8 100644 --- a/src/legacy/core_plugins/status_page/public/components/__snapshots__/metric_tiles.test.js.snap +++ b/src/legacy/core_plugins/status_page/public/components/__snapshots__/metric_tiles.test.js.snap @@ -4,9 +4,7 @@ exports[`byte metric 1`] = ` `; @@ -14,9 +12,7 @@ exports[`float metric 1`] = ` `; @@ -24,9 +20,7 @@ exports[`general metric 1`] = ` `; @@ -34,8 +28,6 @@ exports[`millisecond metric 1`] = ` `; diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts index e3f73ad4bcaf86..38ee5b7db39c47 100644 --- a/test/accessibility/apps/discover.ts +++ b/test/accessibility/apps/discover.ts @@ -19,9 +19,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; -const FROM_TIME = '2015-09-19 06:31:44.000'; -const TO_TIME = '2015-09-23 18:31:44.000'; - export default function({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'timePicker']); const a11y = getService('a11y'); @@ -36,7 +33,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { defaultIndex: 'logstash-*', }); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(FROM_TIME, TO_TIME); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); it('main view', async () => { diff --git a/test/functional/apps/context/_discover_navigation.js b/test/functional/apps/context/_discover_navigation.js index 147d0e74d1c98b..cb328dfa98e3ec 100644 --- a/test/functional/apps/context/_discover_navigation.js +++ b/test/functional/apps/context/_discover_navigation.js @@ -19,8 +19,6 @@ import expect from '@kbn/expect'; -const TEST_DISCOVER_START_TIME = '2015-09-19 06:31:44.000'; -const TEST_DISCOVER_END_TIME = '2015-09-23 18:31:44.000'; const TEST_COLUMN_NAMES = ['@message']; const TEST_FILTER_COLUMN_NAMES = [['extension', 'jpg'], ['geo.src', 'IN']]; @@ -34,7 +32,7 @@ export default function ({ getService, getPageObjects }) { this.tags('smoke'); before(async function () { await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(TEST_DISCOVER_START_TIME, TEST_DISCOVER_END_TIME); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await Promise.all(TEST_COLUMN_NAMES.map((columnName) => ( PageObjects.discover.clickFieldListItemAdd(columnName) ))); diff --git a/test/functional/apps/dashboard/dashboard_time.js b/test/functional/apps/dashboard/dashboard_time.js index 917157e54eee05..39ce43e19d7517 100644 --- a/test/functional/apps/dashboard/dashboard_time.js +++ b/test/functional/apps/dashboard/dashboard_time.js @@ -21,9 +21,6 @@ import expect from '@kbn/expect'; const dashboardName = 'Dashboard Test Time'; -const fromTime = '2015-09-19 06:31:44.000'; -const toTime = '2015-09-23 18:31:44.000'; - export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['dashboard', 'header', 'timePicker']); const browser = getService('browser'); @@ -46,31 +43,31 @@ export default function ({ getPageObjects, getService }) { }); it('Does not set the time picker on open', async () => { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.dashboard.loadSavedDashboard(dashboardName); const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.equal('Sep 19, 2015 @ 06:31:44.000'); - expect(time.end).to.equal('Sep 23, 2015 @ 18:31:44.000'); + expect(time.start).to.equal(PageObjects.timePicker.defaultStartTime); + expect(time.end).to.equal(PageObjects.timePicker.defaultEndTime); }); }); describe('dashboard with stored timed', function () { it('is saved with time', async function () { await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: true }); }); it('sets time on open', async function () { - await PageObjects.timePicker.setAbsoluteRange('2019-01-01 00:00:00.000', '2019-01-02 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2019 @ 00:00:00.000', 'Jan 2, 2019 @ 00:00:00.000'); await PageObjects.dashboard.loadSavedDashboard(dashboardName); const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.equal('Sep 19, 2015 @ 06:31:44.000'); - expect(time.end).to.equal('Sep 23, 2015 @ 18:31:44.000'); + expect(time.start).to.equal(PageObjects.timePicker.defaultStartTime); + expect(time.end).to.equal(PageObjects.timePicker.defaultEndTime); }); // If time is stored with a dashboard, it's supposed to override the current time settings when opened. @@ -99,7 +96,7 @@ export default function ({ getPageObjects, getService }) { it('preserved during navigation', async function () { await PageObjects.dashboard.loadSavedDashboard(dashboardName); - await PageObjects.timePicker.setAbsoluteRange('2019-01-01 00:00:00.000', '2019-01-02 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2019 @ 00:00:00.000', 'Jan 2, 2019 @ 00:00:00.000'); await PageObjects.header.clickVisualize(); await PageObjects.header.clickDashboard(); diff --git a/test/functional/apps/dashboard/dashboard_time_picker.js b/test/functional/apps/dashboard/dashboard_time_picker.js index f09f3fc1de2ad6..ab1d1ff74168a9 100644 --- a/test/functional/apps/dashboard/dashboard_time_picker.js +++ b/test/functional/apps/dashboard/dashboard_time_picker.js @@ -26,6 +26,7 @@ export default function ({ getService, getPageObjects }) { const dashboardVisualizations = getService('dashboardVisualizations'); const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'timePicker']); const browser = getService('browser'); + const kibanaServer = getService('kibanaServer'); describe('dashboard time picker', function describeIndexTests() { before(async function () { @@ -33,6 +34,11 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.preserveCrossAppState(); }); + after(async () => { + await kibanaServer.uiSettings.replace({}); + await browser.refresh(); + }); + it('Visualization updated when time picker changes', async () => { await PageObjects.dashboard.clickNewDashboard(); await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); @@ -49,7 +55,7 @@ export default function ({ getService, getPageObjects }) { await dashboardExpect.docTableFieldCount(150); // Set to time range with no data - await PageObjects.timePicker.setAbsoluteRange('2000-01-01 00:00:00.000', '2000-01-01 01:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2000 @ 00:00:00.000', 'Jan 1, 2000 @ 01:00:00.000'); await dashboardExpect.docTableFieldCount(0); }); @@ -72,5 +78,16 @@ export default function ({ getService, getPageObjects }) { expect(time.end).to.be('Nov 17, 2015 @ 18:01:36.621'); expect(refresh.interval).to.be('2'); }); + + it('Timepicker respects dateFormat from UI settings', async () => { + await kibanaServer.uiSettings.replace({ 'dateFormat': 'YYYY-MM-DD HH:mm:ss.SSS', }); + await browser.refresh(); + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); + // Same date range as `setTimepickerInHistoricalDataRange` + await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000'); + await pieChart.expectPieSliceCount(10); + }); }); } diff --git a/test/functional/apps/dashboard/embeddable_rendering.js b/test/functional/apps/dashboard/embeddable_rendering.js index d90de4204bc76d..bdbfd41b437eb7 100644 --- a/test/functional/apps/dashboard/embeddable_rendering.js +++ b/test/functional/apps/dashboard/embeddable_rendering.js @@ -102,8 +102,8 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.preserveCrossAppState(); await PageObjects.dashboard.clickNewDashboard(); - const fromTime = '2018-01-01 00:00:00.000'; - const toTime = '2018-04-13 00:00:00.000'; + const fromTime = 'Jan 1, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); }); @@ -145,8 +145,8 @@ export default function ({ getService, getPageObjects }) { it('data rendered correctly when dashboard is opened from listing page', async () => { // Change the time to make sure that it's updated when re-opened from the listing page. - const fromTime = '2018-05-10 00:00:00.000'; - const toTime = '2018-05-11 00:00:00.000'; + const fromTime = 'May 10, 2018 @ 00:00:00.000'; + const toTime = 'May 11, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.dashboard.loadSavedDashboard('embeddable rendering test'); await PageObjects.dashboard.waitForRenderComplete(); @@ -162,16 +162,16 @@ export default function ({ getService, getPageObjects }) { }); it('panels are updated when time changes outside of data', async () => { - const fromTime = '2018-05-11 00:00:00.000'; - const toTime = '2018-05-12 00:00:00.000'; + const fromTime = 'May 11, 2018 @ 00:00:00.000'; + const toTime = 'May 12, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.dashboard.waitForRenderComplete(); await expectNoDataRenders(); }); it('panels are updated when time changes inside of data', async () => { - const fromTime = '2018-01-01 00:00:00.000'; - const toTime = '2018-04-13 00:00:00.000'; + const fromTime = 'Jan 1, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.dashboard.waitForRenderComplete(); await expectAllDataRenders(); diff --git a/test/functional/apps/dashboard/time_zones.js b/test/functional/apps/dashboard/time_zones.js index 19516e5092c1cd..30031882ae09e2 100644 --- a/test/functional/apps/dashboard/time_zones.js +++ b/test/functional/apps/dashboard/time_zones.js @@ -51,8 +51,8 @@ export default function ({ getService, getPageObjects }) { it('Exported dashboard adjusts EST time to UTC', async () => { const time = await PageObjects.timePicker.getTimeConfigAsAbsoluteTimes(); - expect(time.start).to.be('2018-04-10 03:00:00.000'); - expect(time.end).to.be('2018-04-10 04:00:00.000'); + expect(time.start).to.be('Apr 10, 2018 @ 03:00:00.000'); + expect(time.end).to.be('Apr 10, 2018 @ 04:00:00.000'); await pieChart.expectPieSliceCount(4); }); @@ -63,8 +63,8 @@ export default function ({ getService, getPageObjects }) { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.loadSavedDashboard('time zone test'); const time = await PageObjects.timePicker.getTimeConfigAsAbsoluteTimes(); - expect(time.start).to.be('2018-04-09 22:00:00.000'); - expect(time.end).to.be('2018-04-09 23:00:00.000'); + expect(time.start).to.be('Apr 9, 2018 @ 22:00:00.000'); + expect(time.end).to.be('Apr 9, 2018 @ 23:00:00.000'); await pieChart.expectPieSliceCount(4); }); }); diff --git a/test/functional/apps/dashboard/view_edit.js b/test/functional/apps/dashboard/view_edit.js index 958a889271b617..74ddb476064c58 100644 --- a/test/functional/apps/dashboard/view_edit.js +++ b/test/functional/apps/dashboard/view_edit.js @@ -75,7 +75,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: true }); await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange('2013-09-19 06:31:44.000', '2013-09-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2013 @ 06:31:44.000', 'Sep 19, 2013 @ 06:31:44.000'); await PageObjects.dashboard.clickCancelOutOfEditMode(); // confirm lose changes @@ -161,10 +161,10 @@ export default function ({ getService, getPageObjects }) { describe('and preserves edits on cancel', function () { it('when time changed is stored with dashboard', async function () { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); - await PageObjects.timePicker.setAbsoluteRange('2013-09-19 06:31:44.000', '2013-09-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2013 @ 06:31:44.000', 'Sep 19, 2013 @ 06:31:44.000'); await PageObjects.dashboard.saveDashboard(dashboardName, true); await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2015 @ 06:31:44.000', 'Sep 19, 2015 @ 06:31:44.000'); await PageObjects.dashboard.clickCancelOutOfEditMode(); await PageObjects.common.clickCancelOnModal(); @@ -186,7 +186,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.setTimepickerInDataRange(); await PageObjects.dashboard.saveDashboard(dashboardName, true); await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange('2013-09-19 06:31:44.000', '2013-09-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2013 @ 06:31:44.000', 'Sep 19, 2013 @ 06:31:44.000'); const newTime = await PageObjects.timePicker.getTimeConfig(); await PageObjects.dashboard.clickCancelOutOfEditMode(); @@ -208,7 +208,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: false }); await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange('2014-10-19 06:31:44.000', '2014-12-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Oct 19, 2014 @ 06:31:44.000', 'Dec 19, 2014 @ 06:31:44.000'); await PageObjects.dashboard.clickCancelOutOfEditMode(); await PageObjects.common.expectConfirmModalOpenState(false); diff --git a/test/functional/apps/discover/_date_nanos.js b/test/functional/apps/discover/_date_nanos.js index 6876c8eb6daa41..d9eb40c16c2d48 100644 --- a/test/functional/apps/discover/_date_nanos.js +++ b/test/functional/apps/discover/_date_nanos.js @@ -23,8 +23,8 @@ export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['common', 'timePicker', 'discover']); const kibanaServer = getService('kibanaServer'); - const fromTime = '2019-09-22 20:31:44.000'; - const toTime = '2019-09-23 03:31:44.000'; + const fromTime = 'Sep 22, 2019 @ 20:31:44.000'; + const toTime = 'Sep 23, 2019 @ 03:31:44.000'; describe('date_nanos', function () { @@ -41,8 +41,8 @@ export default function ({ getService, getPageObjects }) { it('should show a timestamp with nanoseconds in the first result row', async function () { const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.be('Sep 22, 2019 @ 20:31:44.000'); - expect(time.end).to.be('Sep 23, 2019 @ 03:31:44.000'); + expect(time.start).to.be(fromTime); + expect(time.end).to.be(toTime); const rowData = await PageObjects.discover.getDocTableIndex(1); expect(rowData.startsWith('Sep 22, 2019 @ 23:50:13.253123345')).to.be.ok(); }); diff --git a/test/functional/apps/discover/_date_nanos_mixed.js b/test/functional/apps/discover/_date_nanos_mixed.js index 8c9a7eb4d5f138..c77ea3b2915e1e 100644 --- a/test/functional/apps/discover/_date_nanos_mixed.js +++ b/test/functional/apps/discover/_date_nanos_mixed.js @@ -23,8 +23,8 @@ export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['common', 'timePicker', 'discover']); const kibanaServer = getService('kibanaServer'); - const fromTime = '2019-01-01 00:00:00.000'; - const toTime = '2019-01-01 23:59:59.999'; + const fromTime = 'Jan 1, 2019 @ 00:00:00.000'; + const toTime = 'Jan 1, 2019 @ 23:59:59.999'; describe('date_nanos_mixed', function () { diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index 9d3f95e28942a8..94b2941ecd3d18 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -33,8 +33,6 @@ export default function ({ getService, getPageObjects }) { }; describe('discover test', function describeIndexTests() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('load kibana index with default index pattern'); @@ -45,7 +43,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace(defaultSettings); log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('query', function () { @@ -54,8 +52,8 @@ export default function ({ getService, getPageObjects }) { it('should show correct time range string by timepicker', async function () { const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.be('Sep 19, 2015 @ 06:31:44.000'); - expect(time.end).to.be('Sep 23, 2015 @ 18:31:44.000'); + expect(time.start).to.be(PageObjects.timePicker.defaultStartTime); + expect(time.end).to.be(PageObjects.timePicker.defaultEndTime); const rowData = await PageObjects.discover.getDocTableIndex(1); log.debug('check the newest doc timestamp in UTC (check diff timezone in last test)'); expect(rowData.startsWith('Sep 22, 2015 @ 23:50:13.253')).to.be.ok(); @@ -88,12 +86,12 @@ export default function ({ getService, getPageObjects }) { it('should show correct time range string in chart', async function () { const actualTimeString = await PageObjects.discover.getChartTimespan(); - const expectedTimeString = `Sep 19, 2015 @ 06:31:44.000 - Sep 23, 2015 @ 18:31:44.000`; + const expectedTimeString = `${PageObjects.timePicker.defaultStartTime} - ${PageObjects.timePicker.defaultEndTime}`; expect(actualTimeString).to.be(expectedTimeString); }); it('should modify the time range when a bar is clicked', async function () { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.clickHistogramBar(); const time = await PageObjects.timePicker.getTimeConfig(); expect(time.start).to.be('Sep 21, 2015 @ 09:00:00.000'); @@ -103,7 +101,7 @@ export default function ({ getService, getPageObjects }) { }); it('should modify the time range when the histogram is brushed', async function () { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.brushHistogram(); const newDurationHours = await PageObjects.timePicker.getTimeDurationInHours(); @@ -113,7 +111,7 @@ export default function ({ getService, getPageObjects }) { }); it('should show correct initial chart interval of Auto', async function () { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.waitUntilSearchingHasFinished(); const actualInterval = await PageObjects.discover.getChartInterval(); @@ -135,8 +133,8 @@ export default function ({ getService, getPageObjects }) { }); describe('query #2, which has an empty time range', () => { - const fromTime = '1999-06-11 09:22:11.000'; - const toTime = '1999-06-12 11:21:04.000'; + const fromTime = 'Jun 11, 1999 @ 09:22:11.000'; + const toTime = 'Jun 12, 1999 @ 11:21:04.000'; before(async () => { log.debug('setAbsoluteRangeForAnotherQuery'); @@ -159,7 +157,7 @@ export default function ({ getService, getPageObjects }) { before(async () => { log.debug('setAbsoluteRangeForAnotherQuery'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.waitUntilSearchingHasFinished(); }); @@ -213,7 +211,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'America/Phoenix' }); await browser.refresh(); await PageObjects.header.awaitKibanaChrome(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('check that the newest doc timestamp is now -7 hours from the UTC time in the first test'); const rowData = await PageObjects.discover.getDocTableIndex(1); diff --git a/test/functional/apps/discover/_doc_navigation.js b/test/functional/apps/discover/_doc_navigation.js index e9afa7c9b4c195..dc9f6c35174642 100644 --- a/test/functional/apps/discover/_doc_navigation.js +++ b/test/functional/apps/discover/_doc_navigation.js @@ -19,8 +19,6 @@ import expect from '@kbn/expect'; -const TEST_DOC_START_TIME = '2015-09-19 06:31:44.000'; -const TEST_DOC_END_TIME = '2015-09-23 18:31:44.000'; const TEST_COLUMN_NAMES = ['@message']; const TEST_FILTER_COLUMN_NAMES = [['extension', 'jpg'], ['geo.src', 'IN']]; @@ -35,7 +33,7 @@ export default function ({ getService, getPageObjects }) { before(async function () { await esArchiver.loadIfNeeded('logstash_functional'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(TEST_DOC_START_TIME, TEST_DOC_END_TIME); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await Promise.all(TEST_COLUMN_NAMES.map((columnName) => ( PageObjects.discover.clickFieldListItemAdd(columnName) ))); diff --git a/test/functional/apps/discover/_field_data.js b/test/functional/apps/discover/_field_data.js index 828975445e1ef6..38d9a89eecbf3e 100644 --- a/test/functional/apps/discover/_field_data.js +++ b/test/functional/apps/discover/_field_data.js @@ -30,8 +30,6 @@ export default function ({ getService, getPageObjects }) { describe('discover tab', function describeIndexTests() { this.tags('smoke'); before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; await esArchiver.loadIfNeeded('logstash_functional'); await esArchiver.load('discover'); @@ -41,7 +39,7 @@ export default function ({ getService, getPageObjects }) { }); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('field data', function () { diff --git a/test/functional/apps/discover/_inspector.js b/test/functional/apps/discover/_inspector.js index 6a2144e829920c..bd04cd6d1bd643 100644 --- a/test/functional/apps/discover/_inspector.js +++ b/test/functional/apps/discover/_inspector.js @@ -58,7 +58,7 @@ export default function ({ getService, getPageObjects }) { }); it('should display request stats with results', async () => { - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await inspector.open(); const requestStats = await inspector.getTableData(); diff --git a/test/functional/apps/discover/_saved_queries.js b/test/functional/apps/discover/_saved_queries.js index 54b026135025c6..8fbc40f86e8dca 100644 --- a/test/functional/apps/discover/_saved_queries.js +++ b/test/functional/apps/discover/_saved_queries.js @@ -34,8 +34,6 @@ export default function ({ getService, getPageObjects }) { const testSubjects = getService('testSubjects'); describe('saved queries saved objects', function describeIndexTests() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('load kibana index with default index pattern'); @@ -46,7 +44,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace(defaultSettings); log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('saved query management component functionality', function () { @@ -55,8 +53,8 @@ export default function ({ getService, getPageObjects }) { log.debug('set up a query with filters to save'); await queryBar.setQuery('response:200'); await filterBar.addFilter('extension.raw', 'is one of', 'jpg'); - const fromTime = '2015-09-20 08:00:00.000'; - const toTime = '2015-09-21 08:00:00.000'; + const fromTime = 'Sep 20, 2015 @ 08:00:00.000'; + const toTime = 'Sep 21, 2015 @ 08:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); }); @@ -79,15 +77,13 @@ export default function ({ getService, getPageObjects }) { }); it('reinstates filters and the time filter when a saved query has filters and a time filter included', async () => { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await savedQueryManagementComponent.clearCurrentlyLoadedQuery(); await savedQueryManagementComponent.loadSavedQuery('OkResponse'); const timePickerValues = await PageObjects.timePicker.getTimeConfigAsAbsoluteTimes(); expect(await filterBar.hasFilter('extension.raw', 'jpg')).to.be(true); - expect(timePickerValues.start).to.not.eql(fromTime); - expect(timePickerValues.end).to.not.eql(toTime); + expect(timePickerValues.start).to.not.eql(PageObjects.timePicker.defaultStartTime); + expect(timePickerValues.end).to.not.eql(PageObjects.timePicker.defaultEndTime); }); it('allows saving changes to a currently loaded query via the saved query management component', async () => { diff --git a/test/functional/apps/discover/_shared_links.js b/test/functional/apps/discover/_shared_links.js index 0b2b4f14f126dd..8381d9bc7caeae 100644 --- a/test/functional/apps/discover/_shared_links.js +++ b/test/functional/apps/discover/_shared_links.js @@ -38,9 +38,6 @@ export default function ({ getService, getPageObjects }) { baseUrl = baseUrl.replace(':80', '').replace(':443', ''); log.debug('New baseUrl = ' + baseUrl); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - // delete .kibana index and update configDoc await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*', @@ -57,7 +54,7 @@ export default function ({ getService, getPageObjects }) { log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); //After hiding the time picker, we need to wait for //the refresh button to hide before clicking the share button diff --git a/test/functional/apps/discover/_sidebar.js b/test/functional/apps/discover/_sidebar.js index 26a47b0a124222..4cf8fd44da2395 100644 --- a/test/functional/apps/discover/_sidebar.js +++ b/test/functional/apps/discover/_sidebar.js @@ -27,8 +27,6 @@ export default function ({ getService, getPageObjects }) { describe('discover sidebar', function describeIndexTests() { before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; // delete .kibana index and update configDoc await kibanaServer.uiSettings.replace({ @@ -44,7 +42,7 @@ export default function ({ getService, getPageObjects }) { log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('field filtering', function () { diff --git a/test/functional/apps/discover/_source_filters.js b/test/functional/apps/discover/_source_filters.js index 14ecde383fd442..06c81acbd5d436 100644 --- a/test/functional/apps/discover/_source_filters.js +++ b/test/functional/apps/discover/_source_filters.js @@ -27,8 +27,6 @@ export default function ({ getService, getPageObjects }) { describe('source filters', function describeIndexTests() { before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; // delete .kibana index and update configDoc await kibanaServer.uiSettings.replace({ @@ -44,7 +42,7 @@ export default function ({ getService, getPageObjects }) { log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); //After hiding the time picker, we need to wait for //the refresh button to hide before clicking the share button diff --git a/test/functional/apps/home/_navigation.ts b/test/functional/apps/home/_navigation.ts index c60788b64b2a70..58e0793b2d547f 100644 --- a/test/functional/apps/home/_navigation.ts +++ b/test/functional/apps/home/_navigation.ts @@ -28,8 +28,6 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const retry = getService('retry'); const kibanaServer = getService('kibanaServer'); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const getHost = () => { if (process.env.TEST_KIBANA_HOSTNAME) { @@ -77,7 +75,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { // Navigate to discover app await appsMenu.clickLink('Discover'); const discoverUrl = await browser.getCurrentUrl(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); const modifiedTimeDiscoverUrl = await browser.getCurrentUrl(); // Navigate to dashboard app diff --git a/test/functional/apps/home/_sample_data.js b/test/functional/apps/home/_sample_data.js index 954c2dd110585c..44cb7c36a7f282 100644 --- a/test/functional/apps/home/_sample_data.js +++ b/test/functional/apps/home/_sample_data.js @@ -18,6 +18,7 @@ */ import expect from '@kbn/expect'; +import moment from 'moment'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); @@ -85,10 +86,9 @@ export default function ({ getService, getPageObjects }) { await PageObjects.home.launchSampleDataSet('flights'); await PageObjects.header.waitUntilLoadingHasFinished(); await renderable.waitForRender(); - const today = new Date(); - const todayYearMonthDay = today.toISOString().substring(0, 10); - const fromTime = `${todayYearMonthDay} 00:00:00.000`; - const toTime = `${todayYearMonthDay} 23:59:59.999`; + const todayYearMonthDay = moment().format('MMM D, YYYY'); + const fromTime = `${todayYearMonthDay} @ 00:00:00.000`; + const toTime = `${todayYearMonthDay} @ 23:59:59.999`; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(18); @@ -119,10 +119,9 @@ export default function ({ getService, getPageObjects }) { await PageObjects.home.launchSampleDataSet('logs'); await PageObjects.header.waitUntilLoadingHasFinished(); await renderable.waitForRender(); - const today = new Date(); - const todayYearMonthDay = today.toISOString().substring(0, 10); - const fromTime = `${todayYearMonthDay} 00:00:00.000`; - const toTime = `${todayYearMonthDay} 23:59:59.999`; + const todayYearMonthDay = moment().format('MMM D, YYYY'); + const fromTime = `${todayYearMonthDay} @ 00:00:00.000`; + const toTime = `${todayYearMonthDay} @ 23:59:59.999`; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(11); @@ -132,10 +131,9 @@ export default function ({ getService, getPageObjects }) { await PageObjects.home.launchSampleDataSet('ecommerce'); await PageObjects.header.waitUntilLoadingHasFinished(); await renderable.waitForRender(); - const today = new Date(); - const todayYearMonthDay = today.toISOString().substring(0, 10); - const fromTime = `${todayYearMonthDay} 00:00:00.000`; - const toTime = `${todayYearMonthDay} 23:59:59.999`; + const todayYearMonthDay = moment().format('MMM D, YYYY'); + const fromTime = `${todayYearMonthDay} @ 00:00:00.000`; + const toTime = `${todayYearMonthDay} @ 23:59:59.999`; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(12); diff --git a/test/functional/apps/management/_handle_alias.js b/test/functional/apps/management/_handle_alias.js index a5994fc5dd1b49..99941d37df9e77 100644 --- a/test/functional/apps/management/_handle_alias.js +++ b/test/functional/apps/management/_handle_alias.js @@ -72,8 +72,8 @@ export default function ({ getService, getPageObjects }) { it('should be able to discover and verify no of hits for alias2', async function () { const expectedHitCount = '5'; - const fromTime = '2016-11-12 05:00:00.000'; - const toTime = '2016-11-19 05:00:00.000'; + const fromTime = 'Nov 12, 2016 @ 05:00:00.000'; + const toTime = 'Nov 19, 2016 @ 05:00:00.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.discover.selectIndexPattern('alias2'); diff --git a/test/functional/apps/management/_kibana_settings.js b/test/functional/apps/management/_kibana_settings.js index 9fb302cdba00a6..e5ae709b34d6d0 100644 --- a/test/functional/apps/management/_kibana_settings.js +++ b/test/functional/apps/management/_kibana_settings.js @@ -55,7 +55,7 @@ export default function ({ getService, getPageObjects }) { it('when false, dashboard state is unhashed', async function () { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); const currentUrl = await browser.getCurrentUrl(); const urlPieces = currentUrl.match(/(.*)?_g=(.*)&_a=(.*)/); const globalState = urlPieces[2]; @@ -78,7 +78,7 @@ export default function ({ getService, getPageObjects }) { it('when true, dashboard state is hashed', async function () { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); const currentUrl = await browser.getCurrentUrl(); const urlPieces = currentUrl.match(/(.*)?_g=(.*)&_a=(.*)/); const globalState = urlPieces[2]; diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js index 94e38402deebef..7a21e5171595fe 100644 --- a/test/functional/apps/management/_scripted_fields.js +++ b/test/functional/apps/management/_scripted_fields.js @@ -124,8 +124,8 @@ export default function ({ getService, getPageObjects }) { }); it('should see scripted field value in Discover', async function () { - const fromTime = '2015-09-17 06:31:44.000'; - const toTime = '2015-09-18 18:31:44.000'; + const fromTime = 'Sep 17, 2015 @ 06:31:44.000'; + const toTime = 'Sep 18, 2015 @ 18:31:44.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); @@ -186,8 +186,8 @@ export default function ({ getService, getPageObjects }) { }); it('should see scripted field value in Discover', async function () { - const fromTime = '2015-09-17 06:31:44.000'; - const toTime = '2015-09-18 18:31:44.000'; + const fromTime = 'Sep 17, 2015 @ 06:31:44.000'; + const toTime = 'Sep 18, 2015 @ 18:31:44.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); @@ -246,8 +246,8 @@ export default function ({ getService, getPageObjects }) { }); it('should see scripted field value in Discover', async function () { - const fromTime = '2015-09-17 06:31:44.000'; - const toTime = '2015-09-18 18:31:44.000'; + const fromTime = 'Sep 17, 2015 @ 06:31:44.000'; + const toTime = 'Sep 18, 2015 @ 18:31:44.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); @@ -307,8 +307,8 @@ export default function ({ getService, getPageObjects }) { }); it('should see scripted field value in Discover', async function () { - const fromTime = '2015-09-17 19:22:00.000'; - const toTime = '2015-09-18 07:00:00.000'; + const fromTime = 'Sep 17, 2015 @ 19:22:00.000'; + const toTime = 'Sep 18, 2015 @ 07:00:00.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); @@ -326,7 +326,7 @@ export default function ({ getService, getPageObjects }) { it('should filter by scripted field value in Discover', async function () { await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2); - await log.debug('filter by "2015-09-17 23:00" in the expanded scripted field list'); + await log.debug('filter by "Sep 17, 2015 @ 23:00" in the expanded scripted field list'); await PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName2, '2015-09-17 23:00'); await PageObjects.header.waitUntilLoadingHasFinished(); diff --git a/test/functional/apps/timelion/_expression_typeahead.js b/test/functional/apps/timelion/_expression_typeahead.js index 7cc0740823f3c5..55297c68104972 100644 --- a/test/functional/apps/timelion/_expression_typeahead.js +++ b/test/functional/apps/timelion/_expression_typeahead.js @@ -24,11 +24,9 @@ export default function ({ getPageObjects }) { describe('expression typeahead', () => { before(async () => { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; await PageObjects.timelion.initTests(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); it('should display function suggestions filtered by function name', async () => { diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js index 963b7f25bc1c91..c6b33886a2456a 100644 --- a/test/functional/apps/visualize/_area_chart.js +++ b/test/functional/apps/visualize/_area_chart.js @@ -30,8 +30,6 @@ export default function ({ getService, getPageObjects }) { const vizName1 = 'Visualization AreaChart Name Test'; const initAreaChart = async () => { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); @@ -39,7 +37,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.clickAreaChart(); log.debug('clickNewSearch'); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Click X-axis'); await PageObjects.visualize.clickBucket('X-axis'); log.debug('Click Date Histogram'); @@ -327,8 +325,8 @@ export default function ({ getService, getPageObjects }) { }); describe('date histogram with long time range', () => { // that dataset spans from Oct 26, 2013 @ 06:10:17.855 to Apr 18, 2019 @ 11:38:12.790 - const fromTime = '2013-01-01 00:00:00.000'; - const toTime = '2020-01-01 00:00:00.000'; + const fromTime = 'Jan 1, 2013 @ 00:00:00.000'; + const toTime = 'Jan 1, 2020 @ 00:00:00.000'; it('should render a yearly area with 12 svg paths', async () => { log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); diff --git a/test/functional/apps/visualize/_data_table.js b/test/functional/apps/visualize/_data_table.js index b540c1e949fbc1..51c0984c89fed5 100644 --- a/test/functional/apps/visualize/_data_table.js +++ b/test/functional/apps/visualize/_data_table.js @@ -26,9 +26,6 @@ export default function ({ getService, getPageObjects }) { const filterBar = getService('filterBar'); const PageObjects = getPageObjects(['common', 'visualize', 'header', 'timePicker']); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - describe('data table', function indexPatternCreation() { const vizName1 = 'Visualization DataTable'; @@ -39,7 +36,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.clickDataTable(); log.debug('clickNewSearch'); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = Split rows'); await PageObjects.visualize.clickBucket('Split rows'); log.debug('Aggregation = Histogram'); @@ -112,7 +109,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Range'); await PageObjects.visualize.selectField('bytes'); @@ -157,7 +154,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Metric', 'metrics'); await PageObjects.visualize.selectAggregation('Average Bucket', 'metrics'); await PageObjects.visualize.selectAggregation('Terms', 'metrics', 'buckets'); @@ -172,7 +169,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Date Histogram'); await PageObjects.visualize.selectField('@timestamp'); @@ -191,7 +188,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Date Histogram'); await PageObjects.visualize.selectField('@timestamp'); @@ -227,7 +224,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickMetricEditor(); await PageObjects.visualize.selectAggregation('Top Hit', 'metrics'); await PageObjects.visualize.selectField('agent.raw', 'metrics'); @@ -241,7 +238,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Range'); await PageObjects.visualize.selectField('bytes'); @@ -259,7 +256,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Terms'); await PageObjects.visualize.selectField('extension.raw'); @@ -297,7 +294,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Terms'); await PageObjects.visualize.selectField('extension.raw'); @@ -392,7 +389,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split table'); await PageObjects.visualize.selectAggregation('Terms'); await PageObjects.visualize.selectField('extension.raw'); diff --git a/test/functional/apps/visualize/_embedding_chart.js b/test/functional/apps/visualize/_embedding_chart.js index 12bc53ec265073..fcf5e549543477 100644 --- a/test/functional/apps/visualize/_embedding_chart.js +++ b/test/functional/apps/visualize/_embedding_chart.js @@ -26,9 +26,6 @@ export default function ({ getService, getPageObjects }) { const embedding = getService('embedding'); const PageObjects = getPageObjects(['common', 'visualize', 'header', 'timePicker']); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - describe('embedding', () => { describe('a data table', () => { @@ -36,7 +33,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Date Histogram'); await PageObjects.visualize.selectField('@timestamp'); diff --git a/test/functional/apps/visualize/_gauge_chart.js b/test/functional/apps/visualize/_gauge_chart.js index 0d0383ba91aa74..2125717247e9e8 100644 --- a/test/functional/apps/visualize/_gauge_chart.js +++ b/test/functional/apps/visualize/_gauge_chart.js @@ -29,8 +29,6 @@ export default function ({ getService, getPageObjects }) { // FLAKY: https://github.com/elastic/kibana/issues/45089 describe('gauge chart', function indexPatternCreation() { this.tags('smoke'); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; async function initGaugeVis() { log.debug('navigateToApp visualize'); @@ -38,7 +36,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickGauge'); await PageObjects.visualize.clickGauge(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } before(initGaugeVis); diff --git a/test/functional/apps/visualize/_heatmap_chart.js b/test/functional/apps/visualize/_heatmap_chart.js index ac48f78b5dde76..547ecdd5988118 100644 --- a/test/functional/apps/visualize/_heatmap_chart.js +++ b/test/functional/apps/visualize/_heatmap_chart.js @@ -27,8 +27,6 @@ export default function ({ getService, getPageObjects }) { describe('heatmap chart', function indexPatternCreation() { this.tags('smoke'); const vizName1 = 'Visualization HeatmapChart'; - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('navigateToApp visualize'); @@ -36,7 +34,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickHeatmapChart'); await PageObjects.visualize.clickHeatmapChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = X-Axis'); await PageObjects.visualize.clickBucket('X-axis'); log.debug('Aggregation = Date Histogram'); diff --git a/test/functional/apps/visualize/_histogram_request_start.js b/test/functional/apps/visualize/_histogram_request_start.js index 76709e3ed968f2..10b87d204d862c 100644 --- a/test/functional/apps/visualize/_histogram_request_start.js +++ b/test/functional/apps/visualize/_histogram_request_start.js @@ -26,15 +26,13 @@ export default function ({ getService, getPageObjects }) { describe('histogram agg onSearchRequestStart', function () { before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); log.debug('clickDataTable'); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = Split Rows'); await PageObjects.visualize.clickBucket('Split rows'); log.debug('Aggregation = Histogram'); diff --git a/test/functional/apps/visualize/_inspector.js b/test/functional/apps/visualize/_inspector.js index 3c45063a1a16d9..5917216cad40fe 100644 --- a/test/functional/apps/visualize/_inspector.js +++ b/test/functional/apps/visualize/_inspector.js @@ -27,14 +27,12 @@ export default function ({ getService, getPageObjects }) { describe('inspector', function describeIndexTests() { this.tags('smoke'); before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickVerticalBarChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('inspector table', function indexPatternCreation() { diff --git a/test/functional/apps/visualize/_line_chart.js b/test/functional/apps/visualize/_line_chart.js index 29116b0ca56c4b..cbadb7408f9855 100644 --- a/test/functional/apps/visualize/_line_chart.js +++ b/test/functional/apps/visualize/_line_chart.js @@ -30,15 +30,13 @@ export default function ({ getService, getPageObjects }) { const vizName1 = 'Visualization LineChart'; const initLineChart = async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); log.debug('clickLineChart'); await PageObjects.visualize.clickLineChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = Split chart'); await PageObjects.visualize.clickBucket('Split chart'); log.debug('Aggregation = Terms'); diff --git a/test/functional/apps/visualize/_linked_saved_searches.js b/test/functional/apps/visualize/_linked_saved_searches.js index 5343873e9e0a5d..4d9553b4d9262c 100644 --- a/test/functional/apps/visualize/_linked_saved_searches.js +++ b/test/functional/apps/visualize/_linked_saved_searches.js @@ -25,8 +25,6 @@ export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['common', 'discover', 'visualize', 'header', 'timePicker']); describe('visualize app', function describeIndexTests() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; describe('linked saved searched', () => { @@ -45,7 +43,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickSavedSearch(savedSearchName); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await retry.waitFor('wait for count to equal 9,109', async () => { const data = await PageObjects.visualize.getTableVisData(); return data.trim() === '9,109'; @@ -53,7 +51,7 @@ export default function ({ getService, getPageObjects }) { }); it('should respect the time filter when linked to a saved search', async () => { - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-21 10:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2015 @ 06:31:44.000', 'Sep 21, 2015 @ 10:00:00.000'); await retry.waitFor('wait for count to equal 3,950', async () => { const data = await PageObjects.visualize.getTableVisData(); return data.trim() === '3,950'; diff --git a/test/functional/apps/visualize/_metric_chart.js b/test/functional/apps/visualize/_metric_chart.js index 237ee1ef50b1e5..1a4f5683f65c66 100644 --- a/test/functional/apps/visualize/_metric_chart.js +++ b/test/functional/apps/visualize/_metric_chart.js @@ -27,8 +27,6 @@ export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['common', 'visualize', 'timePicker']); describe('metric chart', function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('navigateToApp visualize'); @@ -36,7 +34,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickMetric'); await PageObjects.visualize.clickMetric(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); it('should have inspector enabled', async function () { diff --git a/test/functional/apps/visualize/_pie_chart.js b/test/functional/apps/visualize/_pie_chart.js index b9c10aaf578bfa..fc040c038afd0d 100644 --- a/test/functional/apps/visualize/_pie_chart.js +++ b/test/functional/apps/visualize/_pie_chart.js @@ -25,8 +25,6 @@ export default function ({ getService, getPageObjects }) { const pieChart = getService('pieChart'); const inspector = getService('inspector'); const PageObjects = getPageObjects(['common', 'visualize', 'header', 'settings', 'timePicker']); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; describe('pie chart', function () { const vizName1 = 'Visualization PieChart'; @@ -36,7 +34,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Histogram'); @@ -85,7 +83,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Terms'); @@ -187,7 +185,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Filters'); @@ -199,8 +197,8 @@ export default function ({ getService, getPageObjects }) { log.debug('Set the 2nd filter value'); await PageObjects.visualize.setFilterAggregationValue('geo.dest:"CN"', 1); await PageObjects.visualize.clickGo(); - const emptyFromTime = '2016-09-19 06:31:44.000'; - const emptyToTime = '2016-09-23 18:31:44.000'; + const emptyFromTime = 'Sep 19, 2016 @ 06:31:44.000'; + const emptyToTime = 'Sep 23, 2016 @ 18:31:44.000'; log.debug('Switch to a different time range from \"' + emptyFromTime + '\" to \"' + emptyToTime + '\"'); await PageObjects.timePicker.setAbsoluteRange(emptyFromTime, emptyToTime); await PageObjects.visualize.waitForVisualization(); @@ -214,8 +212,10 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + log.debug('Set absolute time range from \"' + + PageObjects.timePicker.defaultStartTime + '\" to \"' + + PageObjects.timePicker.defaultEndTime + '\"'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Histogram'); @@ -275,7 +275,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Filters'); @@ -302,7 +302,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split chart'); await PageObjects.visualize.clickBucket('Split chart'); await PageObjects.visualize.selectAggregation('Terms'); diff --git a/test/functional/apps/visualize/_point_series_options.js b/test/functional/apps/visualize/_point_series_options.js index d175acbd6c02e4..9bbe140d22f9be 100644 --- a/test/functional/apps/visualize/_point_series_options.js +++ b/test/functional/apps/visualize/_point_series_options.js @@ -29,15 +29,13 @@ export default function ({ getService, getPageObjects }) { const inspector = getService('inspector'); async function initChart() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); log.debug('clickLineChart'); await PageObjects.visualize.clickLineChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = X-axis'); await PageObjects.visualize.clickBucket('X-axis'); log.debug('Aggregation = Date Histogram'); @@ -208,8 +206,8 @@ export default function ({ getService, getPageObjects }) { }); it('should show different labels in different timezone', async function () { - const fromTime = '2015-09-22 09:05:47.415'; - const toTime = '2015-09-22 16:08:34.554'; + const fromTime = 'Sep 22, 2015 @ 09:05:47.415'; + const toTime = 'Sep 22, 2015 @ 16:08:34.554'; // note that we're setting the absolute time range while we're in 'America/Phoenix' tz await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.visualize.waitForRenderingCount(); diff --git a/test/functional/apps/visualize/_region_map.js b/test/functional/apps/visualize/_region_map.js index 11eb2e3f0ca836..e94867f903f077 100644 --- a/test/functional/apps/visualize/_region_map.js +++ b/test/functional/apps/visualize/_region_map.js @@ -23,8 +23,6 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { describe('vector map', function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const inspector = getService('inspector'); const log = getService('log'); @@ -38,7 +36,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickRegionMap'); await PageObjects.visualize.clickRegionMap(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = Shape field'); await PageObjects.visualize.clickBucket('Shape field'); log.debug('Aggregation = Terms'); diff --git a/test/functional/apps/visualize/_tag_cloud.js b/test/functional/apps/visualize/_tag_cloud.js index 4ed95214550c15..5b435ef29a2688 100644 --- a/test/functional/apps/visualize/_tag_cloud.js +++ b/test/functional/apps/visualize/_tag_cloud.js @@ -30,8 +30,6 @@ export default function ({ getService, getPageObjects }) { describe('tag cloud chart', function () { const vizName1 = 'Visualization tagCloud'; - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const termsField = 'machine.ram'; before(async function () { @@ -40,7 +38,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickTagCloud'); await PageObjects.visualize.clickTagCloud(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select Tags'); await PageObjects.visualize.clickBucket('Tags'); log.debug('Click aggregation Terms'); @@ -140,7 +138,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.common.navigateToApp('visualize'); await PageObjects.visualize.loadSavedVisualization(vizName1, { navigateToVisualize: false }); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.waitForVisualization(); }); diff --git a/test/functional/apps/visualize/_tile_map.js b/test/functional/apps/visualize/_tile_map.js index 0e580f6a7ab3fd..f25e7e649a4270 100644 --- a/test/functional/apps/visualize/_tile_map.js +++ b/test/functional/apps/visualize/_tile_map.js @@ -37,15 +37,12 @@ export default function ({ getService, getPageObjects }) { before(async function () { await browser.setWindowSize(1280, 1000); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); log.debug('clickTileMap'); await PageObjects.visualize.clickTileMap(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); //do not configure aggs }); @@ -62,15 +59,12 @@ export default function ({ getService, getPageObjects }) { before(async function () { await browser.setWindowSize(1280, 1000); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); log.debug('clickTileMap'); await PageObjects.visualize.clickTileMap(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Geo Coordinates'); await PageObjects.visualize.clickBucket('Geo coordinates'); log.debug('Click aggregation Geohash'); diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index d4896d0a0fd71d..dc4b9a786eaa46 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -121,8 +121,8 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { const value = await PageObjects.visualBuilder.getMetricValue(); expect(value).to.eql('156'); await PageObjects.visualBuilder.clickPanelOptions('metric'); - const fromTime = '2018-10-22 00:00:00.000'; - const toTime = '2018-10-28 23:59:59.999'; + const fromTime = 'Oct 22, 2018 @ 00:00:00.000'; + const toTime = 'Oct 28, 2018 @ 23:59:59.999'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.visualBuilder.setIndexPatternValue('kibana_sample_data_flights'); await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); diff --git a/test/functional/apps/visualize/_tsvb_markdown.ts b/test/functional/apps/visualize/_tsvb_markdown.ts index f7b8415583a396..b7307ac9c6cabc 100644 --- a/test/functional/apps/visualize/_tsvb_markdown.ts +++ b/test/functional/apps/visualize/_tsvb_markdown.ts @@ -43,7 +43,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { before(async () => { await visualBuilder.resetPage(); await visualBuilder.clickMarkdown(); - await timePicker.setAbsoluteRange('2015-09-22 06:00:00.000', '2015-09-22 11:00:00.000'); + await timePicker.setAbsoluteRange( + 'Sep 22, 2015 @ 06:00:00.000', + 'Sep 22, 2015 @ 11:00:00.000' + ); }); it('should render subtabs and table variables markdown components', async () => { diff --git a/test/functional/apps/visualize/_tsvb_table.ts b/test/functional/apps/visualize/_tsvb_table.ts index 0b3541d7989509..c096c28f7b8043 100644 --- a/test/functional/apps/visualize/_tsvb_table.ts +++ b/test/functional/apps/visualize/_tsvb_table.ts @@ -27,7 +27,7 @@ export default function({ getPageObjects }: FtrProviderContext) { describe('visual builder', function describeIndexTests() { describe('table', () => { beforeEach(async () => { - await visualBuilder.resetPage('2015-09-22 06:00:00.000', '2015-09-22 11:00:00.000'); + await visualBuilder.resetPage('Sep 22, 2015 @ 06:00:00.000', 'Sep 22, 2015 @ 11:00:00.000'); await visualBuilder.clickTable(); await visualBuilder.checkTableTabIsPresent(); diff --git a/test/functional/apps/visualize/_vega_chart.js b/test/functional/apps/visualize/_vega_chart.js index 186318ebe6325a..f4fb9f13d83bd2 100644 --- a/test/functional/apps/visualize/_vega_chart.js +++ b/test/functional/apps/visualize/_vega_chart.js @@ -25,9 +25,6 @@ export default function ({ getService, getPageObjects }) { const inspector = getService('inspector'); const log = getService('log'); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - describe('visualize app', () => { before(async () => { log.debug('navigateToApp visualize'); @@ -64,7 +61,7 @@ export default function ({ getService, getPageObjects }) { describe('with filters', () => { before(async () => { log.debug('setAbsoluteRange'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); afterEach(async () => { diff --git a/test/functional/apps/visualize/_vertical_bar_chart.js b/test/functional/apps/visualize/_vertical_bar_chart.js index 3a704ab0a20261..fb08cfa8982376 100644 --- a/test/functional/apps/visualize/_vertical_bar_chart.js +++ b/test/functional/apps/visualize/_vertical_bar_chart.js @@ -28,8 +28,6 @@ export default function ({ getService, getPageObjects }) { // FLAKY: https://github.com/elastic/kibana/issues/22322 describe('vertical bar chart', function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const vizName1 = 'Visualization VerticalBarChart'; const initBarChart = async () => { @@ -38,7 +36,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickVerticalBarChart'); await PageObjects.visualize.clickVerticalBarChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = X-Axis'); await PageObjects.visualize.clickBucket('X-axis'); log.debug('Aggregation = Date Histogram'); @@ -110,8 +108,8 @@ export default function ({ getService, getPageObjects }) { }); it('should have `drop partial buckets` option', async () => { - const fromTime = '2015-09-20 06:31:44.000'; - const toTime = '2015-09-22 18:31:44.000'; + const fromTime = 'Sep 20, 2015 @ 06:31:44.000'; + const toTime = 'Sep 22, 2015 @ 18:31:44.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); diff --git a/test/functional/apps/visualize/input_control_vis/input_control_options.js b/test/functional/apps/visualize/input_control_vis/input_control_options.js index 4088ab6193a59f..ef58f0da4c8f43 100644 --- a/test/functional/apps/visualize/input_control_vis/input_control_options.js +++ b/test/functional/apps/visualize/input_control_vis/input_control_options.js @@ -35,7 +35,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickInputControlVis(); // set time range to time with no documents - input controls do not use time filter be default - await PageObjects.timePicker.setAbsoluteRange('2017-01-01 00:00:00.000', '2017-01-02 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2017 @ 00:00:00.000', 'Jan 1, 2017 @ 00:00:00.000'); await PageObjects.visualize.clickVisEditorTab('controls'); await PageObjects.visualize.addInputControl(); await comboBox.set('indexPatternSelect-0', 'logstash- '); @@ -176,7 +176,7 @@ export default function ({ getService, getPageObjects }) { }); it('should re-create control when global time filter is updated', async () => { - await PageObjects.timePicker.setAbsoluteRange('2015-01-01 00:00:00.000', '2016-01-01 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2015 @ 00:00:00.000', 'Jan 1, 2016 @ 00:00:00.000'); // Expect control to have values for selected time filter const menu = await comboBox.getOptionsList('listControlSelect0'); diff --git a/test/functional/page_objects/dashboard_page.js b/test/functional/page_objects/dashboard_page.js index 24604227228354..49e6bd02d681fc 100644 --- a/test/functional/page_objects/dashboard_page.js +++ b/test/functional/page_objects/dashboard_page.js @@ -527,20 +527,18 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } async setTimepickerInHistoricalDataRange() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } async setTimepickerInDataRange() { - const fromTime = '2018-01-01 00:00:00.000'; - const toTime = '2018-04-13 00:00:00.000'; + const fromTime = 'Jan 1, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); } async setTimepickerInLogstashDataRange() { - const fromTime = '2018-04-09 00:00:00.000'; - const toTime = '2018-04-13 00:00:00.000'; + const fromTime = 'Apr 9, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); } diff --git a/test/functional/page_objects/time_picker.js b/test/functional/page_objects/time_picker.js index 2b4147908559ad..75628c9c452c73 100644 --- a/test/functional/page_objects/time_picker.js +++ b/test/functional/page_objects/time_picker.js @@ -36,8 +36,8 @@ export function TimePickerPageProvider({ getService, getPageObjects }) { formatDateToAbsoluteTimeString(date) { // toISOString returns dates in format 'YYYY-MM-DDTHH:mm:ss.sssZ' // Need to replace T with space and remove timezone - const dateString = date.toISOString().replace('T', ' '); - return dateString.substring(0, 23); + const DEFAULT_DATE_FORMAT = 'MMM D, YYYY @ HH:mm:ss.SSS'; + return moment(date).format(DEFAULT_DATE_FORMAT); } async getTimePickerPanel() { @@ -74,8 +74,8 @@ export function TimePickerPageProvider({ getService, getPageObjects }) { } /** - * @param {String} fromTime YYYY-MM-DD HH:mm:ss.SSS - * @param {String} fromTime YYYY-MM-DD HH:mm:ss.SSS + * @param {String} fromTime MMM D, YYYY @ HH:mm:ss.SSS + * @param {String} toTime MMM D, YYYY @ HH:mm:ss.SSS */ async setAbsoluteRange(fromTime, toTime) { log.debug(`Setting absolute range to ${fromTime} to ${toTime}`); @@ -112,6 +112,13 @@ export function TimePickerPageProvider({ getService, getPageObjects }) { await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); } + get defaultStartTime() { return 'Sep 19, 2015 @ 06:31:44.000'; } + get defaultEndTime() { return 'Sep 23, 2015 @ 18:31:44.000'; } + + async setDefaultAbsoluteRange() { + await this.setAbsoluteRange(this.defaultStartTime, this.defaultEndTime); + } + async isQuickSelectMenuOpen() { return await testSubjects.exists('superDatePickerQuickMenu'); } @@ -214,7 +221,7 @@ export function TimePickerPageProvider({ getService, getPageObjects }) { } async getTimeDurationInHours() { - const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS'; + const DEFAULT_DATE_FORMAT = 'MMM D, YYYY @ HH:mm:ss.SSS'; const { start, end } = await this.getTimeConfigAsAbsoluteTimes(); const startMoment = moment(start, DEFAULT_DATE_FORMAT); diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 4b65de57f12d81..97d57873503762 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -43,8 +43,8 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro class VisualBuilderPage { public async resetPage( - fromTime = '2015-09-19 06:31:44.000', - toTime = '2015-09-22 18:31:44.000' + fromTime = 'Sep 19, 2015 @ 06:31:44.000', + toTime = 'Sep 22, 2015 @ 18:31:44.000' ) { await PageObjects.common.navigateToUrl('visualize', 'create?type=metrics'); log.debug('Set absolute time range from "' + fromTime + '" to "' + toTime + '"'); diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json index da1bb597f57308..769acc52e207b6 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "react": "^16.8.0", "react-dom": "^16.8.0" } diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json index 4d0444265825a2..41e1e6baca0ecc 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "react": "^16.8.0" } } diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json index 9df9352f76fc27..a0b03e52640fce 100644 --- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json +++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "react": "^16.8.0" }, "scripts": { diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json index 054276b6209078..952d06c4873d4d 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "react": "^16.8.0" }, "scripts": { diff --git a/test/visual_regression/tests/discover/chart_visualization.js b/test/visual_regression/tests/discover/chart_visualization.js index 4e1d9bf643cf6d..540d95973b547f 100644 --- a/test/visual_regression/tests/discover/chart_visualization.js +++ b/test/visual_regression/tests/discover/chart_visualization.js @@ -33,8 +33,6 @@ export default function ({ getService, getPageObjects }) { }; describe('discover', function describeIndexTests() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('load kibana index with default index pattern'); @@ -45,7 +43,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace(defaultSettings); log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('query', function () { @@ -132,7 +130,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'America/Phoenix' }); await browser.refresh(); await PageObjects.header.awaitKibanaChrome(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); await PageObjects.discover.waitUntilSearchingHasFinished(); await visualTesting.snapshot({ diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap index c663c52d7d639e..cc16eef397d20c 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap @@ -122,7 +122,7 @@ exports[`ErrorGroupOverview -> List should render empty state 1`] = ` @@ -501,7 +501,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` diff --git a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot index 134a3da5ec6579..a42360d815176b 100644 --- a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot @@ -246,8 +246,9 @@ Array [ />
- - - +
@@ -277,8 +278,8 @@ Array [ best element ever

-
- +
@@ -599,8 +600,9 @@ Array [ />
- - - +
@@ -626,8 +628,8 @@ Array [

-
- +
@@ -949,8 +951,9 @@ Array [ />
- - - +
My Chart @@ -980,8 +983,8 @@ Array [

-
- +
@@ -1301,8 +1304,9 @@ Array [ />
- - - +
@@ -1332,8 +1336,8 @@ Array [

-
- +
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.examples.storyshot index 35135b5662b24a..f09921607ef467 100644 --- a/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.examples.storyshot @@ -8,11 +8,11 @@ exports[`Storyshots components/Elements/ElementCard with click handler 1`] = ` } } > -
- - +
- +
`; @@ -60,8 +66,9 @@ exports[`Storyshots components/Elements/ElementCard with image 1`] = ` >
- - - +
Element 1 @@ -87,8 +94,8 @@ exports[`Storyshots components/Elements/ElementCard with image 1`] = ` Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.

-
- +
@@ -103,11 +110,11 @@ exports[`Storyshots components/Elements/ElementCard with tags 1`] = ` } } > -
- - +
- - +
+
`; @@ -270,8 +283,9 @@ exports[`Storyshots components/Elements/ElementCard with title and description 1 >
- - - +
Element 1 @@ -301,8 +315,8 @@ exports[`Storyshots components/Elements/ElementCard with title and description 1 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.

-
- +
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot index c192e082523cb8..01774f849dfe79 100644 --- a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot @@ -14,11 +14,11 @@ exports[`Storyshots components/Elements/ElementGrid with controls 1`] = `
-
- - +
- +
@@ -115,11 +121,11 @@ exports[`Storyshots components/Elements/ElementGrid with controls 1`] = `
-
- - +
- +
@@ -216,11 +228,11 @@ exports[`Storyshots components/Elements/ElementGrid with controls 1`] = `
-
- - +
- +
@@ -332,11 +350,11 @@ exports[`Storyshots components/Elements/ElementGrid with controls and filter 1`]
-
- - +
- +
@@ -448,11 +472,11 @@ exports[`Storyshots components/Elements/ElementGrid with tags filter 1`] = `
-
- - +
- - +
+
@@ -522,11 +552,11 @@ exports[`Storyshots components/Elements/ElementGrid with text filter 1`] = `
-
- - +
- - +
+
@@ -596,11 +632,11 @@ exports[`Storyshots components/Elements/ElementGrid without controls 1`] = `
-
- - +
- - +
+
-
- - +
- - +
+
-
- - +
- - +
+
diff --git a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot index 9d1525788b3a66..e02d64e3e0647f 100644 --- a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot @@ -1,1601 +1,1599 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Storyshots components/KeyboardShortcutsDoc default 1`] = ` - +
-
-
+
+ } + tabIndex={1} + /> +
+
- -
-

- Keyboard shortcuts -

-
+ Keyboard shortcuts + +
+
-
-

- Element controls -

-
-
-
- Cut -
-
- - - - CTRL - - - - - - X - - - -
-
- Copy -
-
- - - - CTRL - - - - - - C - - - -
-
- Paste -
-
- - - - CTRL - - - - - - V - - - -
-
- Clone -
-
- - - - CTRL - - - - - - D - - - -
-
- Delete -
-
- - - - DEL - - - - - - or - - - - - - BACKSPACE - - - -
-
- Bring forward -
-
- - - - CTRL - - - - - - ↑ - - - -
-
- Bring to front -
-
- - - - CTRL - - - - - - SHIFT - - - - - - ↑ - - - -
-
- Send backward -
-
- - - - CTRL - - - - - - ↓ - - - -
-
- Send to back -
-
- - - - CTRL - - - - - - SHIFT - - - - - - ↓ - - - -
-
- Group -
-
- - - - G - - - -
-
- Ungroup -
-
- - - - U - - - -
-
- Shift up by 10px -
-
- - - - ↑ - - - -
-
- Shift down by 10px -
-
- - - - ↓ - - - -
-
- Shift left by 10px -
-
- - - - ← - - - -
-
- Shift right by 10px -
-
- - - - → - - - -
-
- Shift up by 1px -
-
- - - - SHIFT - - - - - - ↑ - - - -
-
- Shift down by 1px -
-
- - - - SHIFT - - - - - - ↓ - - - -
-
- Shift left by 1px -
-
- - - - SHIFT - - - - - - ← - - - -
-
- Shift right by 1px -
-
- - - - SHIFT - - - - - - → - - - -
-
-
-
+ Element controls + +
+
+
+ Cut +
+
+ + + + CTRL + + + + + + X + + + +
+
+ Copy +
+
+ + + + CTRL + + + + + + C + + + +
+
+ Paste +
+
+ + + + CTRL + + + + + + V + + + +
+
+ Clone +
+
+ + + + CTRL + + + + + + D + + + +
+
+ Delete +
+
+ + + + DEL + + + + + + or + + + + + + BACKSPACE + + + +
+
+ Bring forward +
+
+ + + + CTRL + + + + + + ↑ + + + +
+
+ Bring to front +
+
+ + + + CTRL + + + + + + SHIFT + + + + + + ↑ + + + +
+
+ Send backward +
+
+ + + + CTRL + + + + + + ↓ + + + +
+
+ Send to back +
+
+ + + + CTRL + + + + + + SHIFT + + + + + + ↓ + + + +
+
+ Group +
+
+ + + + G + + + +
+
+ Ungroup +
+
+ + + + U + + + +
+
+ Shift up by 10px +
+
+ + + + ↑ + + + +
+
+ Shift down by 10px +
+
+ + + + ↓ + + + +
+
+ Shift left by 10px +
+
+ + + + ← + + + +
+
+ Shift right by 10px +
+
+ + + + → + + + +
+
+ Shift up by 1px +
+
+ + + + SHIFT + + + + + + ↑ + + + +
+
+ Shift down by 1px +
+
+ + + + SHIFT + + + + + + ↓ + + + +
+
+ Shift left by 1px +
+
+ + + + SHIFT + + + + + + ← + + + +
+
+ Shift right by 1px +
+
+ + + + SHIFT + + + + + + → + + + +
+
+
+
+

+ Expression controls +

+
+
-

- Expression controls -

-
-
-
- Run whole expression -
-
- - - - CTRL - - - - - - ENTER - - - -
-
-
-
+
+ Run whole expression +
+
+ + + + CTRL + + + + + + ENTER + + + +
+
+
+
+

+ Editor controls +

+
+
-

- Editor controls -

-
-
-
- Select multiple elements -
-
- - - - SHIFT - - - - - - CLICK - - - -
-
- Resize from center -
-
- - - - ALT - - - - - - DRAG - - - -
-
- Move, resize, and rotate without snapping -
-
- - - - CTRL - - - - - - DRAG - - - -
-
- Select element below -
-
- - - - CTRL - - - - - - CLICK - - - -
-
- Undo last action -
-
- - - - CTRL - - - - - - Z - - - -
-
- Redo last action -
-
- - - - CTRL - - - - - - SHIFT - - - - - - Z - - - -
-
- Go to previous page -
-
- - - - ALT - - - - - - [ - - - -
-
- Go to next page -
-
- - - - ALT - - - - - - ] - - - -
-
- Toggle edit mode -
-
- - - - ALT - - - - - - E - - - -
-
- Show grid -
-
- - - - ALT - - - - - - G - - - -
-
- Refresh workpad -
-
- - - - ALT - - - - - - R - - - -
-
- Zoom in -
-
- - - - CTRL - - - - - - ALT - - - - - - + - - - -
-
- Zoom out -
-
- - - - CTRL - - - - - - ALT - - - - - - - - - - -
-
- Reset zoom to 100% -
-
- - - - CTRL - - - - - - ALT - - - - - - [ - - - -
-
- Enter presentation mode -
-
- - - - ALT - - - - - - F - - - - - - or - - - - - - ALT - - - - - - P - - - -
-
-
-
+
+ Select multiple elements +
+
+ + + + SHIFT + + + + + + CLICK + + + +
+
+ Resize from center +
+
+ + + + ALT + + + + + + DRAG + + + +
+
+ Move, resize, and rotate without snapping +
+
+ + + + CTRL + + + + + + DRAG + + + +
+
+ Select element below +
+
+ + + + CTRL + + + + + + CLICK + + + +
+
+ Undo last action +
+
+ + + + CTRL + + + + + + Z + + + +
+
+ Redo last action +
+
+ + + + CTRL + + + + + + SHIFT + + + + + + Z + + + +
+
+ Go to previous page +
+
+ + + + ALT + + + + + + [ + + + +
+
+ Go to next page +
+
+ + + + ALT + + + + + + ] + + + +
+
+ Toggle edit mode +
+
+ + + + ALT + + + + + + E + + + +
+
+ Show grid +
+
+ + + + ALT + + + + + + G + + + +
+
+ Refresh workpad +
+
+ + + + ALT + + + + + + R + + + +
+
+ Zoom in +
+
+ + + + CTRL + + + + + + ALT + + + + + + + + + + +
+
+ Zoom out +
+
+ + + + CTRL + + + + + + ALT + + + + + + - + + + +
+
+ Reset zoom to 100% +
+
+ + + + CTRL + + + + + + ALT + + + + + + [ + + + +
+
+ Enter presentation mode +
+
+ + + + ALT + + + + + + F + + + + + + or + + + + + + ALT + + + + + + P + + + +
+
+
+
+

+ Presentation controls +

+
+
-

- Presentation controls -

-
-
-
- Enter presentation mode -
-
- - - - ALT - - - - - - F - - - - - - or - - - - - - ALT - - - - - - P - - - -
-
- Exit presentation mode -
-
- - - - ESC - - - -
-
- Go to previous page -
-
- - - - ALT - - - - - - [ - - - - - - or - - - - - - BACKSPACE - - - - - - or - - - - - - ← - - - -
-
- Go to next page -
-
- - - - ALT - - - - - - ] - - - - - - or - - - - - - SPACE - - - - - - or - - - - - - → - - - -
-
- Refresh workpad -
-
- - - - ALT - - - - - - R - - - -
-
- Toggle page cycling -
-
- - - - P - - - -
-
-
-
+
+ Enter presentation mode +
+
+ + + + ALT + + + + + + F + + + + + + or + + + + + + ALT + + + + + + P + + + +
+
+ Exit presentation mode +
+
+ + + + ESC + + + +
+
+ Go to previous page +
+
+ + + + ALT + + + + + + [ + + + + + + or + + + + + + BACKSPACE + + + + + + or + + + + + + ← + + + +
+
+ Go to next page +
+
+ + + + ALT + + + + + + ] + + + + + + or + + + + + + SPACE + + + + + + or + + + + + + → + + + +
+
+ Refresh workpad +
+
+ + + + ALT + + + + + + R + + + +
+
+ Toggle page cycling +
+
+ + + + P + + + +
+
+
-
- +
+
`; diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot index 1e66e19b3c0e18..e9f496bfe6358f 100644 --- a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot @@ -27,7 +27,7 @@ exports[`Storyshots shareables/Footer/Settings/AutoplaySettings component: off, >
`; -exports[` can navigate Toolbar Settings, closes when activated 3`] = `"
Settings

Hide Toolbar

Hide the toolbar when the mouse is not within the Canvas?
"`; +exports[` can navigate Toolbar Settings, closes when activated 3`] = `"
Settings

Hide Toolbar

Hide the toolbar when the mouse is not within the Canvas?
"`; diff --git a/x-pack/legacy/plugins/infra/types/eui.d.ts b/x-pack/legacy/plugins/infra/types/eui.d.ts index ef58bfcb2fa04e..e4e0e70ce630b1 100644 --- a/x-pack/legacy/plugins/infra/types/eui.d.ts +++ b/x-pack/legacy/plugins/infra/types/eui.d.ts @@ -53,10 +53,6 @@ declare module '@elastic/eui' { sizes: EuiSizesResponsive[]; }; - export const EuiHideFor: React.SFC; - - export const EuiShowFor: React.SFC; - type EuiInMemoryTableProps = CommonProps & { items?: any; columns?: any; diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap index d5be772af9441b..03421e66c77f59 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap +++ b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AddLicense component when license is active should display correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

Update license
"`; +exports[`AddLicense component when license is active should display correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

"`; -exports[`AddLicense component when license is expired should display with correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

Update license
"`; +exports[`AddLicense component when license is expired should display with correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

"`; diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap index 8d91ddcc563df0..8670b2c378dca1 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap +++ b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`RequestTrialExtension component should display when license is active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

Extend trial
"`; +exports[`RequestTrialExtension component should display when license is active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

"`; -exports[`RequestTrialExtension component should display when license is not active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

Extend trial
"`; +exports[`RequestTrialExtension component should display when license is not active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

"`; -exports[`RequestTrialExtension component should display when platinum license is not active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

Extend trial
"`; +exports[`RequestTrialExtension component should display when platinum license is not active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

"`; diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap index 3b3cf35dcfd913..cb2a41dadbe9e1 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap +++ b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`RevertToBasic component should display when license is about to expire 1`] = `"
Revert to Basic license

You’ll revert to our free features and lose access to machine learning, advanced security, and other Platinum features.

"`; +exports[`RevertToBasic component should display when license is about to expire 1`] = `"
Revert to Basic license

You’ll revert to our free features and lose access to machine learning, advanced security, and other Platinum features.

"`; -exports[`RevertToBasic component should display when license is expired 1`] = `"
Revert to Basic license

You’ll revert to our free features and lose access to machine learning, advanced security, and other Platinum features.

"`; +exports[`RevertToBasic component should display when license is expired 1`] = `"
Revert to Basic license

You’ll revert to our free features and lose access to machine learning, advanced security, and other Platinum features.

"`; -exports[`RevertToBasic component should display when trial is active 1`] = `"
Revert to Basic license

You’ll revert to our free features and lose access to machine learning, advanced security, and other Platinum features.

"`; +exports[`RevertToBasic component should display when trial is active 1`] = `"
Revert to Basic license

You’ll revert to our free features and lose access to machine learning, advanced security, and other Platinum features.

"`; diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap index 9812152dc6363d..df82a820e95136 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap +++ b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`StartTrial component when trial is allowed display for basic license 1`] = `"
Start a 30-day trial

Experience what machine learning, advanced security, and all our other Platinum features have to offer.

"`; +exports[`StartTrial component when trial is allowed display for basic license 1`] = `"
Start a 30-day trial

Experience what machine learning, advanced security, and all our other Platinum features have to offer.

"`; -exports[`StartTrial component when trial is allowed should display for expired platinum license 1`] = `"
Start a 30-day trial

Experience what machine learning, advanced security, and all our other Platinum features have to offer.

"`; +exports[`StartTrial component when trial is allowed should display for expired platinum license 1`] = `"
Start a 30-day trial

Experience what machine learning, advanced security, and all our other Platinum features have to offer.

"`; -exports[`StartTrial component when trial is allowed should display for gold license 1`] = `"
Start a 30-day trial

Experience what machine learning, advanced security, and all our other Platinum features have to offer.

"`; +exports[`StartTrial component when trial is allowed should display for gold license 1`] = `"
Start a 30-day trial

Experience what machine learning, advanced security, and all our other Platinum features have to offer.

"`; diff --git a/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/__snapshots__/top_nav.test.tsx.snap b/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/__snapshots__/top_nav.test.tsx.snap index b898558b20738e..f9df085d2cbe7a 100644 --- a/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/__snapshots__/top_nav.test.tsx.snap +++ b/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/__snapshots__/top_nav.test.tsx.snap @@ -69,6 +69,7 @@ exports[`Navigation Menu: Minimal initialization. 1`] = ` refreshInterval={0} showUpdateButton={true} start="Thu Aug 29 2019 02:04:19 GMT+0200" + timeFormat="HH:mm" />
diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap b/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap index cf8cf37d2e4ee6..bf309c65556a81 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap +++ b/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap @@ -249,7 +249,7 @@ Array [ > +
+

+ Unable to fetch report info +

+
+
+
+
+ Could not fetch the job info +
+
+
+
+
} - tabIndex={1} - /> -
- + +
+ - - -
- } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - /> - -
- - - - + + + + + +
-
- -

- Unable to fetch report info -

-
-
- - + Unable to fetch report info + + +
+
+ +
-
- -
- Could not fetch the job info -
-
-
+ +
+ Could not fetch the job info +
+
- -
+
+
-
+
- -
- - - - + } + tabIndex={0} + /> + +
+ + + ,
- - + + + } /> - - - } - /> - - + + - - -
- -
+
-
+
+ + } - tabIndex={1} - /> -
- + +
+ - - - } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - /> - -
- - - - + + + + + +
-
- -

- Job Info -

-
-
- - + Job Info + + +
+
+ +
-
- -
- -
+ +
+
- -
+
+
-
+
- -
- - - - + } + tabIndex={0} + /> + +
+ + + ,
{ const clickHandler = jest.fn(); const wrapper = mount(); - wrapper.simulate('click'); + wrapper.find('button').simulate('click'); expect(clickHandler).toHaveBeenCalledTimes(1); }); diff --git a/x-pack/package.json b/x-pack/package.json index ff8bff0fec6346..628e77a9fd544e 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -178,7 +178,7 @@ "@babel/runtime": "^7.5.5", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "@elastic/filesaver": "1.1.2", "@elastic/javascript-typescript-langserver": "^0.3.3", "@elastic/lsp-extension": "^0.1.2", diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts index 67bc8bd38ff1c9..7cbab3cdcf4f2e 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts @@ -25,9 +25,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const savedQueryManagementComponent = getService('savedQueryManagementComponent'); async function setDiscoverTimeRange() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } describe('security', () => { diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts index 243d5a0b6b6d0d..4c2a8b4bed3061 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts @@ -21,9 +21,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const appsMenu = getService('appsMenu'); async function setDiscoverTimeRange() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } describe('spaces', () => { diff --git a/x-pack/test/functional/apps/monitoring/beats/beat_detail.js b/x-pack/test/functional/apps/monitoring/beats/beat_detail.js index d352579e011604..d17e233a484e88 100644 --- a/x-pack/test/functional/apps/monitoring/beats/beat_detail.js +++ b/x-pack/test/functional/apps/monitoring/beats/beat_detail.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/beats', { - from: '2017-12-19 17:14:09.000', - to: '2017-12-19 18:15:09.000', + from: 'Dec 19, 2017 @ 17:14:09.000', + to: 'Dec 19, 2017 @ 18:15:09.000', }); // go to beats detail diff --git a/x-pack/test/functional/apps/monitoring/beats/cluster.js b/x-pack/test/functional/apps/monitoring/beats/cluster.js index 8ee93066254d58..9a2532adfbae88 100644 --- a/x-pack/test/functional/apps/monitoring/beats/cluster.js +++ b/x-pack/test/functional/apps/monitoring/beats/cluster.js @@ -15,8 +15,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/beats', { - from: '2017-12-19 17:14:09.000', - to: '2017-12-19 18:15:09.000', + from: 'Dec 19, 2017 @ 17:14:09.000', + to: 'Dec 19, 2017 @ 18:15:09.000', }); }); diff --git a/x-pack/test/functional/apps/monitoring/beats/listing.js b/x-pack/test/functional/apps/monitoring/beats/listing.js index 700b5d593ecb8e..7a27a7b5f219d3 100644 --- a/x-pack/test/functional/apps/monitoring/beats/listing.js +++ b/x-pack/test/functional/apps/monitoring/beats/listing.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/beats', { - from: '2017-12-19 17:14:09.000', - to: '2017-12-19 18:15:09.000', + from: 'Dec 19, 2017 @ 17:14:09.000', + to: 'Dec 19, 2017 @ 18:15:09.000', }); // go to beats listing diff --git a/x-pack/test/functional/apps/monitoring/beats/overview.js b/x-pack/test/functional/apps/monitoring/beats/overview.js index 1c8b70a4628433..16c198be0432f1 100644 --- a/x-pack/test/functional/apps/monitoring/beats/overview.js +++ b/x-pack/test/functional/apps/monitoring/beats/overview.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/beats', { - from: '2017-12-19 17:14:09.000', - to: '2017-12-19 18:15:09.000', + from: 'Dec 19, 2017 @ 17:14:09.000', + to: 'Dec 19, 2017 @ 18:15:09.000', }); // go to beats overview diff --git a/x-pack/test/functional/apps/monitoring/cluster/alerts.js b/x-pack/test/functional/apps/monitoring/cluster/alerts.js index 1e61518947d2ea..2a0dbec6f3b9ea 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/alerts.js +++ b/x-pack/test/functional/apps/monitoring/cluster/alerts.js @@ -23,8 +23,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:23:47.528', - to: '2017-08-29 17:25:50.701', + from: 'Aug 29, 2017 @ 17:23:47.528', + to: 'Aug 29, 2017 @ 17:25:50.701', }); // ensure cluster alerts are shown on overview @@ -51,8 +51,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum--with-10-alerts', { - from: '2017-08-29 17:23:47.528', - to: '2017-08-29 17:25:50.701', + from: 'Aug 29, 2017 @ 17:23:47.528', + to: 'Aug 29, 2017 @ 17:25:50.701', }); // ensure cluster alerts are shown on overview @@ -166,8 +166,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:23:47.528', - to: '2017-08-29 17:25:50.701', + from: 'Aug 29, 2017 @ 17:23:47.528', + to: 'Aug 29, 2017 @ 17:25:50.701', }); // ensure cluster alerts are shown on overview diff --git a/x-pack/test/functional/apps/monitoring/cluster/list.js b/x-pack/test/functional/apps/monitoring/cluster/list.js index 70e89689a89dbc..399b392cad7972 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/list.js +++ b/x-pack/test/functional/apps/monitoring/cluster/list.js @@ -21,8 +21,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/multicluster', { - from: '2017-08-15 21:00:00.000', - to: '2017-08-16 00:00:00.000', + from: 'Aug 15, 2017 @ 21:00:00.000', + to: 'Aug 16, 2017 @ 00:00:00.000', }); await clusterList.assertDefaults(); @@ -76,8 +76,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/multi-basic', { - from: '2017-09-07 20:12:04.011', - to: '2017-09-07 20:18:55.733', + from: 'Sep 7, 2017 @ 20:12:04.011', + to: 'Sep 7, 2017 @ 20:18:55.733', }); await clusterList.assertDefaults(); diff --git a/x-pack/test/functional/apps/monitoring/cluster/overview.js b/x-pack/test/functional/apps/monitoring/cluster/overview.js index 8242150e404eb6..3396426e953808 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/overview.js +++ b/x-pack/test/functional/apps/monitoring/cluster/overview.js @@ -16,8 +16,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-green-gold', { - from: '2017-08-23 21:29:35.267', - to: '2017-08-23 21:47:25.556', + from: 'Aug 23, 2017 @ 21:29:35.267', + to: 'Aug 23, 2017 @ 21:47:25.556', }); }); @@ -71,8 +71,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:23:47.528', - to: '2017-08-29 17:25:50.701', + from: 'Aug 29, 2017 @ 17:23:47.528', + to: 'Aug 29, 2017 @ 17:25:50.701', }); }); @@ -121,8 +121,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-basic', { - from: '2017-08-29 17:55:43.879', - to: '2017-08-29 18:01:34.958', + from: 'Aug 29, 2017 @ 17:55:43.879', + to: 'Aug 29, 2017 @ 18:01:34.958', }); }); diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js b/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js index c3fe5f9273a897..7109f9363e1b7e 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js @@ -25,8 +25,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:31:48.354', - to: '2017-10-05 20:35:12.176' + from: 'Oct 5, 2017 @ 20:31:48.354', + to: 'Oct 5, 2017 @ 20:35:12.176' }); // go to indices listing @@ -83,8 +83,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-red-platinum', { - from: '2017-10-06 19:53:06.748', - to: '2017-10-06 20:15:30.212' + from: 'Oct 6, 2017 @ 19:53:06.748', + to: 'Oct 6, 2017 @ 20:15:30.212' }); // go to indices listing diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js b/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js index 1ed7c15a9ecf1f..6500f373807a43 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-red-platinum', { - from: '2017-10-06 19:53:06.748', - to: '2017-10-06 20:15:30.212', + from: 'Oct 6, 2017 @ 19:53:06.748', + to: 'Oct 6, 2017 @ 20:15:30.212', }); // go to indices listing diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js b/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js index 99dce6c1b89b6f..6521753de506a1 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js @@ -19,8 +19,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:31:48.354', - to: '2017-10-05 20:35:12.176' + from: 'Oct 5, 2017 @ 20:31:48.354', + to: 'Oct 5, 2017 @ 20:35:12.176' }); // go to nodes listing @@ -74,8 +74,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-red-platinum', { - from: '2017-10-06 19:53:06.748', - to: '2017-10-06 20:15:30.212' + from: 'Oct 6, 2017 @ 19:53:06.748', + to: 'Oct 6, 2017 @ 20:15:30.212' }); // go to nodes listing diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js index 7ad09e034e13b9..94ad5e493d73e1 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js @@ -21,8 +21,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:28:28.475', - to: '2017-10-05 20:34:38.341', + from: 'Oct 5, 2017 @ 20:28:28.475', + to: 'Oct 5, 2017 @ 20:34:38.341', }); // go to nodes listing @@ -196,8 +196,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:31:48.354', - to: '2017-10-05 20:35:12.176', + from: 'Oct 5, 2017 @ 20:31:48.354', + to: 'Oct 5, 2017 @ 20:35:12.176', }); // go to nodes listing diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js b/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js index a0e91e2336e082..b5429cdc891f94 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:31:48.354', - to: '2017-10-05 20:35:12.176' + from: 'Oct 5, 2017 @ 20:31:48.354', + to: 'Oct 5, 2017 @ 20:35:12.176' }); // go to overview diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js b/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js index ab02eead163338..4a40d686af4968 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js @@ -21,8 +21,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 19:34:48.000', - to: '2017-10-05 20:35:12.000', + from: 'Oct 5, 2017 @ 19:34:48.000', + to: 'Oct 5, 2017 @ 20:35:12.000', }); }); diff --git a/x-pack/test/functional/apps/monitoring/kibana/instance.js b/x-pack/test/functional/apps/monitoring/kibana/instance.js index 33448fc4b206a5..0d4e06fb2b98f1 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/instance.js +++ b/x-pack/test/functional/apps/monitoring/kibana/instance.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:24:14.254', - to: '2017-08-29 17:25:44.142', + from: 'Aug 29, 2017 @ 17:24:14.254', + to: 'Aug 29, 2017 @ 17:25:44.142', }); // go to kibana instance diff --git a/x-pack/test/functional/apps/monitoring/kibana/instances.js b/x-pack/test/functional/apps/monitoring/kibana/instances.js index 28bf108d59f242..8f72806eee4419 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/instances.js +++ b/x-pack/test/functional/apps/monitoring/kibana/instances.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:24:14.254', - to: '2017-08-29 17:25:44.142', + from: 'Aug 29, 2017 @ 17:24:14.254', + to: 'Aug 29, 2017 @ 17:25:44.142', }); // go to kibana instances diff --git a/x-pack/test/functional/apps/monitoring/kibana/overview.js b/x-pack/test/functional/apps/monitoring/kibana/overview.js index 7282e48fc8a919..c5da75e37a77f6 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/overview.js +++ b/x-pack/test/functional/apps/monitoring/kibana/overview.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:24:14.254', - to: '2017-08-29 17:25:44.142', + from: 'Aug 29, 2017 @ 17:24:14.254', + to: 'Aug 29, 2017 @ 17:25:44.142', }); // go to kibana overview diff --git a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js index fb9fcf8bab8bb4..f4d2a5a4a20a5e 100644 --- a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js +++ b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js @@ -19,8 +19,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/logstash-pipelines', { - from: '2018-01-22 09:10:00.000', - to: '2018-01-22 09:41:00.000', + from: 'Jan 22, 2018 @ 09:10:00.000', + to: 'Jan 22, 2018 @ 09:41:00.000', }); // go to pipelines listing diff --git a/x-pack/test/functional/apps/monitoring/time_filter.js b/x-pack/test/functional/apps/monitoring/time_filter.js index 0afcada14be5fb..ae5b11e8e0b325 100644 --- a/x-pack/test/functional/apps/monitoring/time_filter.js +++ b/x-pack/test/functional/apps/monitoring/time_filter.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/multicluster', { - from: '2017-08-15 21:00:00.000', - to: '2017-08-16 00:00:00.000', + from: 'Aug 15, 2017 @ 21:00:00.000', + to: 'Aug 16, 2017 @ 00:00:00.000', }); await clusterList.assertDefaults(); }); @@ -35,7 +35,7 @@ export default function ({ getService, getPageObjects }) { }); it('should send another request when changing the time picker', async () => { - await PageObjects.timePicker.setAbsoluteRange('2016-08-15 21:00:00.000', '2016-08-16 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Aug 15, 2016 @ 21:00:00.000', 'Aug 16, 2016 @ 00:00:00.000'); await clusterList.assertNoData(); }); }); diff --git a/x-pack/test/functional/apps/security/rbac_phase1.js b/x-pack/test/functional/apps/security/rbac_phase1.js index 9b8be614c9f5bf..3f9f2f6bdbe87d 100644 --- a/x-pack/test/functional/apps/security/rbac_phase1.js +++ b/x-pack/test/functional/apps/security/rbac_phase1.js @@ -85,8 +85,6 @@ export default function ({ getService, getPageObjects }) { // this is to acertain that all role assigned to the user can perform actions like creating a Visualization it('rbac all role can save a visualization', async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const vizName1 = 'Visualization VerticalBarChart'; log.debug('log in as kibanauser with rbac_all role'); @@ -96,8 +94,10 @@ export default function ({ getService, getPageObjects }) { log.debug('clickVerticalBarChart'); await PageObjects.visualize.clickVerticalBarChart(); await PageObjects.visualize.clickNewSearch(); - log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + log.debug('Set absolute time range from \"' + + PageObjects.timePicker.defaultStartTime + '\" to \"' + + PageObjects.timePicker.defaultEndTime + '\"'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.waitForVisualization(); await PageObjects.visualize.saveVisualizationExpectSuccess(vizName1); await PageObjects.security.logout(); diff --git a/x-pack/test/functional/apps/uptime/monitor.ts b/x-pack/test/functional/apps/uptime/monitor.ts index ecbe893b1f2c06..034ccad4815a1f 100644 --- a/x-pack/test/functional/apps/uptime/monitor.ts +++ b/x-pack/test/functional/apps/uptime/monitor.ts @@ -19,8 +19,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { after(async () => await esArchiver.unload(archive)); it('loads and displays uptime data based on date range', async () => { await pageObjects.uptime.loadDataAndGoToMonitorPage( - '2019-09-10 12:40:08.078', - '2019-09-11 19:40:08.078', + 'Sep 10, 2019 @ 12:40:08.078', + 'Sep 11, 2019 @ 19:40:08.078', '0000-intermittent', '0000-intermittent' ); diff --git a/x-pack/test/functional/apps/uptime/overview.ts b/x-pack/test/functional/apps/uptime/overview.ts index cdb904537a0f25..9a337c86185fe0 100644 --- a/x-pack/test/functional/apps/uptime/overview.ts +++ b/x-pack/test/functional/apps/uptime/overview.ts @@ -12,8 +12,8 @@ export default ({ getPageObjects }: FtrProviderContext) => { const pageObjects = getPageObjects(['uptime']); describe('overview page', function() { - const DEFAULT_DATE_START = '2019-09-10 12:40:08.078'; - const DEFAULT_DATE_END = '2019-09-11 19:40:08.078'; + const DEFAULT_DATE_START = 'Sep 10, 2019 @ 12:40:08.078'; + const DEFAULT_DATE_END = 'Sep 11, 2019 @ 19:40:08.078'; it('loads and displays uptime data based on date range', async () => { await pageObjects.uptime.goToUptimeOverviewAndLoadData( DEFAULT_DATE_START, diff --git a/x-pack/test/functional/apps/visualize/hybrid_visualization.ts b/x-pack/test/functional/apps/visualize/hybrid_visualization.ts index dacd0b75b126c3..03b6ed8e8e7c54 100644 --- a/x-pack/test/functional/apps/visualize/hybrid_visualization.ts +++ b/x-pack/test/functional/apps/visualize/hybrid_visualization.ts @@ -75,8 +75,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { ['2019-08-22 00:00', 'php', '11'], ['2019-08-22 16:00', 'jpg', '3'], ]; - const fromTime = '2019-08-19 01:55:07.240'; - const toTime = '2019-08-22 23:09:36.205'; + const fromTime = 'Aug 19, 2019 @ 01:55:07.240'; + const toTime = 'Aug 22, 2019 @ 23:09:36.205'; await PageObjects.common.navigateToApp('visualize'); await PageObjects.visualize.clickVisualizationByName('hybrid_histogram_line_chart'); diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 8153a8713ca2f3..480814cb027817 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -46,7 +46,9 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont * Move the date filter to the specified time range, defaults to * a range that has data in our dataset. */ - goToTimeRange(fromTime = '2015-09-19 06:31:44.000', toTime = '2015-09-23 18:31:44.000') { + goToTimeRange(fromTime?: string, toTime?: string) { + fromTime = fromTime || PageObjects.timePicker.defaultStartTime; + toTime = toTime || PageObjects.timePicker.defaultEndTime; return PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); }, diff --git a/x-pack/test/functional/page_objects/reporting_page.js b/x-pack/test/functional/page_objects/reporting_page.js index 30de10c400c888..0ba0325ad56020 100644 --- a/x-pack/test/functional/page_objects/reporting_page.js +++ b/x-pack/test/functional/page_objects/reporting_page.js @@ -165,15 +165,13 @@ export function ReportingPageProvider({ getService, getPageObjects }) { async setTimepickerInDataRange() { log.debug('Reporting:setTimepickerInDataRange'); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } async setTimepickerInNoDataRange() { log.debug('Reporting:setTimepickerInNoDataRange'); - const fromTime = '1999-09-19 06:31:44.000'; - const toTime = '1999-09-23 18:31:44.000'; + const fromTime = 'Sep 19, 1999 @ 06:31:44.000'; + const toTime = 'Sep 23, 1999 @ 18:31:44.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); } } diff --git a/yarn.lock b/yarn.lock index 71c09a6ed4b0f3..85405acbcf7a0f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -990,7 +990,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.4.4": +"@babel/runtime@^7.4.4", "@babel/runtime@^7.6.3": version "7.7.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.2.tgz#111a78002a5c25fc8e3361bedc9529c696b85a6a" integrity sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw== @@ -1173,10 +1173,10 @@ tabbable "^1.1.0" uuid "^3.1.0" -"@elastic/eui@14.9.0": - version "14.9.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-14.9.0.tgz#934ab8d51c56671635dc17ac20ec325f43ceda75" - integrity sha512-0ZztvfRO3SNgHtS8a+4i6CSG3Yc+C0Kodzc7obY5wkOzissrnbwLZdU79hU/H6DHYCt/zYDdGcrDp6BeD67RtQ== +"@elastic/eui@16.0.0": + version "16.0.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-16.0.0.tgz#511898bfbeba5ffea6ac96c077d1184d657a451d" + integrity sha512-i9t13PzrsfBUolMZ6n2X9aAYJ/wUI2NJduCQlDU4zrXfFrM1LFJ5/KSCcpgzI8VNDakeA3PTml+oqD7J0qGA3g== dependencies: "@types/lodash" "^4.14.116" "@types/numeral" "^0.0.25" @@ -1188,12 +1188,12 @@ lodash "^4.17.11" numeral "^2.0.6" prop-types "^15.6.0" - react-ace "^5.5.0" + react-ace "^7.0.5" react-beautiful-dnd "^10.1.0" react-focus-lock "^1.17.7" - react-input-autosize "^2.2.1" + react-input-autosize "^2.2.2" react-is "~16.3.0" - react-virtualized "^9.18.5" + react-virtualized "^9.21.2" resize-observer-polyfill "^1.5.0" tabbable "^3.0.0" uuid "^3.1.0" @@ -6754,7 +6754,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace@0.11.1, brace@^0.11.0: +brace@0.11.1, brace@^0.11.0, brace@^0.11.1: version "0.11.1" resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58" integrity sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg= @@ -8036,6 +8036,11 @@ cloneable-readable@^1.0.0: process-nextick-args "^2.0.0" readable-stream "^2.3.5" +clsx@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec" + integrity sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg== + cmd-shim@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.1.0.tgz#e59a08d4248dda3bb502044083a4db4ac890579a" @@ -9173,6 +9178,11 @@ csstype@^2.5.7: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.3.tgz#b701e5968245bf9b08d54ac83d00b624e622a9fa" integrity sha512-rINUZXOkcBmoHWEyu7JdHu5JMzkGRoMX4ov9830WNgxf5UYxcBUO0QTKAqeJ5EZfSdlrcJYkC8WwfVW7JYi4yg== +csstype@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" + integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ== + cuint@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" @@ -10134,6 +10144,11 @@ diagnostics@^1.1.1: enabled "1.0.x" kuler "1.0.x" +diff-match-patch@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1" + integrity sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg== + diff-sequences@^24.0.0: version "24.0.0" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.0.0.tgz#cdf8e27ed20d8b8d3caccb4e0c0d8fe31a173013" @@ -10261,6 +10276,14 @@ dom-helpers@^3.3.1: dependencies: "@babel/runtime" "^7.1.2" +dom-helpers@^5.0.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.3.tgz#7233248eb3a2d1f74aafca31e52c5299cc8ce821" + integrity sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw== + dependencies: + "@babel/runtime" "^7.6.3" + csstype "^2.6.7" + dom-serialize@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" @@ -22647,6 +22670,17 @@ react-ace@^5.9.0: lodash.isequal "^4.1.1" prop-types "^15.5.8" +react-ace@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-7.0.5.tgz#798299fd52ddf3a3dcc92afc5865538463544f01" + integrity sha512-3iI+Rg2bZXCn9K984ll2OF4u9SGcJH96Q1KsUgs9v4M2WePS4YeEHfW2nrxuqJrAkE5kZbxaCE79k6kqK0YBjg== + dependencies: + brace "^0.11.1" + diff-match-patch "^1.0.4" + lodash.get "^4.4.2" + lodash.isequal "^4.5.0" + prop-types "^15.7.2" + react-addons-create-fragment@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/react-addons-create-fragment/-/react-addons-create-fragment-15.6.2.tgz#a394de7c2c7becd6b5475ba1b97ac472ce7c74f8" @@ -23377,6 +23411,18 @@ react-virtualized@^9.18.5: prop-types "^15.6.0" react-lifecycles-compat "^3.0.4" +react-virtualized@^9.21.2: + version "9.21.2" + resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.2.tgz#02e6df65c1e020c8dbf574ec4ce971652afca84e" + integrity sha512-oX7I7KYiUM7lVXQzmhtF4Xg/4UA5duSA+/ZcAvdWlTLFCoFYq1SbauJT5gZK9cZS/wdYR6TPGpX/dqzvTqQeBA== + dependencies: + babel-runtime "^6.26.0" + clsx "^1.0.1" + dom-helpers "^5.0.0" + loose-envify "^1.3.0" + prop-types "^15.6.0" + react-lifecycles-compat "^3.0.4" + react-vis@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/react-vis/-/react-vis-1.8.2.tgz#0e0aebc427e50856a01b666569ffad0411ef050f" From 1dc08d4738af808cef10f632259b5f2dcd7d1710 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Wed, 20 Nov 2019 18:51:39 -0600 Subject: [PATCH 27/29] Fix wrong path in brew doc (#50659) (#51248) * Fix wrong path in brew doc * Update brew.asciidoc --- docs/setup/install/brew.asciidoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/setup/install/brew.asciidoc b/docs/setup/install/brew.asciidoc index ad531a83d3690d..3fe104bd047941 100644 --- a/docs/setup/install/brew.asciidoc +++ b/docs/setup/install/brew.asciidoc @@ -32,13 +32,13 @@ and data directory are stored in the following locations. | Type | Description | Default Location | Setting | home | Kibana home directory or `$KIBANA_HOME` - | /usr/local/var/homebrew/linked/kibana + | /usr/local/var/homebrew/linked/kibana-full d| | bin | Binary scripts including `kibana` to start a node and `kibana-plugin` to install plugins - | /usr/local/var/homebrew/linked/kibana/bin + | /usr/local/var/homebrew/linked/kibana-full/bin d| | conf @@ -59,7 +59,7 @@ and data directory are stored in the following locations. | plugins | Plugin files location. Each plugin will be contained in a subdirectory. - | /usr/local/var/homebrew/linked/kibana/plugins + | /usr/local/var/homebrew/linked/kibana-full/plugins d| |======================================================================= From db401e40a5de51162b79ab2886b6882c3577bb1f Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 20 Nov 2019 19:11:53 -0700 Subject: [PATCH 28/29] add simple description of how to pin es snapshot versions (#51225) --- packages/kbn-es/README.md | 60 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/packages/kbn-es/README.md b/packages/kbn-es/README.md index 0d9af2442ebf42..4d4c2aa94db07f 100644 --- a/packages/kbn-es/README.md +++ b/packages/kbn-es/README.md @@ -59,4 +59,62 @@ Cloned location of elasticsearch repository, used when running from source Type: `String` -Location where snapshots are cached \ No newline at end of file +Location where snapshots are cached + +## Snapshot Pinning + +Sometimes we need to pin snapshots for a specific version. We'd really like to get this automated, but until that is completed here are the steps to take to build, upload, and switch to pinned snapshots for a branch. + +To use these steps you'll need to setup the google-cloud-sdk, which can be installed on macOS with `brew cask install google-cloud-sdk`. Login with the CLI and you'll have access to the `gsutil` to do efficient/parallel uploads to GCS from the command line. + + 1. Clone the elasticsearch repo somewhere + 2. Checkout the branch you want to build + 3. Run the following to delete old distributables + + ``` + find distribution/archives -type f \( -name 'elasticsearch-*-*.tar.gz' -o -name 'elasticsearch-*-*.zip' \) -not -path *no-jdk* -exec rm {} \; + ``` + + 4. Build the new artifacts + + ``` + ./gradlew -p distribution/archives assemble --parallel + ``` + + 4. Copy new artifacts to your `~/Downloads/tmp-artifacts` + + ``` + rm -rf ~/Downloads/tmp-artifacts + mkdir ~/Downloads/tmp-artifacts + find distribution/archives -type f \( -name 'elasticsearch-*-*.tar.gz' -o -name 'elasticsearch-*-*.zip' \) -not -path *no-jdk* -exec cp {} ~/Downloads/tmp-artifacts \; + ``` + + 5. Calculate shasums of the uploads + + ``` + cd ~/Downloads/tmp-artifacts + find * -exec bash -c "shasum -a 512 {} > {}.sha512" \; + ``` + + 6. Check that the files in `~/Downloads/tmp-artifacts` look reasonable + 7. Upload the files to GCS + + ``` + gsutil -m rsync . gs://kibana-ci-tmp-artifacts/ + ``` + + 8. Once the artifacts are uploaded, modify `packages/kbn-es/src/custom_snapshots.js` in a PR to use a URL formatted like: + + ``` + // force use of manually created snapshots until ReindexPutMappings fix + if (!process.env.KBN_ES_SNAPSHOT_URL && !process.argv.some(isVersionFlag)) { + // return undefined; + return 'https://storage.googleapis.com/kibana-ci-tmp-artifacts/{name}-{version}-{os}-x86_64.{ext}'; + } + ``` + + For 6.8, the format of the url should look like: + + ``` + 'https://storage.googleapis.com/kibana-ci-tmp-artifacts/{name}-{version}.{ext}'; + ``` \ No newline at end of file From 7d49b2f9c3965755609ea6bbe0497c23823b132f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20=C3=81lvarez?= Date: Thu, 21 Nov 2019 10:25:14 +0100 Subject: [PATCH 29/29] update apm index pattern (#51256) --- .../kibana/server/tutorials/apm/index_pattern.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json b/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json index f54c2fa35f80d0..69a165c09c2f91 100644 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json +++ b/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json @@ -1,11 +1,11 @@ { "attributes": { - "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", - "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", + "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", + "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", "sourceFilters": "[{\"value\":\"sourcemap.sourcemap\"}]", "timeFieldName": "@timestamp" }, "id": "apm-*", "type": "index-pattern", "version": "1" -} +} \ No newline at end of file