diff --git a/.ci/Jenkinsfile_security_cypress b/.ci/Jenkinsfile_security_cypress index d7f702a56563f..f7b02cd1c4ab1 100644 --- a/.ci/Jenkinsfile_security_cypress +++ b/.ci/Jenkinsfile_security_cypress @@ -10,7 +10,8 @@ kibanaPipeline(timeoutMinutes: 180) { ) { catchError { withEnv([ - 'CI_PARALLEL_PROCESS_NUMBER=1' + 'CI_PARALLEL_PROCESS_NUMBER=1', + 'IGNORE_SHIP_CI_STATS_ERROR=true', ]) { def job = 'xpack-securityCypress' diff --git a/.ci/es-snapshots/Jenkinsfile_verify_es b/.ci/es-snapshots/Jenkinsfile_verify_es index 11a39faa9aed0..736a71b73d14d 100644 --- a/.ci/es-snapshots/Jenkinsfile_verify_es +++ b/.ci/es-snapshots/Jenkinsfile_verify_es @@ -26,10 +26,12 @@ kibanaPipeline(timeoutMinutes: 150) { message: "[${SNAPSHOT_VERSION}] ES Snapshot Verification Failure", ) { retryable.enable(2) - withEnv(["ES_SNAPSHOT_MANIFEST=${SNAPSHOT_MANIFEST}"]) { + withEnv([ + "ES_SNAPSHOT_MANIFEST=${SNAPSHOT_MANIFEST}", + 'IGNORE_SHIP_CI_STATS_ERROR=true', + ]) { parallel([ 'kibana-intake-agent': workers.intake('kibana-intake', './test/scripts/jenkins_unit.sh'), - 'x-pack-intake-agent': workers.intake('x-pack-intake', './test/scripts/jenkins_xpack.sh'), 'kibana-oss-agent': workers.functional('kibana-oss-tests', { kibanaPipeline.buildOss() }, [ 'oss-ciGroup1': kibanaPipeline.ossCiGroupProcess(1), 'oss-ciGroup2': kibanaPipeline.ossCiGroupProcess(2), diff --git a/.ci/jobs.yml b/.ci/jobs.yml index b05e834f5a459..6aa93d4a1056a 100644 --- a/.ci/jobs.yml +++ b/.ci/jobs.yml @@ -2,7 +2,6 @@ JOB: - kibana-intake - - x-pack-intake - kibana-firefoxSmoke - kibana-ciGroup1 - kibana-ciGroup2 diff --git a/.eslintrc.js b/.eslintrc.js index 9430b9bf24466..7608bcb40a0b9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1119,6 +1119,39 @@ module.exports = { // All files files: ['x-pack/plugins/enterprise_search/**/*.{ts,tsx}'], rules: { + 'import/order': [ + 'error', + { + groups: ['unknown', ['builtin', 'external'], 'internal', 'parent', 'sibling', 'index'], + pathGroups: [ + { + pattern: + '{../../../../../../,../../../../../,../../../../,../../../,../../,../}{common/,*}__mocks__{*,/**}', + group: 'unknown', + }, + { + pattern: '{**,.}/*.mock', + group: 'unknown', + }, + { + pattern: 'react*', + group: 'external', + position: 'before', + }, + { + pattern: '{@elastic/**,@kbn/**,src/**}', + group: 'internal', + }, + ], + pathGroupsExcludedImportTypes: [], + alphabetize: { + order: 'asc', + caseInsensitive: true, + }, + 'newlines-between': 'always-and-inside-groups', + }, + ], + 'import/newline-after-import': 'error', 'react-hooks/exhaustive-deps': 'off', 'react/jsx-boolean-value': ['error', 'never'], }, diff --git a/dev_docs/assets/applications.png b/dev_docs/assets/applications.png new file mode 100644 index 0000000000000..409f3416136ec Binary files /dev/null and b/dev_docs/assets/applications.png differ diff --git a/dev_docs/assets/platform_plugins_core.png b/dev_docs/assets/platform_plugins_core.png new file mode 100644 index 0000000000000..a1b7df4483c3f Binary files /dev/null and b/dev_docs/assets/platform_plugins_core.png differ diff --git a/dev_docs/kibana_platform_plugin_intro.mdx b/dev_docs/kibana_platform_plugin_intro.mdx index 3303561fae069..ce8b8b8b54756 100644 --- a/dev_docs/kibana_platform_plugin_intro.mdx +++ b/dev_docs/kibana_platform_plugin_intro.mdx @@ -11,45 +11,34 @@ From an end user perspective, Kibana is a tool for interacting with Elasticsearc to visualize and analyze data. From a developer perspective, Kibana is a platform that provides a set of tools to build not only the UI you see in Kibana today, but -a wide variety of applications that can be used to explore, visualize, and act upon data in Elasticsearch. The platform provides developers the ability to build applications, or inject extra functionality into +a wide variety of applications that can be used to explore, visualize, and act upon data in Elasticsearch. The platform provides developers the ability +to build applications, or inject extra functionality into already existing applications. Did you know that almost everything you see in the Kibana UI is built inside a plugin? If you removed all plugins from Kibana, you'd be left with an empty navigation menu, and a set of developer tools. The Kibana platform is a blank canvas, just waiting for a developer to come along and create something! ![Kibana personas](assets/kibana_platform_plugin_end_user.png) + +## Platform services -## Plugins vs The Platform +Plugins have access to three kinds of public services: -The core platform provides the most basic and fundamental tools neccessary for building a plugin, like creating saved objects, -routing, application registration, and notifications. The Core platform is not a plugin itself, although -there are some plugins that provide platform functionality. For example, the - provides basic utilities to search, query, and filter data in Elasticsearch. -This code is not part of Core, but is still fundamental for building a plugin, - and we strongly encourage using this service over querying Elasticsearch directly. - - -We currently have three kinds of public services: - - - platform services provided by `core` - - platform services provided by plugins, that can, and should, be used by every plugin (e.g. ) . - - shared services provided by plugins, that are only relevant for only a few, specific plugins (e.g. "presentation utils"). - -Two common questions we encounter are: + - Platform services provided by `core` () + - Platform services provided by plugins () + - Shared services provided by plugins, that are only relevant for only a few, specific plugins (e.g. "presentation utils"). -1. Which services are platform services? -2. What is the difference between platform code supplied by core, and platform code supplied by plugins? + The first two items are what make up "Platform services". -We don't have great answers to those questions today. Currently, the best answers we have are: + -1. Platform plugins are _usually_ plugins that are managed by the Platform Group, but we are starting to see some exceptions. -2. `core` code contains the most fundamental and stable services needed for plugin development. Everything else goes in a plugin. +We try to put only the most stable and fundamental code into `Core`, while more application focused functionality goes in a plugin, but the heuristic isn't +clear, and we haven't done a great job of sticking to it. For example, notifications and toasts are core services, but data and search are plugin services. -We will continue to focus on adding clarity around these types of services and what developers can expect from each. - - +Today it looks something like this. +![Core vs platform plugins vs plugins](assets/platform_plugins_core.png) + - When the Kibana platform and plugin infrastructure was built, we thought of two types of code: core services, and other plugin services. We planned to keep the most stable and fundamental code needed to build plugins inside core. @@ -70,125 +59,62 @@ Another side effect of having many small plugins is that common code often ends We recognize the need to better clarify the relationship between core functionality, platform-like plugin functionality, and functionality exposed by other plugins. It's something we will be working on! - -The main difference between core functionality and functionality supplied by plugins, is in how it is accessed. Core is -passed to plugins as the first parameter to their `start` and `setup` lifecycle functions, while plugin supplied functionality is passed as the -second parameter. Plugin dependencies must be declared explicitly inside the `kibana.json` file. Core functionality is always provided. Read the -section on for more information. - -## The anatomy of a plugin - -Plugins are defined as classes and present themselves to Kibana through a simple wrapper function. A plugin can have browser-side code, server-side code, -or both. There is no architectural difference between a plugin in the browser and a plugin on the server. In both places, you describe your plugin similarly, -and you interact with Core and other plugins in the same way. - -The basic file structure of a Kibana plugin named demo that has both client-side and server-side code would be: - -``` -plugins/ - demo - kibana.json [1] - public - index.ts [2] - plugin.ts [3] - server - index.ts [4] - plugin.ts [5] -``` - -### [1] kibana.json - -`kibana.json` is a static manifest file that is used to identify the plugin and to specify if this plugin has server-side code, browser-side code, or both: - -``` -{ - "id": "demo", - "version": "kibana", - "server": true, - "ui": true -} -``` - -### [2] public/index.ts - -`public/index.ts` is the entry point into the client-side code of this plugin. It must export a function named plugin, which will receive a standard set of - core capabilities as an argument. It should return an instance of its plugin class for Kibana to load. - -``` -import type { PluginInitializerContext } from 'kibana/server'; -import { DemoPlugin } from './plugin'; - -export function plugin(initializerContext: PluginInitializerContext) { - return new DemoPlugin(initializerContext); -} -``` - -### [3] public/plugin.ts - -`public/plugin.ts` is the client-side plugin definition itself. Technically speaking, it does not need to be a class or even a separate file from the entry - point, but all plugins at Elastic should be consistent in this way. - +We will continue to focus on adding clarity around these types of services and what developers can expect from each. - ```ts -import type { Plugin, PluginInitializerContext, CoreSetup, CoreStart } from 'kibana/server'; -export class DemoPlugin implements Plugin { - constructor(initializerContext: PluginInitializerContext) {} + - public setup(core: CoreSetup) { - // called when plugin is setting up during Kibana's startup sequence - } +### Core services - public start(core: CoreStart) { - // called after all plugins are set up - } +Sometimes referred to just as Core, Core services provide the most basic and fundamental tools neccessary for building a plugin, like creating saved objects, +routing, application registration, and notifications. The Core platform is not a plugin itself, although +there are some plugins that provide platform functionality. We call these . - public stop() { - // called when plugin is torn down during Kibana's shutdown sequence - } -} - ``` +### Platform plugins +Plugins that provide fundamental services and functionality to extend and customize Kibana, for example, the + plugin. There is no official way to tell if a plugin is a platform plugin or not. +Platform plugins are _usually_ plugins that are managed by the Platform Group, but we are starting to see some exceptions. -### [4] server/index.ts +## Plugins -`server/index.ts` is the entry-point into the server-side code of this plugin. It is identical in almost every way to the client-side entry-point: +Plugins are code that is written to extend and customize Kibana. Plugin's don't have to be part of the Kibana repo, though the Kibana +repo does contain many plugins! Plugins add customizations by +using provided by . +Sometimes people confuse the term "plugin" and "application". While often there is a 1:1 relationship between a plugin and an application, it is not always the case. +A plugin may register many applications, or none. -### [5] server/plugin.ts +### Applications -`server/plugin.ts` is the server-side plugin definition. The shape of this plugin is the same as it’s client-side counter-part: +Applications are top level pages in the Kibana UI. Dashboard, Canvas, Maps, App Search, etc, are all examples of applications: -```ts -import type { Plugin, PluginInitializerContext, CoreSetup, CoreStart } from 'kibana/server'; +![applications in kibana](./assets/applications.png) -export class DemoPlugin implements Plugin { - constructor(initializerContext: PluginInitializerContext) {} +A plugin can register an application by +adding it to core's application . - public setup(core: CoreSetup) { - // called when plugin is setting up during Kibana's startup sequence - } +### Public plugin API - public start(core: CoreStart) { - // called after all plugins are set up - } +A plugin's public API consists of everything exported from a plugin's , +as well as from the top level `index.ts` files that exist in the three "scope" folders: - public stop() { - // called when plugin is torn down during Kibana's shutdown sequence - } -} -``` +- common/index.ts +- public/index.ts +- server/index.ts -Kibana does not impose any technical restrictions on how the the internals of a plugin are architected, though there are certain -considerations related to how plugins integrate with core APIs and APIs exposed by other plugins that may greatly impact how they are built. +Any plugin that exports something from those files, or from the lifecycle methods, is exposing a public service. We sometimes call these things "plugin services" or +"shared services". -## Plugin lifecycles & Core services +## Lifecycle methods -The various independent domains that make up core are represented by a series of services. Those services expose public interfaces that are provided to all plugins. -Services expose different features at different parts of their lifecycle. We describe the lifecycle of core services and plugins with specifically-named functions on the service definition. +Core, and plugins, expose different features at different parts of their lifecycle. We describe the lifecycle of core services and plugins with + specifically-named functions on the service definition. -Kibana has three lifecycles: setup, start, and stop. Each plugin’s setup function is called sequentially while Kibana is setting up on the server or when it is being loaded in the browser. The start functions are called sequentially after setup has been completed for all plugins. The stop functions are called sequentially while Kibana is gracefully shutting down the server or when the browser tab or window is being closed. +Kibana has three lifecycles: setup, start, and stop. Each plugin’s setup function is called sequentially while Kibana is setting up + on the server or when it is being loaded in the browser. The start functions are called sequentially after setup has been completed for all plugins. + The stop functions are called sequentially while Kibana is gracefully shutting down the server or when the browser tab or window is being closed. The table below explains how each lifecycle relates to the state of Kibana. @@ -201,105 +127,18 @@ The table below explains how each lifecycle relates to the state of Kibana. Different service interfaces can and will be passed to setup, start, and stop because certain functionality makes sense in the context of a running plugin while other types of functionality may have restrictions or may only make sense in the context of a plugin that is stopping. -## How plugin's interact with each other, and Core - -The lifecycle-specific contracts exposed by core services are always passed as the first argument to the equivalent lifecycle function in a plugin. -For example, the core http service exposes a function createRouter to all plugin setup functions. To use this function to register an HTTP route handler, -a plugin just accesses it off of the first argument: - -```ts -import type { CoreSetup } from 'kibana/server'; - -export class DemoPlugin { - public setup(core: CoreSetup) { - const router = core.http.createRouter(); - // handler is called when '/path' resource is requested with `GET` method - router.get({ path: '/path', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); - } -} -``` - -Unlike core, capabilities exposed by plugins are not automatically injected into all plugins. -Instead, if a plugin wishes to use the public interface provided by another plugin, it must first declare that plugin as a - dependency in it’s kibana.json manifest file. - -** foobar plugin.ts: ** - -``` -import type { Plugin } from 'kibana/server'; -export interface FoobarPluginSetup { [1] - getFoo(): string; -} - -export interface FoobarPluginStart { [1] - getBar(): string; -} - -export class MyPlugin implements Plugin { - public setup(): FoobarPluginSetup { - return { - getFoo() { - return 'foo'; - }, - }; - } - - public start(): FoobarPluginStart { - return { - getBar() { - return 'bar'; - }, - }; - } -} -``` -[1] We highly encourage plugin authors to explicitly declare public interfaces for their plugins. - - -** demo kibana.json** - -``` -{ - "id": "demo", - "requiredPlugins": ["foobar"], - "server": true, - "ui": true -} -``` - -With that specified in the plugin manifest, the appropriate interfaces are then available via the second argument of setup and/or start: - -```ts -import type { CoreSetup, CoreStart } from 'kibana/server'; -import type { FoobarPluginSetup, FoobarPluginStart } from '../../foobar/server'; - -interface DemoSetupPlugins { [1] - foobar: FoobarPluginSetup; -} - -interface DemoStartPlugins { - foobar: FoobarPluginStart; -} - -export class DemoPlugin { - public setup(core: CoreSetup, plugins: DemoSetupPlugins) { [2] - const { foobar } = plugins; - foobar.getFoo(); // 'foo' - foobar.getBar(); // throws because getBar does not exist - } - - public start(core: CoreStart, plugins: DemoStartPlugins) { [3] - const { foobar } = plugins; - foobar.getFoo(); // throws because getFoo does not exist - foobar.getBar(); // 'bar' - } - - public stop() {} -} -``` - -[1] The interface for plugin’s dependencies must be manually composed. You can do this by importing the appropriate type from the plugin and constructing an interface where the property name is the plugin’s ID. - -[2] These manually constructed types should then be used to specify the type of the second argument to the plugin. - -[3] Notice that the type for the setup and start lifecycles are different. Plugin lifecycle functions can only access the APIs that are exposed during that lifecycle. +## Extension points + +An extension point is a function provided by core, or a plugin's plugin API, that can be used by other +plugins to customize the Kibana experience. Examples of extension points are: + +- core.application.register (The extension point talked about above) +- core.notifications.toasts.addSuccess +- core.overlays.showModal +- embeddables.registerEmbeddableFactory +- uiActions.registerAction +- core.saedObjects.registerType + +## Follow up material + +Learn how to build your own plugin by following \ No newline at end of file diff --git a/dev_docs/tutorials/building_a_plugin.mdx b/dev_docs/tutorials/building_a_plugin.mdx new file mode 100644 index 0000000000000..cee5a9a399de5 --- /dev/null +++ b/dev_docs/tutorials/building_a_plugin.mdx @@ -0,0 +1,226 @@ +--- +id: kibDevTutorialBuildAPlugin +slug: /kibana-dev-docs/tutorials/build-a-plugin +title: Kibana plugin tutorial +summary: Anatomy of a Kibana plugin and how to build one +date: 2021-02-05 +tags: ['kibana','onboarding', 'dev', 'tutorials'] +--- + +Prereading material: + +- + +## The anatomy of a plugin + +Plugins are defined as classes and present themselves to Kibana through a simple wrapper function. A plugin can have browser-side code, server-side code, +or both. There is no architectural difference between a plugin in the browser and a plugin on the server. In both places, you describe your plugin similarly, +and you interact with Core and other plugins in the same way. + +The basic file structure of a Kibana plugin named demo that has both client-side and server-side code would be: + +``` +plugins/ + demo + kibana.json [1] + public + index.ts [2] + plugin.ts [3] + server + index.ts [4] + plugin.ts [5] + common + index.ts [6] +``` + +### [1] kibana.json + +`kibana.json` is a static manifest file that is used to identify the plugin and to specify if this plugin has server-side code, browser-side code, or both: + +``` +{ + "id": "demo", + "version": "kibana", + "server": true, + "ui": true +} +``` + +### [2] public/index.ts + +`public/index.ts` is the entry point into the client-side code of this plugin. It must export a function named plugin, which will receive a standard set of + core capabilities as an argument. It should return an instance of its plugin class for Kibana to load. + +``` +import type { PluginInitializerContext } from 'kibana/server'; +import { DemoPlugin } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new DemoPlugin(initializerContext); +} +``` + +### [3] public/plugin.ts + +`public/plugin.ts` is the client-side plugin definition itself. Technically speaking, it does not need to be a class or even a separate file from the entry + point, but all plugins at Elastic should be consistent in this way. + + + ```ts +import type { Plugin, PluginInitializerContext, CoreSetup, CoreStart } from 'kibana/server'; + +export class DemoPlugin implements Plugin { + constructor(initializerContext: PluginInitializerContext) {} + + public setup(core: CoreSetup) { + // called when plugin is setting up during Kibana's startup sequence + } + + public start(core: CoreStart) { + // called after all plugins are set up + } + + public stop() { + // called when plugin is torn down during Kibana's shutdown sequence + } +} + ``` + + +### [4] server/index.ts + +`server/index.ts` is the entry-point into the server-side code of this plugin. It is identical in almost every way to the client-side entry-point: + +### [5] server/plugin.ts + +`server/plugin.ts` is the server-side plugin definition. The shape of this plugin is the same as it’s client-side counter-part: + +```ts +import type { Plugin, PluginInitializerContext, CoreSetup, CoreStart } from 'kibana/server'; + +export class DemoPlugin implements Plugin { + constructor(initializerContext: PluginInitializerContext) {} + + public setup(core: CoreSetup) { + // called when plugin is setting up during Kibana's startup sequence + } + + public start(core: CoreStart) { + // called after all plugins are set up + } + + public stop() { + // called when plugin is torn down during Kibana's shutdown sequence + } +} +``` + +Kibana does not impose any technical restrictions on how the the internals of a plugin are architected, though there are certain +considerations related to how plugins integrate with core APIs and APIs exposed by other plugins that may greatly impact how they are built. + +### [6] common/index.ts + +`common/index.ts` is the entry-point into code that can be used both server-side or client side. + +## How plugin's interact with each other, and Core + +The lifecycle-specific contracts exposed by core services are always passed as the first argument to the equivalent lifecycle function in a plugin. +For example, the core http service exposes a function createRouter to all plugin setup functions. To use this function to register an HTTP route handler, +a plugin just accesses it off of the first argument: + +```ts +import type { CoreSetup } from 'kibana/server'; + +export class DemoPlugin { + public setup(core: CoreSetup) { + const router = core.http.createRouter(); + // handler is called when '/path' resource is requested with `GET` method + router.get({ path: '/path', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); + } +} +``` + +Unlike core, capabilities exposed by plugins are not automatically injected into all plugins. +Instead, if a plugin wishes to use the public interface provided by another plugin, it must first declare that plugin as a + dependency in it’s kibana.json manifest file. + +** foobar plugin.ts: ** + +``` +import type { Plugin } from 'kibana/server'; +export interface FoobarPluginSetup { [1] + getFoo(): string; +} + +export interface FoobarPluginStart { [1] + getBar(): string; +} + +export class MyPlugin implements Plugin { + public setup(): FoobarPluginSetup { + return { + getFoo() { + return 'foo'; + }, + }; + } + + public start(): FoobarPluginStart { + return { + getBar() { + return 'bar'; + }, + }; + } +} +``` +[1] We highly encourage plugin authors to explicitly declare public interfaces for their plugins. + + +** demo kibana.json** + +``` +{ + "id": "demo", + "requiredPlugins": ["foobar"], + "server": true, + "ui": true +} +``` + +With that specified in the plugin manifest, the appropriate interfaces are then available via the second argument of setup and/or start: + +```ts +import type { CoreSetup, CoreStart } from 'kibana/server'; +import type { FoobarPluginSetup, FoobarPluginStart } from '../../foobar/server'; + +interface DemoSetupPlugins { [1] + foobar: FoobarPluginSetup; +} + +interface DemoStartPlugins { + foobar: FoobarPluginStart; +} + +export class DemoPlugin { + public setup(core: CoreSetup, plugins: DemoSetupPlugins) { [2] + const { foobar } = plugins; + foobar.getFoo(); // 'foo' + foobar.getBar(); // throws because getBar does not exist + } + + public start(core: CoreStart, plugins: DemoStartPlugins) { [3] + const { foobar } = plugins; + foobar.getFoo(); // throws because getFoo does not exist + foobar.getBar(); // 'bar' + } + + public stop() {} +} +``` + +[1] The interface for plugin’s dependencies must be manually composed. You can do this by importing the appropriate type from the plugin and constructing an interface where the property name is the plugin’s ID. + +[2] These manually constructed types should then be used to specify the type of the second argument to the plugin. + +[3] Notice that the type for the setup and start lifecycles are different. Plugin lifecycle functions can only access the APIs that are exposed during that lifecycle. diff --git a/docs/developer/contributing/development-ci-metrics.asciidoc b/docs/developer/contributing/development-ci-metrics.asciidoc index 3e49686fb67f0..2efe4e7c60a7d 100644 --- a/docs/developer/contributing/development-ci-metrics.asciidoc +++ b/docs/developer/contributing/development-ci-metrics.asciidoc @@ -121,13 +121,20 @@ Changes to the {kib-repo}blob/{branch}/packages/kbn-optimizer/limits.yml[`limits [[ci-metric-validating-limits]] === Validating `page load bundle size` limits -Once you've fixed any issues discovered while diagnosing overages you probably should just push the changes to your PR and let CI validate them. +While you're trying to track down changes which will improve the bundle size, try running the following command locally: -If you have a pretty powerful dev machine, or the necessary patience/determination, you can validate the limits locally by running the following command: +[source,shell] +----------- +node scripts/build_kibana_platform_plugins --dist --watch --focus {pluginId} +----------- + +This will build the front-end bundles for your plugin and only the plugins your plugin depends on. Whenever you make changes the bundles are rebuilt and you can inspect the metrics of that build in the `target/public/metrics.json` file within your plugin. This file will be updated as you save changes to the source and should be helpful to determine if your changes are lowering the `page load asset size` enough. + +If you only want to run the build once you can run: [source,shell] ----------- -node scripts/build_kibana_platform_plugins --validate-limits +node scripts/build_kibana_platform_plugins --validate-limits --focus {pluginId} ----------- This command needs to apply production optimizations to get the right sizes, which means that the optimizer will take significantly longer to run and on most developmer machines will consume all of your machines resources for 20 minutes or more. If you'd like to multi-task while this is running you might need to limit the number of workers using the `--max-workers` flag. \ No newline at end of file diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 6587d5dc422b4..263addc98ee62 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -443,10 +443,6 @@ using the CURL scripts in the scripts folder. |Visualize geo data from Elasticsearch or 3rd party geo-services. -|{kib-repo}blob/{branch}/x-pack/plugins/maps_file_upload/README.md[mapsFileUpload] -|Deprecated - plugin targeted for removal and will get merged into file_upload plugin - - |{kib-repo}blob/{branch}/x-pack/plugins/maps_legacy_licensing/README.md[mapsLegacyLicensing] |This plugin provides access to the detailed tile map services from Elastic. diff --git a/docs/migration/migrate_8_0.asciidoc b/docs/migration/migrate_8_0.asciidoc index 14eff4594c813..5452621440ed8 100644 --- a/docs/migration/migrate_8_0.asciidoc +++ b/docs/migration/migrate_8_0.asciidoc @@ -52,7 +52,18 @@ for example, `logstash-*`. ==== Default logging timezone is now the system's timezone *Details:* In prior releases the timezone used in logs defaulted to UTC. We now use the host machine's timezone by default. -*Impact:* To restore the previous behavior, in kibana.yml set `logging.timezone: UTC`. +*Impact:* To restore the previous behavior, in kibana.yml use the pattern layout, with a date modifier: +[source,yaml] +------------------- +logging: + appenders: + console: + kind: console + layout: + kind: pattern + pattern: "%date{ISO8601_TZ}{UTC}" +------------------- +See https://github.com/elastic/kibana/pull/90368 for more details. [float] ==== Responses are never logged by default diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index ecdb41c897b12..9b9c26fd0e1db 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -309,7 +309,8 @@ suppress all logging output. *Default: `false`* | Set to the canonical time zone ID (for example, `America/Los_Angeles`) to log events using that time zone. For possible values, refer to -https://en.wikipedia.org/wiki/List_of_tz_database_time_zones[database time zones]. *Default: `UTC`* +https://en.wikipedia.org/wiki/List_of_tz_database_time_zones[database time zones]. +When not set, log events use the host timezone | [[logging-verbose]] `logging.verbose:` {ess-icon} | Set to `true` to log all events, including system usage information and all diff --git a/docs/user/alerting/alert-types.asciidoc b/docs/user/alerting/alert-types.asciidoc index 279739e95b522..016ecc3167298 100644 --- a/docs/user/alerting/alert-types.asciidoc +++ b/docs/user/alerting/alert-types.asciidoc @@ -130,12 +130,13 @@ image::images/alert-types-es-query-select.png[Choosing an ES query alert type] [float] ==== Defining the conditions -The ES query alert has 4 clauses that define the condition to detect. +The ES query alert has 5 clauses that define the condition to detect. [role="screenshot"] image::images/alert-types-es-query-conditions.png[Four clauses define the condition to detect] Index:: This clause requires an *index or index pattern* and a *time field* that will be used for the *time window*. +Size:: This clause specifies the number of documents to pass to the configured actions when the the threshold condition is met. ES query:: This clause specifies the ES DSL query to execute. The number of documents that match this query will be evaulated against the threshold condition. Aggregations are not supported at this time. Threshold:: This clause defines a threshold value and a comparison operator (`is above`, `is above or equals`, `is below`, `is below or equals`, or `is between`). The number of documents that match the specified query is compared to this threshold. diff --git a/docs/user/alerting/images/alert-types-es-query-conditions.png b/docs/user/alerting/images/alert-types-es-query-conditions.png index ce2bd6a42a4b5..3cbba5eb4950e 100644 Binary files a/docs/user/alerting/images/alert-types-es-query-conditions.png and b/docs/user/alerting/images/alert-types-es-query-conditions.png differ diff --git a/jest.config.integration.js b/jest.config.integration.js index df9fa9029aaa3..50767932a52d7 100644 --- a/jest.config.integration.js +++ b/jest.config.integration.js @@ -17,6 +17,7 @@ module.exports = { testPathIgnorePatterns: preset.testPathIgnorePatterns.filter( (pattern) => !pattern.includes('integration_tests') ), + setupFilesAfterEnv: ['/packages/kbn-test/target/jest/setup/after_env.integration.js'], reporters: [ 'default', [ @@ -24,5 +25,7 @@ module.exports = { { reportName: 'Jest Integration Tests' }, ], ], - setupFilesAfterEnv: ['/packages/kbn-test/target/jest/setup/after_env.integration.js'], + coverageReporters: !!process.env.CI + ? [['json', { file: 'jest-integration.json' }]] + : ['html', 'text'], }; diff --git a/jest.config.js b/jest.config.js index 89f66b5ee462f..03dc832ba170c 100644 --- a/jest.config.js +++ b/jest.config.js @@ -7,6 +7,14 @@ */ module.exports = { + preset: '@kbn/test', rootDir: '.', - projects: [...require('./jest.config.oss').projects, ...require('./x-pack/jest.config').projects], + projects: [ + '/packages/*/jest.config.js', + '/src/*/jest.config.js', + '/src/legacy/*/jest.config.js', + '/src/plugins/*/jest.config.js', + '/test/*/jest.config.js', + '/x-pack/plugins/*/jest.config.js', + ], }; diff --git a/jest.config.oss.js b/jest.config.oss.js deleted file mode 100644 index fcd704382f39d..0000000000000 --- a/jest.config.oss.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '.', - projects: [ - '/packages/*/jest.config.js', - '/src/*/jest.config.js', - '/src/legacy/*/jest.config.js', - '/src/plugins/*/jest.config.js', - '/test/*/jest.config.js', - ], -}; diff --git a/package.json b/package.json index 7144745f2ae35..aac576dbc3561 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "@babel/runtime": "^7.12.5", "@elastic/datemath": "link:packages/elastic-datemath", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary", - "@elastic/ems-client": "7.11.0", + "@elastic/ems-client": "7.12.0", "@elastic/eui": "31.4.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "^9.0.1-kibana3", diff --git a/packages/kbn-dev-utils/src/ci_stats_reporter/ship_ci_stats_cli.ts b/packages/kbn-dev-utils/src/ci_stats_reporter/ship_ci_stats_cli.ts index 1ee78518bb801..4d07b54b8cf03 100644 --- a/packages/kbn-dev-utils/src/ci_stats_reporter/ship_ci_stats_cli.ts +++ b/packages/kbn-dev-utils/src/ci_stats_reporter/ship_ci_stats_cli.ts @@ -22,10 +22,18 @@ export function shipCiStatsCli() { throw createFlagError('expected --metrics to be a string'); } + const maybeFail = (message: string) => { + const error = createFailError(message); + if (process.env.IGNORE_SHIP_CI_STATS_ERROR === 'true') { + error.exitCode = 0; + } + return error; + }; + const reporter = CiStatsReporter.fromEnv(log); if (!reporter.isEnabled()) { - throw createFailError('unable to initilize the CI Stats reporter'); + throw maybeFail('unable to initilize the CI Stats reporter'); } for (const path of metricPaths) { @@ -35,7 +43,7 @@ export function shipCiStatsCli() { if (await reporter.metrics(JSON.parse(json))) { log.success('shipped metrics from', path); } else { - throw createFailError('failed to ship metrics'); + throw maybeFail('failed to ship metrics'); } } }, diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 490c2ccc19d7d..a1e40c06f6fa1 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -104,4 +104,4 @@ pageLoadAssetSize: presentationUtil: 28545 spacesOss: 18817 osquery: 107090 - mapsFileUpload: 23775 + fileUpload: 25664 diff --git a/packages/kbn-test/jest-preset.js b/packages/kbn-test/jest-preset.js index 9ed11c4fe5fdd..717be8f413b48 100644 --- a/packages/kbn-test/jest-preset.js +++ b/packages/kbn-test/jest-preset.js @@ -19,7 +19,9 @@ module.exports = { coveragePathIgnorePatterns: ['/node_modules/', '.*\\.d\\.ts'], // A list of reporter names that Jest uses when writing coverage reports - coverageReporters: !!process.env.CODE_COVERAGE ? ['json'] : ['html', 'text'], + coverageReporters: !!process.env.CODE_COVERAGE + ? [['json', { file: 'jest.json' }]] + : ['html', 'text'], // An array of file extensions your modules use moduleFileExtensions: ['js', 'mjs', 'json', 'ts', 'tsx', 'node'], diff --git a/rfcs/text/0013_saved_object_migrations.md b/rfcs/text/0013_saved_object_migrations.md index 6f5ab280a4612..88879e5e706eb 100644 --- a/rfcs/text/0013_saved_object_migrations.md +++ b/rfcs/text/0013_saved_object_migrations.md @@ -248,45 +248,49 @@ Note: 6. Use the reindexed legacy `.kibana_pre6.5.0_001` as the source for the rest of the migration algorithm. 3. If `.kibana` and `.kibana_7.10.0` both exists and are pointing to the same index this version's migration has already been completed. 1. Because the same version can have plugins enabled at any point in time, - perform the mappings update in step (7) and migrate outdated documents - with step (8). - 2. Skip to step (10) to start serving traffic. + migrate outdated documents with step (9) and perform the mappings update in step (10). + 2. Skip to step (12) to start serving traffic. 4. Fail the migration if: 1. `.kibana` is pointing to an index that belongs to a later version of Kibana .e.g. `.kibana_7.12.0_001` 2. (Only in 8.x) The source index contains documents that belong to an unknown Saved Object type (from a disabled plugin). Log an error explaining that the plugin that created these documents needs to be enabled again or that these objects should be deleted. See section (4.2.1.4). -5. Mark the source index as read-only and wait for all in-flight operations to drain (requires https://github.com/elastic/elasticsearch/pull/58094). This prevents any further writes from outdated nodes. Assuming this API is similar to the existing `//_close` API, we expect to receive `"acknowledged" : true` and `"shards_acknowledged" : true`. If all shards don’t acknowledge within the timeout, retry the operation until it succeeds. -6. Clone the source index into a new target index which has writes enabled. All nodes on the same version will use the same fixed index name e.g. `.kibana_7.10.0_001`. The `001` postfix isn't used by Kibana, but allows for re-indexing an index should this be required by an Elasticsearch upgrade. E.g. re-index `.kibana_7.10.0_001` into `.kibana_7.10.0_002` and point the `.kibana_7.10.0` alias to `.kibana_7.10.0_002`. - 1. `POST /.kibana_n/_clone/.kibana_7.10.0_001?wait_for_active_shards=all {"settings": {"index.blocks.write": false}}`. Ignore errors if the clone already exists. - 2. Wait for the cloning to complete `GET /_cluster/health/.kibana_7.10.0_001?wait_for_status=green&timeout=60s` If cloning doesn’t complete within the 60s timeout, log a warning for visibility and poll again. -7. Update the mappings of the target index +5. Set a write block on the source index. This prevents any further writes from outdated nodes. +6. Create a new temporary index `.kibana_7.10.0_reindex_temp` with `dynamic: false` on the top-level mappings so that any kind of document can be written to the index. This allows us to write untransformed documents to the index which might have fields which have been removed from the latest mappings defined by the plugin. Define minimal mappings for the `migrationVersion` and `type` fields so that we're still able to search for outdated documents that need to be transformed. + 1. Ignore errors if the target index already exists. +7. Reindex the source index into the new temporary index. + 1. Use `op_type=create` `conflicts=proceed` and `wait_for_completion=false` so that multiple instances can perform the reindex in parallel but only one write per document will succeed. + 2. Wait for the reindex task to complete. If reindexing doesn’t complete within the 60s timeout, log a warning for visibility and poll again. +8. Clone the temporary index into the target index `.kibana_7.10.0_001`. Since any further writes will only happen against the cloned target index this prevents a lost delete from occuring where one instance finishes the migration and deletes a document and another instance's reindex operation re-creates the deleted document. + 1. Set a write block on the temporary index + 2. Clone the temporary index into the target index while specifying that the target index should have writes enabled. + 3. If the clone operation fails because the target index already exist, ignore the error and wait for the target index to become green before proceeding. + 4. (The `001` postfix in the target index name isn't used by Kibana, but allows for re-indexing an index should this be required by an Elasticsearch upgrade. E.g. re-index `.kibana_7.10.0_001` into `.kibana_7.10.0_002` and point the `.kibana_7.10.0` alias to `.kibana_7.10.0_002`.) +9. Transform documents by reading batches of outdated documents from the target index then transforming and updating them with optimistic concurrency control. + 1. Ignore any version conflict errors. + 2. If a document transform throws an exception, add the document to a failure list and continue trying to transform all other documents. If any failures occured, log the complete list of documents that failed to transform. Fail the migration. +10. Update the mappings of the target index 1. Retrieve the existing mappings including the `migrationMappingPropertyHashes` metadata. - 2. Update the mappings with `PUT /.kibana_7.10.0_001/_mapping`. The API deeply merges any updates so this won't remove the mappings of any plugins that were enabled in a previous version but are now disabled. + 2. Update the mappings with `PUT /.kibana_7.10.0_001/_mapping`. The API deeply merges any updates so this won't remove the mappings of any plugins that are disabled on this instance but have been enabled on another instance that also migrated this index. 3. Ensure that fields are correctly indexed using the target index's latest mappings `POST /.kibana_7.10.0_001/_update_by_query?conflicts=proceed`. In the future we could optimize this query by only targeting documents: 1. That belong to a known saved object type. - 2. Which don't have outdated migrationVersion numbers since these will be transformed anyway. - 3. That belong to a type whose mappings were changed by comparing the `migrationMappingPropertyHashes`. (Metadata, unlike the mappings isn't commutative, so there is a small chance that the metadata hashes do not accurately reflect the latest mappings, however, this will just result in an less efficient query). -8. Transform documents by reading batches of outdated documents from the target index then transforming and updating them with optimistic concurrency control. - 1. Ignore any version conflict errors. - 2. If a document transform throws an exception, add the document to a failure list and continue trying to transform all other documents. If any failures occured, log the complete list of documents that failed to transform. Fail the migration. -9. Mark the migration as complete. This is done as a single atomic +11. Mark the migration as complete. This is done as a single atomic operation (requires https://github.com/elastic/elasticsearch/pull/58100) - to guarantees when multiple versions of Kibana are performing the + to guarantee that when multiple versions of Kibana are performing the migration in parallel, only one version will win. E.g. if 7.11 and 7.12 are started in parallel and migrate from a 7.9 index, either 7.11 or 7.12 should succeed and accept writes, but not both. - 3. Checks that `.kibana` alias is still pointing to the source index - 4. Points the `.kibana_7.10.0` and `.kibana` aliases to the target index. - 5. If this fails with a "required alias [.kibana] does not exist" error fetch `.kibana` again: + 1. Check that `.kibana` alias is still pointing to the source index + 2. Point the `.kibana_7.10.0` and `.kibana` aliases to the target index. + 3. Remove the temporary index `.kibana_7.10.0_reindex_temp` + 4. If this fails with a "required alias [.kibana] does not exist" error or "index_not_found_exception" for the temporary index, fetch `.kibana` again: 1. If `.kibana` is _not_ pointing to our target index fail the migration. - 2. If `.kibana` is pointing to our target index the migration has succeeded and we can proceed to step (10). -10. Start serving traffic. All saved object reads/writes happen through the + 2. If `.kibana` is pointing to our target index the migration has succeeded and we can proceed to step (12). +12. Start serving traffic. All saved object reads/writes happen through the version-specific alias `.kibana_7.10.0`. Together with the limitations, this algorithm ensures that migrations are idempotent. If two nodes are started simultaneously, both of them will start transforming documents in that version's target index, but because migrations are idempotent, it doesn’t matter which node’s writes win. - #### Known weaknesses: (Also present in our existing migration algorithm since v7.4) When the task manager index gets reindexed a reindex script is applied. diff --git a/src/core/server/config/deprecation/core_deprecations.test.ts b/src/core/server/config/deprecation/core_deprecations.test.ts index 70ca91b0d6317..4d7dafd2162c2 100644 --- a/src/core/server/config/deprecation/core_deprecations.test.ts +++ b/src/core/server/config/deprecation/core_deprecations.test.ts @@ -298,4 +298,24 @@ describe('core deprecations', () => { expect(messages).toEqual([]); }); }); + + describe('logging.timezone', () => { + it('warns when ops events are used', () => { + const { messages } = applyCoreDeprecations({ + logging: { timezone: 'GMT' }, + }); + expect(messages).toMatchInlineSnapshot(` + Array [ + "\\"logging.timezone\\" has been deprecated and will be removed in 8.0. To set the timezone moving forward, please add a timezone date modifier to the log pattern in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md", + ] + `); + }); + + it('does not warn when other events are configured', () => { + const { messages } = applyCoreDeprecations({ + logging: { events: { log: '*' } }, + }); + expect(messages).toEqual([]); + }); + }); }); diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 0db53cdb2e8be..fbdbaeb14fd59 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -127,6 +127,18 @@ const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, l return settings; }; +const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, log) => { + if (has(settings, 'logging.timezone')) { + log( + '"logging.timezone" has been deprecated and will be removed ' + + 'in 8.0. To set the timezone moving forward, please add a timezone date modifier to the log pattern ' + + 'in your logging configuration. For more details, see ' + + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md' + ); + } + return settings; +}; + export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unusedFromRoot }) => [ unusedFromRoot('savedObjects.indexCheckTimeout'), unusedFromRoot('server.xsrf.token'), @@ -163,4 +175,5 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unu mapManifestServiceUrlDeprecation, opsLoggingEventDeprecation, requestLoggingEventDeprecation, + timezoneLoggingDeprecation, ]; diff --git a/src/core/server/legacy/integration_tests/logging.test.ts b/src/core/server/legacy/integration_tests/logging.test.ts index 6588f4270fe18..321eb81708f1e 100644 --- a/src/core/server/legacy/integration_tests/logging.test.ts +++ b/src/core/server/legacy/integration_tests/logging.test.ts @@ -87,7 +87,7 @@ describe('logging service', () => { const loggedString = getPlatformLogsFromMock(mockConsoleLog); expect(loggedString).toMatchInlineSnapshot(` Array [ - "[xxxx-xx-xxTxx:xx:xx.xxxZ][INFO ][test-file] handled by NP", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][INFO ][test-file] handled by NP", ] `); }); @@ -131,9 +131,9 @@ describe('logging service', () => { expect(getPlatformLogsFromMock(mockConsoleLog)).toMatchInlineSnapshot(` Array [ - "[xxxx-xx-xxTxx:xx:xx.xxxZ][INFO ][test-file] info", - "[xxxx-xx-xxTxx:xx:xx.xxxZ][WARN ][test-file] warn", - "[xxxx-xx-xxTxx:xx:xx.xxxZ][ERROR][test-file] error", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][INFO ][test-file] info", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][WARN ][test-file] warn", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][ERROR][test-file] error", ] `); @@ -162,9 +162,9 @@ describe('logging service', () => { expect(getPlatformLogsFromMock(mockConsoleLog)).toMatchInlineSnapshot(` Array [ - "[xxxx-xx-xxTxx:xx:xx.xxxZ][INFO ][test-file] info", - "[xxxx-xx-xxTxx:xx:xx.xxxZ][WARN ][test-file] warn", - "[xxxx-xx-xxTxx:xx:xx.xxxZ][ERROR][test-file] error", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][INFO ][test-file] info", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][WARN ][test-file] warn", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][ERROR][test-file] error", ] `); @@ -199,9 +199,9 @@ describe('logging service', () => { expect(getPlatformLogsFromMock(mockConsoleLog)).toMatchInlineSnapshot(` Array [ - "[xxxx-xx-xxTxx:xx:xx.xxxZ][INFO ][test-file] info", - "[xxxx-xx-xxTxx:xx:xx.xxxZ][WARN ][test-file] warn", - "[xxxx-xx-xxTxx:xx:xx.xxxZ][ERROR][test-file] error", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][INFO ][test-file] info", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][WARN ][test-file] warn", + "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][ERROR][test-file] error", ] `); diff --git a/src/core/server/logging/README.md b/src/core/server/logging/README.md index b0759defb8803..9e3da1f3e0d71 100644 --- a/src/core/server/logging/README.md +++ b/src/core/server/logging/README.md @@ -110,7 +110,8 @@ Example of `%meta` output: ##### date Outputs the date of the logging event. The date conversion specifier may be followed by a set of braces containing a name of predefined date format and canonical timezone name. -Timezone name is expected to be one from [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) +Timezone name is expected to be one from [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). +Timezone defaults to the host timezone when not explicitly specified. Example of `%date` output: | Conversion pattern | Example | @@ -410,22 +411,22 @@ loggerWithNestedContext.debug('Message with `debug` log level.'); And assuming logger for `server` context with `console` appender and `trace` level was used, console output will look like this: ```bash -[2017-07-25T18:54:41.639Z][TRACE][server] Message with `trace` log level. -[2017-07-25T18:54:41.639Z][DEBUG][server] Message with `debug` log level. -[2017-07-25T18:54:41.639Z][INFO ][server] Message with `info` log level. -[2017-07-25T18:54:41.639Z][WARN ][server] Message with `warn` log level. -[2017-07-25T18:54:41.639Z][ERROR][server] Message with `error` log level. -[2017-07-25T18:54:41.639Z][FATAL][server] Message with `fatal` log level. - -[2017-07-25T18:54:41.639Z][TRACE][server.http] Message with `trace` log level. -[2017-07-25T18:54:41.639Z][DEBUG][server.http] Message with `debug` log level. +[2017-07-25T11:54:41.639-07:00][TRACE][server] Message with `trace` log level. +[2017-07-25T11:54:41.639-07:00][DEBUG][server] Message with `debug` log level. +[2017-07-25T11:54:41.639-07:00][INFO ][server] Message with `info` log level. +[2017-07-25T11:54:41.639-07:00][WARN ][server] Message with `warn` log level. +[2017-07-25T11:54:41.639-07:00][ERROR][server] Message with `error` log level. +[2017-07-25T11:54:41.639-07:00][FATAL][server] Message with `fatal` log level. + +[2017-07-25T11:54:41.639-07:00][TRACE][server.http] Message with `trace` log level. +[2017-07-25T11:54:41.639-07:00][DEBUG][server.http] Message with `debug` log level. ``` The log will be less verbose with `warn` level for the `server` context: ```bash -[2017-07-25T18:54:41.639Z][WARN ][server] Message with `warn` log level. -[2017-07-25T18:54:41.639Z][ERROR][server] Message with `error` log level. -[2017-07-25T18:54:41.639Z][FATAL][server] Message with `fatal` log level. +[2017-07-25T11:54:41.639-07:00][WARN ][server] Message with `warn` log level. +[2017-07-25T11:54:41.639-07:00][ERROR][server] Message with `error` log level. +[2017-07-25T11:54:41.639-07:00][FATAL][server] Message with `fatal` log level. ``` ### Logging config migration @@ -488,7 +489,7 @@ logging.root.level: all #### logging.timezone Set to the canonical timezone id to log events using that timezone. New logging config allows -to [specify timezone](#date) for `layout: pattern`. +to [specify timezone](#date) for `layout: pattern`. Defaults to host timezone when not specified. ```yaml logging: appenders: @@ -530,7 +531,7 @@ TBD | Parameter | Platform log record in **pattern** format | Legacy Platform log record **text** format | | --------------- | ------------------------------------------ | ------------------------------------------ | -| @timestamp | ISO8601 `2012-01-31T23:33:22.011Z` | Absolute `23:33:22.011` | +| @timestamp | ISO8601_TZ `2012-01-31T23:33:22.011-05:00` | Absolute `23:33:22.011` | | context | `parent.child` | `['parent', 'child']` | | level | `DEBUG` | `['debug']` | | meta | stringified JSON object `{"to": "v8"}` | N/A | diff --git a/src/core/server/logging/__snapshots__/logging_system.test.ts.snap b/src/core/server/logging/__snapshots__/logging_system.test.ts.snap index cbe0e352a0f3a..8013aec4a06fd 100644 --- a/src/core/server/logging/__snapshots__/logging_system.test.ts.snap +++ b/src/core/server/logging/__snapshots__/logging_system.test.ts.snap @@ -1,20 +1,20 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`appends records via multiple appenders.: console logs 1`] = `"[2012-01-31T23:33:22.011Z][INFO ][some-context] You know, just for your info."`; +exports[`appends records via multiple appenders.: console logs 1`] = `"[2012-01-31T18:33:22.011-05:00][INFO ][some-context] You know, just for your info."`; exports[`appends records via multiple appenders.: file logs 1`] = ` -"[2012-01-31T23:33:22.011Z][WARN ][tests] Config is not ready! +"[2012-01-31T13:33:22.011-05:00][WARN ][tests] Config is not ready! " `; exports[`appends records via multiple appenders.: file logs 2`] = ` -"[2012-01-31T23:33:22.011Z][ERROR][tests.child] Too bad that config is not ready :/ +"[2012-01-31T08:33:22.011-05:00][ERROR][tests.child] Too bad that config is not ready :/ " `; exports[`asLoggerFactory() only allows to create new loggers. 1`] = ` Object { - "@timestamp": "2012-01-31T18:33:22.011-05:00", + "@timestamp": "2012-01-30T22:33:22.011-05:00", "log": Object { "level": "TRACE", "logger": "test.context", @@ -28,7 +28,7 @@ Object { exports[`asLoggerFactory() only allows to create new loggers. 2`] = ` Object { - "@timestamp": "2012-01-31T13:33:22.011-05:00", + "@timestamp": "2012-01-30T17:33:22.011-05:00", "log": Object { "level": "INFO", "logger": "test.context", @@ -43,7 +43,7 @@ Object { exports[`asLoggerFactory() only allows to create new loggers. 3`] = ` Object { - "@timestamp": "2012-01-31T08:33:22.011-05:00", + "@timestamp": "2012-01-30T12:33:22.011-05:00", "log": Object { "level": "FATAL", "logger": "test.context", @@ -87,7 +87,7 @@ Object { exports[`uses \`root\` logger if context is not specified. 1`] = ` Array [ Array [ - "[2012-01-31T23:33:22.011Z][INFO ][root] This message goes to a root context.", + "[2012-01-31T03:33:22.011-05:00][INFO ][root] This message goes to a root context.", ], ] `; diff --git a/src/core/server/logging/layouts/__snapshots__/pattern_layout.test.ts.snap b/src/core/server/logging/layouts/__snapshots__/pattern_layout.test.ts.snap index 8988f3019d509..54e46ca7f520e 100644 --- a/src/core/server/logging/layouts/__snapshots__/pattern_layout.test.ts.snap +++ b/src/core/server/logging/layouts/__snapshots__/pattern_layout.test.ts.snap @@ -12,29 +12,29 @@ exports[`\`format()\` correctly formats record with custom pattern. 5`] = `"mock exports[`\`format()\` correctly formats record with custom pattern. 6`] = `"mock-message-6-context-6-message-6"`; -exports[`\`format()\` correctly formats record with full pattern. 1`] = `"[2012-02-01T14:30:22.011Z][FATAL][context-1] Some error stack"`; +exports[`\`format()\` correctly formats record with full pattern. 1`] = `"[2012-02-01T09:30:22.011-05:00][FATAL][context-1] Some error stack"`; -exports[`\`format()\` correctly formats record with full pattern. 2`] = `"[2012-02-01T14:30:22.011Z][ERROR][context-2] message-2"`; +exports[`\`format()\` correctly formats record with full pattern. 2`] = `"[2012-02-01T09:30:22.011-05:00][ERROR][context-2] message-2"`; -exports[`\`format()\` correctly formats record with full pattern. 3`] = `"[2012-02-01T14:30:22.011Z][WARN ][context-3] message-3"`; +exports[`\`format()\` correctly formats record with full pattern. 3`] = `"[2012-02-01T09:30:22.011-05:00][WARN ][context-3] message-3"`; -exports[`\`format()\` correctly formats record with full pattern. 4`] = `"[2012-02-01T14:30:22.011Z][DEBUG][context-4] message-4"`; +exports[`\`format()\` correctly formats record with full pattern. 4`] = `"[2012-02-01T09:30:22.011-05:00][DEBUG][context-4] message-4"`; -exports[`\`format()\` correctly formats record with full pattern. 5`] = `"[2012-02-01T14:30:22.011Z][INFO ][context-5] message-5"`; +exports[`\`format()\` correctly formats record with full pattern. 5`] = `"[2012-02-01T09:30:22.011-05:00][INFO ][context-5] message-5"`; -exports[`\`format()\` correctly formats record with full pattern. 6`] = `"[2012-02-01T14:30:22.011Z][TRACE][context-6] message-6"`; +exports[`\`format()\` correctly formats record with full pattern. 6`] = `"[2012-02-01T09:30:22.011-05:00][TRACE][context-6] message-6"`; -exports[`\`format()\` correctly formats record with highlighting. 1`] = `[2012-02-01T14:30:22.011Z][FATAL][context-1] Some error stack`; +exports[`\`format()\` correctly formats record with highlighting. 1`] = `[2012-02-01T09:30:22.011-05:00][FATAL][context-1] Some error stack`; -exports[`\`format()\` correctly formats record with highlighting. 2`] = `[2012-02-01T14:30:22.011Z][ERROR][context-2] message-2`; +exports[`\`format()\` correctly formats record with highlighting. 2`] = `[2012-02-01T09:30:22.011-05:00][ERROR][context-2] message-2`; -exports[`\`format()\` correctly formats record with highlighting. 3`] = `[2012-02-01T14:30:22.011Z][WARN ][context-3] message-3`; +exports[`\`format()\` correctly formats record with highlighting. 3`] = `[2012-02-01T09:30:22.011-05:00][WARN ][context-3] message-3`; -exports[`\`format()\` correctly formats record with highlighting. 4`] = `[2012-02-01T14:30:22.011Z][DEBUG][context-4] message-4`; +exports[`\`format()\` correctly formats record with highlighting. 4`] = `[2012-02-01T09:30:22.011-05:00][DEBUG][context-4] message-4`; -exports[`\`format()\` correctly formats record with highlighting. 5`] = `[2012-02-01T14:30:22.011Z][INFO ][context-5] message-5`; +exports[`\`format()\` correctly formats record with highlighting. 5`] = `[2012-02-01T09:30:22.011-05:00][INFO ][context-5] message-5`; -exports[`\`format()\` correctly formats record with highlighting. 6`] = `[2012-02-01T14:30:22.011Z][TRACE][context-6] message-6`; +exports[`\`format()\` correctly formats record with highlighting. 6`] = `[2012-02-01T09:30:22.011-05:00][TRACE][context-6] message-6`; exports[`allows specifying the PID in custom pattern 1`] = `"5355-context-1-Some error stack"`; diff --git a/src/core/server/logging/layouts/conversions/date.ts b/src/core/server/logging/layouts/conversions/date.ts index c1f871282c5de..66aad5b42354a 100644 --- a/src/core/server/logging/layouts/conversions/date.ts +++ b/src/core/server/logging/layouts/conversions/date.ts @@ -22,11 +22,14 @@ const formats = { UNIX_MILLIS: 'UNIX_MILLIS', }; -function formatDate(date: Date, dateFormat: string = formats.ISO8601, timezone?: string): string { +function formatDate( + date: Date, + dateFormat: string = formats.ISO8601_TZ, + timezone?: string +): string { const momentDate = moment(date); - if (timezone) { - momentDate.tz(timezone); - } + momentDate.tz(timezone ?? moment.tz.guess()); + switch (dateFormat) { case formats.ISO8601: return momentDate.toISOString(); diff --git a/src/core/server/logging/layouts/pattern_layout.test.ts b/src/core/server/logging/layouts/pattern_layout.test.ts index d291516524be0..7dd3c7c51f833 100644 --- a/src/core/server/logging/layouts/pattern_layout.test.ts +++ b/src/core/server/logging/layouts/pattern_layout.test.ts @@ -122,7 +122,9 @@ test('`format()` correctly formats record with meta data.', () => { to: 'v8', }, }) - ).toBe('[2012-02-01T14:30:22.011Z][DEBUG][context-meta]{"from":"v7","to":"v8"} message-meta'); + ).toBe( + '[2012-02-01T09:30:22.011-05:00][DEBUG][context-meta]{"from":"v7","to":"v8"} message-meta' + ); expect( layout.format({ @@ -133,7 +135,7 @@ test('`format()` correctly formats record with meta data.', () => { pid: 5355, meta: {}, }) - ).toBe('[2012-02-01T14:30:22.011Z][DEBUG][context-meta]{} message-meta'); + ).toBe('[2012-02-01T09:30:22.011-05:00][DEBUG][context-meta]{} message-meta'); expect( layout.format({ @@ -143,7 +145,7 @@ test('`format()` correctly formats record with meta data.', () => { timestamp, pid: 5355, }) - ).toBe('[2012-02-01T14:30:22.011Z][DEBUG][context-meta] message-meta'); + ).toBe('[2012-02-01T09:30:22.011-05:00][DEBUG][context-meta] message-meta'); }); test('`format()` correctly formats record with highlighting.', () => { @@ -187,10 +189,10 @@ describe('format', () => { timestamp, pid: 5355, }; - it('uses ISO8601 as default', () => { + it('uses ISO8601_TZ as default', () => { const layout = new PatternLayout(); - expect(layout.format(record)).toBe('[2012-02-01T14:30:22.011Z][DEBUG][context] message'); + expect(layout.format(record)).toBe('[2012-02-01T09:30:22.011-05:00][DEBUG][context] message'); }); describe('supports specifying a predefined format', () => { diff --git a/src/dev/code_coverage/shell_scripts/extract_archives.sh b/src/dev/code_coverage/shell_scripts/extract_archives.sh index 376467f9f2e55..14b35f8786d02 100644 --- a/src/dev/code_coverage/shell_scripts/extract_archives.sh +++ b/src/dev/code_coverage/shell_scripts/extract_archives.sh @@ -6,7 +6,7 @@ EXTRACT_DIR=/tmp/extracted_coverage mkdir -p $EXTRACT_DIR echo "### Extracting downloaded artifacts" -for x in kibana-intake x-pack-intake kibana-oss-tests kibana-xpack-tests; do +for x in kibana-intake kibana-oss-tests kibana-xpack-tests; do tar -xzf $DOWNLOAD_DIR/coverage/${x}/kibana-coverage.tar.gz -C $EXTRACT_DIR || echo "### Error 'tarring': ${x}" done diff --git a/src/dev/typescript/build_refs.ts b/src/dev/typescript/build_refs.ts index ff6a81843972c..77d6eb2abc612 100644 --- a/src/dev/typescript/build_refs.ts +++ b/src/dev/typescript/build_refs.ts @@ -7,12 +7,10 @@ */ import execa from 'execa'; -import Path from 'path'; import { run, ToolingLog } from '@kbn/dev-utils'; export async function buildAllRefs(log: ToolingLog) { await buildRefs(log, 'tsconfig.refs.json'); - await buildRefs(log, Path.join('x-pack', 'tsconfig.refs.json')); } async function buildRefs(log: ToolingLog, projectPath: string) { diff --git a/src/plugins/dashboard/public/application/listing/dashboard_listing.test.tsx b/src/plugins/dashboard/public/application/listing/dashboard_listing.test.tsx index ee731db0ced65..c7d5db970db42 100644 --- a/src/plugins/dashboard/public/application/listing/dashboard_listing.test.tsx +++ b/src/plugins/dashboard/public/application/listing/dashboard_listing.test.tsx @@ -49,11 +49,16 @@ function makeDefaultServices(): DashboardAppServices { hits, }); }; + const dashboardPanelStorage = ({ + getDashboardIdsWithUnsavedChanges: jest + .fn() + .mockResolvedValue(['dashboardUnsavedOne', 'dashboardUnsavedTwo']), + } as unknown) as DashboardPanelStorage; + return { savedObjects: savedObjectsPluginMock.createStartContract(), embeddable: embeddablePluginMock.createInstance().doStart(), dashboardCapabilities: {} as DashboardCapabilities, - dashboardPanelStorage: {} as DashboardPanelStorage, initializerContext: {} as PluginInitializerContext, chrome: chromeServiceMock.createStartContract(), navigation: {} as NavigationPublicPluginStart, @@ -68,6 +73,7 @@ function makeDefaultServices(): DashboardAppServices { restorePreviousUrl: () => {}, onAppLeave: (handler) => {}, allowByValueEmbeddables: true, + dashboardPanelStorage, savedDashboards, core, }; diff --git a/src/plugins/dashboard/public/application/listing/dashboard_listing.tsx b/src/plugins/dashboard/public/application/listing/dashboard_listing.tsx index 24d08ad06cc3b..c12385a29c4ec 100644 --- a/src/plugins/dashboard/public/application/listing/dashboard_listing.tsx +++ b/src/plugins/dashboard/public/application/listing/dashboard_listing.tsx @@ -8,7 +8,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiLink, EuiButton, EuiEmptyPrompt } from '@elastic/eui'; -import React, { Fragment, useCallback, useEffect, useMemo } from 'react'; +import React, { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; import { attemptLoadDashboardByTitle } from '../lib'; import { DashboardAppServices, DashboardRedirect } from '../types'; import { getDashboardBreadcrumb, dashboardListingTable } from '../../dashboard_strings'; @@ -48,6 +48,10 @@ export const DashboardListing = ({ }, } = useKibana(); + const [unsavedDashboardIds, setUnsavedDashboardIds] = useState( + dashboardPanelStorage.getDashboardIdsWithUnsavedChanges() + ); + // Set breadcrumbs useEffect useEffect(() => { setBreadcrumbs([ @@ -135,8 +139,12 @@ export const DashboardListing = ({ ); const deleteItems = useCallback( - (dashboards: Array<{ id: string }>) => savedDashboards.delete(dashboards.map((d) => d.id)), - [savedDashboards] + (dashboards: Array<{ id: string }>) => { + dashboards.map((d) => dashboardPanelStorage.clearPanels(d.id)); + setUnsavedDashboardIds(dashboardPanelStorage.getDashboardIdsWithUnsavedChanges()); + return savedDashboards.delete(dashboards.map((d) => d.id)); + }, + [savedDashboards, dashboardPanelStorage] ); const editItem = useCallback( @@ -179,7 +187,13 @@ export const DashboardListing = ({ tableColumns, }} > - + + setUnsavedDashboardIds(dashboardPanelStorage.getDashboardIdsWithUnsavedChanges()) + } + /> ); }; diff --git a/src/plugins/dashboard/public/application/listing/dashboard_unsaved_listing.test.tsx b/src/plugins/dashboard/public/application/listing/dashboard_unsaved_listing.test.tsx index 119b2d559b68a..13688b4061be9 100644 --- a/src/plugins/dashboard/public/application/listing/dashboard_unsaved_listing.test.tsx +++ b/src/plugins/dashboard/public/application/listing/dashboard_unsaved_listing.test.tsx @@ -17,8 +17,8 @@ import { KibanaContextProvider } from '../../services/kibana_react'; import { SavedObjectLoader } from '../../services/saved_objects'; import { DashboardPanelStorage } from '../lib'; import { DASHBOARD_PANELS_UNSAVED_ID } from '../lib/dashboard_panel_storage'; -import { DashboardAppServices, DashboardRedirect } from '../types'; -import { DashboardUnsavedListing } from './dashboard_unsaved_listing'; +import { DashboardAppServices } from '../types'; +import { DashboardUnsavedListing, DashboardUnsavedListingProps } from './dashboard_unsaved_listing'; const mockedDashboards: { [key: string]: DashboardSavedObject } = { dashboardUnsavedOne: { @@ -39,16 +39,11 @@ function makeDefaultServices(): DashboardAppServices { const core = coreMock.createStart(); core.overlays.openConfirm = jest.fn().mockResolvedValue(true); const savedDashboards = {} as SavedObjectLoader; - savedDashboards.get = jest.fn().mockImplementation((id: string) => mockedDashboards[id]); + savedDashboards.get = jest + .fn() + .mockImplementation((id: string) => Promise.resolve(mockedDashboards[id])); const dashboardPanelStorage = {} as DashboardPanelStorage; dashboardPanelStorage.clearPanels = jest.fn(); - dashboardPanelStorage.getDashboardIdsWithUnsavedChanges = jest - .fn() - .mockImplementation(() => [ - 'dashboardUnsavedOne', - 'dashboardUnsavedTwo', - 'dashboardUnsavedThree', - ]); return ({ dashboardPanelStorage, savedDashboards, @@ -56,14 +51,18 @@ function makeDefaultServices(): DashboardAppServices { } as unknown) as DashboardAppServices; } -const makeDefaultProps = () => ({ redirectTo: jest.fn() }); +const makeDefaultProps = (): DashboardUnsavedListingProps => ({ + redirectTo: jest.fn(), + unsavedDashboardIds: ['dashboardUnsavedOne', 'dashboardUnsavedTwo', 'dashboardUnsavedThree'], + refreshUnsavedDashboards: jest.fn(), +}); function mountWith({ services: incomingServices, props: incomingProps, }: { services?: DashboardAppServices; - props?: { redirectTo: DashboardRedirect }; + props?: DashboardUnsavedListingProps; }) { const services = incomingServices ?? makeDefaultServices(); const props = incomingProps ?? makeDefaultProps(); @@ -89,11 +88,9 @@ describe('Unsaved listing', () => { }); it('Does not attempt to get unsaved dashboard id', async () => { - const services = makeDefaultServices(); - services.dashboardPanelStorage.getDashboardIdsWithUnsavedChanges = jest - .fn() - .mockImplementation(() => ['dashboardUnsavedOne', DASHBOARD_PANELS_UNSAVED_ID]); - mountWith({ services }); + const props = makeDefaultProps(); + props.unsavedDashboardIds = ['dashboardUnsavedOne', DASHBOARD_PANELS_UNSAVED_ID]; + const { services } = mountWith({ props }); await waitFor(() => { expect(services.savedDashboards.get).toHaveBeenCalledTimes(1); }); @@ -115,11 +112,9 @@ describe('Unsaved listing', () => { }); it('Redirects to new dashboard when continue editing clicked', async () => { - const services = makeDefaultServices(); - services.dashboardPanelStorage.getDashboardIdsWithUnsavedChanges = jest - .fn() - .mockImplementation(() => [DASHBOARD_PANELS_UNSAVED_ID]); - const { props, component } = mountWith({ services }); + const props = makeDefaultProps(); + props.unsavedDashboardIds = [DASHBOARD_PANELS_UNSAVED_ID]; + const { component } = mountWith({ props }); const getEditButton = () => findTestSubject(component, `edit-unsaved-New-Dashboard`); await waitFor(() => { component.update(); @@ -150,4 +145,34 @@ describe('Unsaved listing', () => { ); }); }); + + it('removes unsaved changes from any dashboard which errors on fetch', async () => { + const services = makeDefaultServices(); + const props = makeDefaultProps(); + services.savedDashboards.get = jest.fn().mockImplementation((id: string) => { + if (id === 'failCase1' || id === 'failCase2') { + return Promise.reject(new Error()); + } + return Promise.resolve(mockedDashboards[id]); + }); + + props.unsavedDashboardIds = [ + 'dashboardUnsavedOne', + 'dashboardUnsavedTwo', + 'dashboardUnsavedThree', + 'failCase1', + 'failCase2', + ]; + const { component } = mountWith({ services, props }); + waitFor(() => { + component.update(); + expect(services.dashboardPanelStorage.clearPanels).toHaveBeenCalledWith('failCase1'); + expect(services.dashboardPanelStorage.clearPanels).toHaveBeenCalledWith('failCase2'); + + // clearing panels from dashboard with errors should cause getDashboardIdsWithUnsavedChanges to be called again. + expect( + services.dashboardPanelStorage.getDashboardIdsWithUnsavedChanges + ).toHaveBeenCalledTimes(2); + }); + }); }); diff --git a/src/plugins/dashboard/public/application/listing/dashboard_unsaved_listing.tsx b/src/plugins/dashboard/public/application/listing/dashboard_unsaved_listing.tsx index d7b9564d9d1e3..db50cfb638d64 100644 --- a/src/plugins/dashboard/public/application/listing/dashboard_unsaved_listing.tsx +++ b/src/plugins/dashboard/public/application/listing/dashboard_unsaved_listing.tsx @@ -106,7 +106,17 @@ interface UnsavedItemMap { [key: string]: DashboardSavedObject; } -export const DashboardUnsavedListing = ({ redirectTo }: { redirectTo: DashboardRedirect }) => { +export interface DashboardUnsavedListingProps { + refreshUnsavedDashboards: () => void; + redirectTo: DashboardRedirect; + unsavedDashboardIds: string[]; +} + +export const DashboardUnsavedListing = ({ + redirectTo, + unsavedDashboardIds, + refreshUnsavedDashboards, +}: DashboardUnsavedListingProps) => { const { services: { dashboardPanelStorage, @@ -116,9 +126,6 @@ export const DashboardUnsavedListing = ({ redirectTo }: { redirectTo: DashboardR } = useKibana(); const [items, setItems] = useState({}); - const [dashboardIds, setDashboardIds] = useState( - dashboardPanelStorage.getDashboardIdsWithUnsavedChanges() - ); const onOpen = useCallback( (id?: string) => { @@ -133,48 +140,63 @@ export const DashboardUnsavedListing = ({ redirectTo }: { redirectTo: DashboardR overlays, () => { dashboardPanelStorage.clearPanels(id); - setDashboardIds(dashboardPanelStorage.getDashboardIdsWithUnsavedChanges()); + refreshUnsavedDashboards(); }, createConfirmStrings.getCancelButtonText() ); }, - [overlays, dashboardPanelStorage] + [overlays, refreshUnsavedDashboards, dashboardPanelStorage] ); useEffect(() => { - if (dashboardIds?.length === 0) { + if (unsavedDashboardIds?.length === 0) { return; } let canceled = false; - const dashPromises = dashboardIds + const dashPromises = unsavedDashboardIds .filter((id) => id !== DASHBOARD_PANELS_UNSAVED_ID) - .map((dashboardId) => savedDashboards.get(dashboardId)); - Promise.all(dashPromises).then((dashboards: DashboardSavedObject[]) => { + .map((dashboardId) => { + return (savedDashboards.get(dashboardId) as Promise).catch( + () => dashboardId + ); + }); + Promise.all(dashPromises).then((dashboards: Array) => { const dashboardMap = {}; if (canceled) { return; } - setItems( - dashboards.reduce((map, dashboard) => { - return { - ...map, - [dashboard.id || DASHBOARD_PANELS_UNSAVED_ID]: dashboard, - }; - }, dashboardMap) - ); + let hasError = false; + const newItems = dashboards.reduce((map, dashboard) => { + if (typeof dashboard === 'string') { + hasError = true; + dashboardPanelStorage.clearPanels(dashboard); + return map; + } + return { + ...map, + [dashboard.id || DASHBOARD_PANELS_UNSAVED_ID]: dashboard, + }; + }, dashboardMap); + if (hasError) { + refreshUnsavedDashboards(); + return; + } + setItems(newItems); }); return () => { canceled = true; }; - }, [dashboardIds, savedDashboards]); + }, [savedDashboards, dashboardPanelStorage, refreshUnsavedDashboards, unsavedDashboardIds]); - return dashboardIds.length === 0 ? null : ( + return unsavedDashboardIds.length === 0 ? null : ( <> 1)} + title={dashboardUnsavedListingStrings.getUnsavedChangesTitle( + unsavedDashboardIds.length > 1 + )} > - {dashboardIds.map((dashboardId: string) => { + {unsavedDashboardIds.map((dashboardId: string) => { const title: string | undefined = dashboardId === DASHBOARD_PANELS_UNSAVED_ID ? getNewDashboardTitle() diff --git a/src/plugins/data/common/search/tabify/__snapshots__/tabify_docs.test.ts.snap b/src/plugins/data/common/search/tabify/__snapshots__/tabify_docs.test.ts.snap index 6cc191a67633c..22276335a0599 100644 --- a/src/plugins/data/common/search/tabify/__snapshots__/tabify_docs.test.ts.snap +++ b/src/plugins/data/common/search/tabify/__snapshots__/tabify_docs.test.ts.snap @@ -1,5 +1,113 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`tabifyDocs combines meta fields if meta option is set 1`] = ` +Object { + "columns": Array [ + Object { + "id": "fieldTest", + "meta": Object { + "field": "fieldTest", + "index": "test-index", + "params": Object { + "id": "number", + }, + "type": "number", + }, + "name": "fieldTest", + }, + Object { + "id": "invalidMapping", + "meta": Object { + "field": "invalidMapping", + "index": "test-index", + "params": undefined, + "type": "number", + }, + "name": "invalidMapping", + }, + Object { + "id": "nested", + "meta": Object { + "field": "nested", + "index": "test-index", + "params": undefined, + "type": "object", + }, + "name": "nested", + }, + Object { + "id": "sourceTest", + "meta": Object { + "field": "sourceTest", + "index": "test-index", + "params": Object { + "id": "number", + }, + "type": "number", + }, + "name": "sourceTest", + }, + Object { + "id": "_id", + "meta": Object { + "field": "_id", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_id", + }, + Object { + "id": "_index", + "meta": Object { + "field": "_index", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_index", + }, + Object { + "id": "_score", + "meta": Object { + "field": "_score", + "index": "test-index", + "params": undefined, + "type": "number", + }, + "name": "_score", + }, + Object { + "id": "_type", + "meta": Object { + "field": "_type", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_type", + }, + ], + "rows": Array [ + Object { + "_id": "hit-id-value", + "_index": "hit-index-value", + "_score": 77, + "_type": "hit-type-value", + "fieldTest": 123, + "invalidMapping": 345, + "nested": Array [ + Object { + "field": 123, + }, + ], + "sourceTest": 123, + }, + ], + "type": "datatable", +} +`; + exports[`tabifyDocs converts fields by default 1`] = ` Object { "columns": Array [ @@ -47,9 +155,53 @@ Object { }, "name": "sourceTest", }, + Object { + "id": "_id", + "meta": Object { + "field": "_id", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_id", + }, + Object { + "id": "_index", + "meta": Object { + "field": "_index", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_index", + }, + Object { + "id": "_score", + "meta": Object { + "field": "_score", + "index": "test-index", + "params": undefined, + "type": "number", + }, + "name": "_score", + }, + Object { + "id": "_type", + "meta": Object { + "field": "_type", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_type", + }, ], "rows": Array [ Object { + "_id": "hit-id-value", + "_index": "hit-index-value", + "_score": 77, + "_type": "hit-type-value", "fieldTest": 123, "invalidMapping": 345, "nested": Array [ @@ -111,9 +263,53 @@ Object { }, "name": "sourceTest", }, + Object { + "id": "_id", + "meta": Object { + "field": "_id", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_id", + }, + Object { + "id": "_index", + "meta": Object { + "field": "_index", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_index", + }, + Object { + "id": "_score", + "meta": Object { + "field": "_score", + "index": "test-index", + "params": undefined, + "type": "number", + }, + "name": "_score", + }, + Object { + "id": "_type", + "meta": Object { + "field": "_type", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_type", + }, ], "rows": Array [ Object { + "_id": "hit-id-value", + "_index": "hit-index-value", + "_score": 77, + "_type": "hit-type-value", "fieldTest": 123, "invalidMapping": 345, "nested": Array [ @@ -175,9 +371,53 @@ Object { }, "name": "sourceTest", }, + Object { + "id": "_id", + "meta": Object { + "field": "_id", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_id", + }, + Object { + "id": "_index", + "meta": Object { + "field": "_index", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_index", + }, + Object { + "id": "_score", + "meta": Object { + "field": "_score", + "index": "test-index", + "params": undefined, + "type": "number", + }, + "name": "_score", + }, + Object { + "id": "_type", + "meta": Object { + "field": "_type", + "index": "test-index", + "params": undefined, + "type": "string", + }, + "name": "_type", + }, ], "rows": Array [ Object { + "_id": "hit-id-value", + "_index": "hit-index-value", + "_score": 77, + "_type": "hit-type-value", "fieldTest": 123, "invalidMapping": 345, "nested": Array [ @@ -235,9 +475,53 @@ Object { }, "name": "sourceTest", }, + Object { + "id": "_id", + "meta": Object { + "field": "_id", + "index": undefined, + "params": undefined, + "type": "string", + }, + "name": "_id", + }, + Object { + "id": "_index", + "meta": Object { + "field": "_index", + "index": undefined, + "params": undefined, + "type": "string", + }, + "name": "_index", + }, + Object { + "id": "_score", + "meta": Object { + "field": "_score", + "index": undefined, + "params": undefined, + "type": "number", + }, + "name": "_score", + }, + Object { + "id": "_type", + "meta": Object { + "field": "_type", + "index": undefined, + "params": undefined, + "type": "string", + }, + "name": "_type", + }, ], "rows": Array [ Object { + "_id": "hit-id-value", + "_index": "hit-index-value", + "_score": 77, + "_type": "hit-type-value", "fieldTest": 123, "invalidMapping": 345, "nested": Array [ diff --git a/src/plugins/data/common/search/tabify/tabify_docs.test.ts b/src/plugins/data/common/search/tabify/tabify_docs.test.ts index c81e39f4c156a..52e12aeee1ae6 100644 --- a/src/plugins/data/common/search/tabify/tabify_docs.test.ts +++ b/src/plugins/data/common/search/tabify/tabify_docs.test.ts @@ -37,6 +37,10 @@ describe('tabifyDocs', () => { hits: { hits: [ { + _id: 'hit-id-value', + _index: 'hit-index-value', + _type: 'hit-type-value', + _score: 77, _source: { sourceTest: 123 }, fields: { fieldTest: 123, invalidMapping: 345, nested: [{ field: 123 }] }, }, @@ -59,6 +63,11 @@ describe('tabifyDocs', () => { expect(table).toMatchSnapshot(); }); + it('combines meta fields if meta option is set', () => { + const table = tabifyDocs(response, index, { meta: true }); + expect(table).toMatchSnapshot(); + }); + it('works without provided index pattern', () => { const table = tabifyDocs(response); expect(table).toMatchSnapshot(); diff --git a/src/plugins/data/common/search/tabify/tabify_docs.ts b/src/plugins/data/common/search/tabify/tabify_docs.ts index eaf43d9fd6ff6..b4806283e63f2 100644 --- a/src/plugins/data/common/search/tabify/tabify_docs.ts +++ b/src/plugins/data/common/search/tabify/tabify_docs.ts @@ -11,6 +11,12 @@ import { isPlainObject } from 'lodash'; import { IndexPattern } from '../../index_patterns/index_patterns'; import { Datatable, DatatableColumn, DatatableColumnType } from '../../../../expressions/common'; +export interface TabifyDocsOptions { + shallow?: boolean; + source?: boolean; + meta?: boolean; +} + export function flattenHit( hit: SearchResponse['hits']['hits'][0], indexPattern?: IndexPattern, @@ -56,12 +62,13 @@ export function flattenHit( if (params?.source !== false && hit._source) { flatten(hit._source as Record); } - return flat; -} + if (params?.meta !== false) { + // combine the fields that Discover allows to add as columns + const { _id, _index, _type, _score } = hit; + flatten({ _id, _index, _score, _type }); + } -export interface TabifyDocsOptions { - shallow?: boolean; - source?: boolean; + return flat; } export const tabifyDocs = ( diff --git a/test/scripts/jenkins_unit.sh b/test/scripts/jenkins_unit.sh index 6e28f9c3ef56a..9e387f97a016e 100755 --- a/test/scripts/jenkins_unit.sh +++ b/test/scripts/jenkins_unit.sh @@ -2,12 +2,6 @@ source test/scripts/jenkins_test_setup.sh -rename_coverage_file() { - test -f target/kibana-coverage/jest/coverage-final.json \ - && mv target/kibana-coverage/jest/coverage-final.json \ - target/kibana-coverage/jest/$1-coverage-final.json -} - if [[ -z "$CODE_COVERAGE" ]] ; then # Lint ./test/scripts/lint/eslint.sh @@ -34,13 +28,8 @@ if [[ -z "$CODE_COVERAGE" ]] ; then ./test/scripts/checks/test_hardening.sh else echo " -> Running jest tests with coverage" - node scripts/jest --ci --verbose --coverage --config jest.config.oss.js || true; - rename_coverage_file "oss" - echo "" - echo "" + node scripts/jest --ci --verbose --maxWorkers=6 --coverage || true; + echo " -> Running jest integration tests with coverage" - node --max-old-space-size=8192 scripts/jest_integration --ci --verbose --coverage || true; - rename_coverage_file "oss-integration" - echo "" - echo "" + node scripts/jest_integration --ci --verbose --coverage || true; fi diff --git a/test/scripts/jenkins_xpack.sh b/test/scripts/jenkins_xpack.sh deleted file mode 100755 index 66fb5ae5370bc..0000000000000 --- a/test/scripts/jenkins_xpack.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -source test/scripts/jenkins_test_setup.sh - -if [[ -z "$CODE_COVERAGE" ]] ; then - echo " -> Running jest tests" - - ./test/scripts/test/xpack_jest_unit.sh -else - echo " -> Build runtime for canvas" - # build runtime for canvas - echo "NODE_ENV=$NODE_ENV" - node ./x-pack/plugins/canvas/scripts/shareable_runtime - echo " -> Running jest tests with coverage" - cd x-pack - node --max-old-space-size=6144 scripts/jest --ci --verbose --maxWorkers=5 --coverage --config jest.config.js || true; - # rename file in order to be unique one - test -f ../target/kibana-coverage/jest/coverage-final.json \ - && mv ../target/kibana-coverage/jest/coverage-final.json \ - ../target/kibana-coverage/jest/xpack-coverage-final.json - echo "" - echo "" -fi diff --git a/test/scripts/test/jest_unit.sh b/test/scripts/test/jest_unit.sh index 88c0fe528b88c..1442a0f728727 100755 --- a/test/scripts/test/jest_unit.sh +++ b/test/scripts/test/jest_unit.sh @@ -2,5 +2,7 @@ source src/dev/ci_setup/setup_env.sh +export NODE_OPTIONS="--max-old-space-size=2048" + checks-reporter-with-killswitch "Jest Unit Tests" \ - node scripts/jest --config jest.config.oss.js --ci --verbose --maxWorkers=5 + node scripts/jest --ci --verbose --maxWorkers=8 diff --git a/test/scripts/test/xpack_jest_unit.sh b/test/scripts/test/xpack_jest_unit.sh deleted file mode 100755 index 33b1c8a2b5183..0000000000000 --- a/test/scripts/test/xpack_jest_unit.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -source src/dev/ci_setup/setup_env.sh - -checks-reporter-with-killswitch "X-Pack Jest" \ - node scripts/jest x-pack --ci --verbose --maxWorkers=5 diff --git a/tsconfig.refs.json b/tsconfig.refs.json index 17b1fc5dc1fe9..d5482a85856fe 100644 --- a/tsconfig.refs.json +++ b/tsconfig.refs.json @@ -55,5 +55,60 @@ { "path": "./src/plugins/visualizations/tsconfig.json" }, { "path": "./src/plugins/visualize/tsconfig.json" }, { "path": "./src/plugins/index_pattern_management/tsconfig.json" }, + { "path": "./x-pack/plugins/actions/tsconfig.json" }, + { "path": "./x-pack/plugins/alerts/tsconfig.json" }, + { "path": "./x-pack/plugins/beats_management/tsconfig.json" }, + { "path": "./x-pack/plugins/canvas/tsconfig.json" }, + { "path": "./x-pack/plugins/cloud/tsconfig.json" }, + { "path": "./x-pack/plugins/code/tsconfig.json" }, + { "path": "./x-pack/plugins/console_extensions/tsconfig.json" }, + { "path": "./x-pack/plugins/dashboard_enhanced/tsconfig.json" }, + { "path": "./x-pack/plugins/data_enhanced/tsconfig.json" }, + { "path": "./x-pack/plugins/dashboard_mode/tsconfig.json" }, + { "path": "./x-pack/plugins/discover_enhanced/tsconfig.json" }, + { "path": "./x-pack/plugins/embeddable_enhanced/tsconfig.json" }, + { "path": "./x-pack/plugins/encrypted_saved_objects/tsconfig.json" }, + { "path": "./x-pack/plugins/enterprise_search/tsconfig.json" }, + { "path": "./x-pack/plugins/event_log/tsconfig.json" }, + { "path": "./x-pack/plugins/features/tsconfig.json" }, + { "path": "./x-pack/plugins/file_upload/tsconfig.json" }, + { "path": "./x-pack/plugins/fleet/tsconfig.json" }, + { "path": "./x-pack/plugins/global_search_bar/tsconfig.json" }, + { "path": "./x-pack/plugins/global_search_providers/tsconfig.json" }, + { "path": "./x-pack/plugins/global_search/tsconfig.json" }, + { "path": "./x-pack/plugins/graph/tsconfig.json" }, + { "path": "./x-pack/plugins/grokdebugger/tsconfig.json" }, + { "path": "./x-pack/plugins/infra/tsconfig.json" }, + { "path": "./x-pack/plugins/ingest_pipelines/tsconfig.json" }, + { "path": "./x-pack/plugins/lens/tsconfig.json" }, + { "path": "./x-pack/plugins/license_management/tsconfig.json" }, + { "path": "./x-pack/plugins/licensing/tsconfig.json" }, + { "path": "./x-pack/plugins/maps_legacy_licensing/tsconfig.json" }, + { "path": "./x-pack/plugins/maps/tsconfig.json" }, + { "path": "./x-pack/plugins/ml/tsconfig.json" }, + { "path": "./x-pack/plugins/observability/tsconfig.json" }, + { "path": "./x-pack/plugins/painless_lab/tsconfig.json" }, + { "path": "./x-pack/plugins/reporting/tsconfig.json" }, + { "path": "./x-pack/plugins/saved_objects_tagging/tsconfig.json" }, + { "path": "./x-pack/plugins/searchprofiler/tsconfig.json" }, + { "path": "./x-pack/plugins/security/tsconfig.json" }, + { "path": "./x-pack/plugins/snapshot_restore/tsconfig.json" }, + { "path": "./x-pack/plugins/spaces/tsconfig.json" }, + { "path": "./x-pack/plugins/stack_alerts/tsconfig.json" }, + { "path": "./x-pack/plugins/task_manager/tsconfig.json" }, + { "path": "./x-pack/plugins/telemetry_collection_xpack/tsconfig.json" }, + { "path": "./x-pack/plugins/transform/tsconfig.json" }, + { "path": "./x-pack/plugins/translations/tsconfig.json" }, + { "path": "./x-pack/plugins/triggers_actions_ui/tsconfig.json" }, + { "path": "./x-pack/plugins/ui_actions_enhanced/tsconfig.json" }, + { "path": "./x-pack/plugins/upgrade_assistant/tsconfig.json" }, + { "path": "./x-pack/plugins/runtime_fields/tsconfig.json" }, + { "path": "./x-pack/plugins/index_management/tsconfig.json" }, + { "path": "./x-pack/plugins/watcher/tsconfig.json" }, + { "path": "./x-pack/plugins/rollup/tsconfig.json"}, + { "path": "./x-pack/plugins/remote_clusters/tsconfig.json"}, + { "path": "./x-pack/plugins/cross_cluster_replication/tsconfig.json"}, + { "path": "./x-pack/plugins/index_lifecycle_management/tsconfig.json"}, + { "path": "./x-pack/plugins/uptime/tsconfig.json" }, ] } diff --git a/vars/kibanaCoverage.groovy b/vars/kibanaCoverage.groovy index 609d8f78aeb96..e393f3a5d2150 100644 --- a/vars/kibanaCoverage.groovy +++ b/vars/kibanaCoverage.groovy @@ -197,13 +197,6 @@ def ingest(jobName, buildNumber, buildUrl, timestamp, previousSha, teamAssignmen def runTests() { parallel([ 'kibana-intake-agent': workers.intake('kibana-intake', './test/scripts/jenkins_unit.sh'), - 'x-pack-intake-agent': { - withEnv([ - 'NODE_ENV=test' // Needed for jest tests only - ]) { - workers.intake('x-pack-intake', './test/scripts/jenkins_xpack.sh')() - } - }, 'kibana-oss-agent' : workers.functional( 'kibana-oss-tests', { kibanaPipeline.buildOss() }, diff --git a/vars/kibanaPipeline.groovy b/vars/kibanaPipeline.groovy index 17349f6b566dc..5efcea3edb9bb 100644 --- a/vars/kibanaPipeline.groovy +++ b/vars/kibanaPipeline.groovy @@ -186,20 +186,21 @@ def uploadCoverageArtifacts(prefix, pattern) { def withGcsArtifactUpload(workerName, closure) { def uploadPrefix = "kibana-ci-artifacts/jobs/${env.JOB_NAME}/${BUILD_NUMBER}/${workerName}" def ARTIFACT_PATTERNS = [ + 'target/junit/**/*', 'target/kibana-*', - 'target/test-metrics/*', + 'target/kibana-coverage/**/*', 'target/kibana-security-solution/**/*.png', - 'target/junit/**/*', + 'target/test-metrics/*', 'target/test-suites-ci-plan.json', - 'test/**/screenshots/session/*.png', - 'test/**/screenshots/failure/*.png', 'test/**/screenshots/diff/*.png', + 'test/**/screenshots/failure/*.png', + 'test/**/screenshots/session/*.png', 'test/functional/failure_debug/html/*.html', - 'x-pack/test/**/screenshots/session/*.png', - 'x-pack/test/**/screenshots/failure/*.png', 'x-pack/test/**/screenshots/diff/*.png', - 'x-pack/test/functional/failure_debug/html/*.html', + 'x-pack/test/**/screenshots/failure/*.png', + 'x-pack/test/**/screenshots/session/*.png', 'x-pack/test/functional/apps/reporting/reports/session/*.pdf', + 'x-pack/test/functional/failure_debug/html/*.html', ] withEnv([ @@ -462,15 +463,10 @@ def allCiTasks() { } }, jest: { - workers.ci(name: 'jest', size: 'c2-8', ramDisk: true) { + workers.ci(name: 'jest', size: 'n2-standard-16', ramDisk: false) { scriptTask('Jest Unit Tests', 'test/scripts/test/jest_unit.sh')() } }, - xpackJest: { - workers.ci(name: 'xpack-jest', size: 'c2-8', ramDisk: true) { - scriptTask('X-Pack Jest Unit Tests', 'test/scripts/test/xpack_jest_unit.sh')() - } - }, ]) } diff --git a/vars/workers.groovy b/vars/workers.groovy index e1684f7aadb43..5d3328bc8a3c4 100644 --- a/vars/workers.groovy +++ b/vars/workers.groovy @@ -19,8 +19,8 @@ def label(size) { return 'docker && tests-xl-highmem' case 'xxl': return 'docker && tests-xxl && gobld/machineType:custom-64-270336' - case 'c2-8': - return 'docker && linux && immutable && gobld/machineType:c2-standard-8' + case 'n2-standard-16': + return 'docker && linux && immutable && gobld/machineType:n2-standard-16' } error "unknown size '${size}'" diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index f95c4286b3f26..c09198b3874a1 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -20,7 +20,7 @@ "xpack.endpoint": "plugins/endpoint", "xpack.enterpriseSearch": "plugins/enterprise_search", "xpack.features": "plugins/features", - "xpack.fileUpload": "plugins/maps_file_upload", + "xpack.fileUpload": "plugins/file_upload", "xpack.globalSearch": ["plugins/global_search"], "xpack.globalSearchBar": ["plugins/global_search_bar"], "xpack.graph": ["plugins/graph"], diff --git a/x-pack/jest.config.js b/x-pack/jest.config.js deleted file mode 100644 index 231004359632b..0000000000000 --- a/x-pack/jest.config.js +++ /dev/null @@ -1,12 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '..', - projects: ['/x-pack/plugins/*/jest.config.js'], -}; diff --git a/x-pack/plugins/actions/server/action_type_registry.test.ts b/x-pack/plugins/actions/server/action_type_registry.test.ts index 813e47c2e9957..c8972d8113f16 100644 --- a/x-pack/plugins/actions/server/action_type_registry.test.ts +++ b/x-pack/plugins/actions/server/action_type_registry.test.ts @@ -26,9 +26,7 @@ beforeEach(() => { actionTypeRegistryParams = { licensing: licensingMock.createSetup(), taskManager: mockTaskManager, - taskRunnerFactory: new TaskRunnerFactory( - new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false }) - ), + taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })), actionsConfigUtils: mockedActionsConfig, licenseState: mockedLicenseState, preconfiguredActions: [ diff --git a/x-pack/plugins/actions/server/actions_client.test.ts b/x-pack/plugins/actions/server/actions_client.test.ts index 1bea3e1fc356d..3bd8bb5f1ba52 100644 --- a/x-pack/plugins/actions/server/actions_client.test.ts +++ b/x-pack/plugins/actions/server/actions_client.test.ts @@ -59,9 +59,7 @@ beforeEach(() => { actionTypeRegistryParams = { licensing: licensingMock.createSetup(), taskManager: mockTaskManager, - taskRunnerFactory: new TaskRunnerFactory( - new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false }) - ), + taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })), actionsConfigUtils: actionsConfigMock.create(), licenseState: mockedLicenseState, preconfiguredActions: [], @@ -411,9 +409,7 @@ describe('create()', () => { const localActionTypeRegistryParams = { licensing: licensingMock.createSetup(), taskManager: mockTaskManager, - taskRunnerFactory: new TaskRunnerFactory( - new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false }) - ), + taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })), actionsConfigUtils: localConfigUtils, licenseState: licenseStateMock.create(), preconfiguredActions: [], diff --git a/x-pack/plugins/actions/server/builtin_action_types/index.test.ts b/x-pack/plugins/actions/server/builtin_action_types/index.test.ts index bad709247d080..10955af2f3b13 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/index.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/index.test.ts @@ -33,9 +33,7 @@ export function createActionTypeRegistry(): { const actionTypeRegistry = new ActionTypeRegistry({ taskManager: taskManagerMock.createSetup(), licensing: licensingMock.createSetup(), - taskRunnerFactory: new TaskRunnerFactory( - new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false }) - ), + taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })), actionsConfigUtils: actionsConfigMock.create(), licenseState: licenseStateMock.create(), preconfiguredActions: [], diff --git a/x-pack/plugins/actions/server/create_execute_function.test.ts b/x-pack/plugins/actions/server/create_execute_function.test.ts index aaf11669c1d03..d4100537fa6b8 100644 --- a/x-pack/plugins/actions/server/create_execute_function.test.ts +++ b/x-pack/plugins/actions/server/create_execute_function.test.ts @@ -28,7 +28,7 @@ describe('execute()', () => { const executeFn = createExecutionEnqueuerFunction({ taskManager: mockTaskManager, actionTypeRegistry, - isESOUsingEphemeralEncryptionKey: false, + isESOCanEncrypt: true, preconfiguredActions: [], }); savedObjectsClient.get.mockResolvedValueOnce({ @@ -87,7 +87,7 @@ describe('execute()', () => { const executeFn = createExecutionEnqueuerFunction({ taskManager: mockTaskManager, actionTypeRegistry: actionTypeRegistryMock.create(), - isESOUsingEphemeralEncryptionKey: false, + isESOCanEncrypt: true, preconfiguredActions: [ { id: '123', @@ -158,10 +158,10 @@ describe('execute()', () => { ); }); - test('throws when passing isESOUsingEphemeralEncryptionKey with true as a value', async () => { + test('throws when passing isESOCanEncrypt with false as a value', async () => { const executeFn = createExecutionEnqueuerFunction({ taskManager: mockTaskManager, - isESOUsingEphemeralEncryptionKey: true, + isESOCanEncrypt: false, actionTypeRegistry: actionTypeRegistryMock.create(), preconfiguredActions: [], }); @@ -173,7 +173,7 @@ describe('execute()', () => { apiKey: null, }) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unable to execute action because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` + `"Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` ); }); @@ -181,7 +181,7 @@ describe('execute()', () => { const mockedActionTypeRegistry = actionTypeRegistryMock.create(); const executeFn = createExecutionEnqueuerFunction({ taskManager: mockTaskManager, - isESOUsingEphemeralEncryptionKey: false, + isESOCanEncrypt: true, actionTypeRegistry: mockedActionTypeRegistry, preconfiguredActions: [], }); @@ -211,7 +211,7 @@ describe('execute()', () => { const mockedActionTypeRegistry = actionTypeRegistryMock.create(); const executeFn = createExecutionEnqueuerFunction({ taskManager: mockTaskManager, - isESOUsingEphemeralEncryptionKey: false, + isESOCanEncrypt: true, actionTypeRegistry: mockedActionTypeRegistry, preconfiguredActions: [ { diff --git a/x-pack/plugins/actions/server/create_execute_function.ts b/x-pack/plugins/actions/server/create_execute_function.ts index 0d75c0b410e44..025b4d3107798 100644 --- a/x-pack/plugins/actions/server/create_execute_function.ts +++ b/x-pack/plugins/actions/server/create_execute_function.ts @@ -14,7 +14,7 @@ import { isSavedObjectExecutionSource } from './lib'; interface CreateExecuteFunctionOptions { taskManager: TaskManagerStartContract; - isESOUsingEphemeralEncryptionKey: boolean; + isESOCanEncrypt: boolean; actionTypeRegistry: ActionTypeRegistryContract; preconfiguredActions: PreConfiguredAction[]; } @@ -33,16 +33,16 @@ export type ExecutionEnqueuer = ( export function createExecutionEnqueuerFunction({ taskManager, actionTypeRegistry, - isESOUsingEphemeralEncryptionKey, + isESOCanEncrypt, preconfiguredActions, }: CreateExecuteFunctionOptions) { return async function execute( unsecuredSavedObjectsClient: SavedObjectsClientContract, { id, params, spaceId, source, apiKey }: ExecuteOptions ) { - if (isESOUsingEphemeralEncryptionKey === true) { + if (!isESOCanEncrypt) { throw new Error( - `Unable to execute action because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` + `Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` ); } diff --git a/x-pack/plugins/actions/server/lib/action_executor.test.ts b/x-pack/plugins/actions/server/lib/action_executor.test.ts index e9b72f9bf0e4e..8ec94c4d4a552 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -17,7 +17,7 @@ import { ActionType } from '../types'; import { actionsMock, actionsClientMock } from '../mocks'; import { pick } from 'lodash'; -const actionExecutor = new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false }); +const actionExecutor = new ActionExecutor({ isESOCanEncrypt: true }); const services = actionsMock.createServices(); const actionsClient = actionsClientMock.create(); @@ -310,8 +310,8 @@ test('should not throws an error if actionType is preconfigured', async () => { }); }); -test('throws an error when passing isESOUsingEphemeralEncryptionKey with value of true', async () => { - const customActionExecutor = new ActionExecutor({ isESOUsingEphemeralEncryptionKey: true }); +test('throws an error when passing isESOCanEncrypt with value of false', async () => { + const customActionExecutor = new ActionExecutor({ isESOCanEncrypt: false }); customActionExecutor.initialize({ logger: loggingSystemMock.create().get(), spaces: spacesMock, @@ -325,7 +325,7 @@ test('throws an error when passing isESOUsingEphemeralEncryptionKey with value o await expect( customActionExecutor.execute(executeParams) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unable to execute action because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` + `"Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` ); }); diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 7a54f88e2f27c..6deaa4d587904 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -48,10 +48,10 @@ export type ActionExecutorContract = PublicMethodsOf; export class ActionExecutor { private isInitialized = false; private actionExecutorContext?: ActionExecutorContext; - private readonly isESOUsingEphemeralEncryptionKey: boolean; + private readonly isESOCanEncrypt: boolean; - constructor({ isESOUsingEphemeralEncryptionKey }: { isESOUsingEphemeralEncryptionKey: boolean }) { - this.isESOUsingEphemeralEncryptionKey = isESOUsingEphemeralEncryptionKey; + constructor({ isESOCanEncrypt }: { isESOCanEncrypt: boolean }) { + this.isESOCanEncrypt = isESOCanEncrypt; } public initialize(actionExecutorContext: ActionExecutorContext) { @@ -72,9 +72,9 @@ export class ActionExecutor { throw new Error('ActionExecutor not initialized'); } - if (this.isESOUsingEphemeralEncryptionKey === true) { + if (!this.isESOCanEncrypt) { throw new Error( - `Unable to execute action because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` + `Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` ); } diff --git a/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts index e42fc363f328b..9e101f2ee76b0 100644 --- a/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts +++ b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts @@ -84,18 +84,14 @@ beforeEach(() => { }); test(`throws an error if factory isn't initialized`, () => { - const factory = new TaskRunnerFactory( - new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false }) - ); + const factory = new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })); expect(() => factory.create({ taskInstance: mockedTaskInstance }) ).toThrowErrorMatchingInlineSnapshot(`"TaskRunnerFactory not initialized"`); }); test(`throws an error if factory is already initialized`, () => { - const factory = new TaskRunnerFactory( - new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false }) - ); + const factory = new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })); factory.initialize(taskRunnerFactoryInitializerParams); expect(() => factory.initialize(taskRunnerFactoryInitializerParams) diff --git a/x-pack/plugins/actions/server/plugin.test.ts b/x-pack/plugins/actions/server/plugin.test.ts index 187cba9d3240c..0e916220ca946 100644 --- a/x-pack/plugins/actions/server/plugin.test.ts +++ b/x-pack/plugins/actions/server/plugin.test.ts @@ -51,25 +51,21 @@ describe('Actions Plugin', () => { }; }); - it('should log warning when Encrypted Saved Objects plugin is using an ephemeral encryption key', async () => { - // coreMock.createSetup doesn't support Plugin generics - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await plugin.setup(coreSetup as any, pluginsSetup); - expect(pluginsSetup.encryptedSavedObjects.usingEphemeralEncryptionKey).toEqual(true); + it('should log warning when Encrypted Saved Objects plugin is missing encryption key', async () => { + await plugin.setup(coreSetup, pluginsSetup); + expect(pluginsSetup.encryptedSavedObjects.canEncrypt).toEqual(false); expect(context.logger.get().warn).toHaveBeenCalledWith( - 'APIs are disabled because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' + 'APIs are disabled because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' ); }); describe('routeHandlerContext.getActionsClient()', () => { - it('should not throw error when ESO plugin not using a generated key', async () => { - // coreMock.createSetup doesn't support Plugin generics - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await plugin.setup(coreSetup as any, { + it('should not throw error when ESO plugin has encryption key', async () => { + await plugin.setup(coreSetup, { ...pluginsSetup, encryptedSavedObjects: { ...pluginsSetup.encryptedSavedObjects, - usingEphemeralEncryptionKey: false, + canEncrypt: true, }, }); @@ -99,10 +95,8 @@ describe('Actions Plugin', () => { actionsContextHandler!.getActionsClient(); }); - it('should throw error when ESO plugin using a generated key', async () => { - // coreMock.createSetup doesn't support Plugin generics - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await plugin.setup(coreSetup as any, pluginsSetup); + it('should throw error when ESO plugin is missing encryption key', async () => { + await plugin.setup(coreSetup, pluginsSetup); expect(coreSetup.http.registerRouteHandlerContext).toHaveBeenCalledTimes(1); const handler = coreSetup.http.registerRouteHandlerContext.mock.calls[0] as [ @@ -123,7 +117,7 @@ describe('Actions Plugin', () => { httpServerMock.createResponseFactory() )) as unknown) as ActionsApiRequestHandlerContext; expect(() => actionsContextHandler!.getActionsClient()).toThrowErrorMatchingInlineSnapshot( - `"Unable to create actions client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` + `"Unable to create actions client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` ); }); }); @@ -234,14 +228,12 @@ describe('Actions Plugin', () => { expect(pluginStart.isActionExecutable('preconfiguredServerLog', '.server-log')).toBe(true); }); - it('should not throw error when ESO plugin not using a generated key', async () => { - // coreMock.createSetup doesn't support Plugin generics - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await plugin.setup(coreSetup as any, { + it('should not throw error when ESO plugin has encryption key', async () => { + await plugin.setup(coreSetup, { ...pluginsSetup, encryptedSavedObjects: { ...pluginsSetup.encryptedSavedObjects, - usingEphemeralEncryptionKey: false, + canEncrypt: true, }, }); const pluginStart = await plugin.start(coreStart, pluginsStart); @@ -249,17 +241,15 @@ describe('Actions Plugin', () => { await pluginStart.getActionsClientWithRequest(httpServerMock.createKibanaRequest()); }); - it('should throw error when ESO plugin using generated key', async () => { - // coreMock.createSetup doesn't support Plugin generics - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await plugin.setup(coreSetup as any, pluginsSetup); + it('should throw error when ESO plugin is missing encryption key', async () => { + await plugin.setup(coreSetup, pluginsSetup); const pluginStart = await plugin.start(coreStart, pluginsStart); - expect(pluginsSetup.encryptedSavedObjects.usingEphemeralEncryptionKey).toEqual(true); + expect(pluginsSetup.encryptedSavedObjects.canEncrypt).toEqual(false); await expect( pluginStart.getActionsClientWithRequest(httpServerMock.createKibanaRequest()) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unable to create actions client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` + `"Unable to create actions client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` ); }); }); diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 8fbacc71d30cb..c4159c80e806f 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -144,7 +144,7 @@ export class ActionsPlugin implements Plugin ) => { - if (isESOUsingEphemeralEncryptionKey === true) { + if (isESOCanEncrypt !== true) { throw new Error( - `Unable to create actions client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` + `Unable to create actions client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` ); } @@ -314,7 +313,7 @@ export class ActionsPlugin implements Plugin => { const { actionTypeRegistry, - isESOUsingEphemeralEncryptionKey, + isESOCanEncrypt, preconfiguredActions, actionExecutor, instantiateAuthorization, @@ -448,9 +447,9 @@ export class ActionsPlugin implements Plugin { - if (isESOUsingEphemeralEncryptionKey === true) { + if (isESOCanEncrypt !== true) { throw new Error( - `Unable to create actions client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` + `Unable to create actions client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` ); } return new ActionsClient({ @@ -468,7 +467,7 @@ export class ActionsPlugin implements Plugin { let coreSetup: ReturnType; let pluginsSetup: jest.Mocked; - it('should log warning when Encrypted Saved Objects plugin is using an ephemeral encryption key', async () => { + it('should log warning when Encrypted Saved Objects plugin is missing encryption key', async () => { const context = coreMock.createPluginInitializerContext({ healthCheck: { interval: '5m', @@ -40,7 +40,7 @@ describe('Alerting Plugin', () => { const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup(); const setupMocks = coreMock.createSetup(); - // need await to test number of calls of setupMocks.status.set, becuase it is under async function which awaiting core.getStartServices() + // need await to test number of calls of setupMocks.status.set, because it is under async function which awaiting core.getStartServices() await plugin.setup(setupMocks, { licensing: licensingMock.createSetup(), encryptedSavedObjects: encryptedSavedObjectsSetup, @@ -51,9 +51,9 @@ describe('Alerting Plugin', () => { }); expect(setupMocks.status.set).toHaveBeenCalledTimes(1); - expect(encryptedSavedObjectsSetup.usingEphemeralEncryptionKey).toEqual(true); + expect(encryptedSavedObjectsSetup.canEncrypt).toEqual(false); expect(context.logger.get().warn).toHaveBeenCalledWith( - 'APIs are disabled because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' + 'APIs are disabled because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' ); }); @@ -110,7 +110,7 @@ describe('Alerting Plugin', () => { describe('start()', () => { describe('getAlertsClientWithRequest()', () => { - it('throws error when encryptedSavedObjects plugin has usingEphemeralEncryptionKey set to true', async () => { + it('throws error when encryptedSavedObjects plugin is missing encryption key', async () => { const context = coreMock.createPluginInitializerContext({ healthCheck: { interval: '5m', @@ -141,15 +141,15 @@ describe('Alerting Plugin', () => { taskManager: taskManagerMock.createStart(), }); - expect(encryptedSavedObjectsSetup.usingEphemeralEncryptionKey).toEqual(true); + expect(encryptedSavedObjectsSetup.canEncrypt).toEqual(false); expect(() => startContract.getAlertsClientWithRequest({} as KibanaRequest) ).toThrowErrorMatchingInlineSnapshot( - `"Unable to create alerts client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` + `"Unable to create alerts client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` ); }); - it(`doesn't throw error when encryptedSavedObjects plugin has usingEphemeralEncryptionKey set to false`, async () => { + it(`doesn't throw error when encryptedSavedObjects plugin has encryption key`, async () => { const context = coreMock.createPluginInitializerContext({ healthCheck: { interval: '5m', @@ -163,7 +163,7 @@ describe('Alerting Plugin', () => { const encryptedSavedObjectsSetup = { ...encryptedSavedObjectsMock.createSetup(), - usingEphemeralEncryptionKey: false, + canEncrypt: true, }; plugin.setup(coreMock.createSetup(), { licensing: licensingMock.createSetup(), diff --git a/x-pack/plugins/alerts/server/plugin.ts b/x-pack/plugins/alerts/server/plugin.ts index aaec0bb8a080d..8dba4453d5682 100644 --- a/x-pack/plugins/alerts/server/plugin.ts +++ b/x-pack/plugins/alerts/server/plugin.ts @@ -153,7 +153,7 @@ export class AlertingPlugin { private alertTypeRegistry?: AlertTypeRegistry; private readonly taskRunnerFactory: TaskRunnerFactory; private licenseState: ILicenseState | null = null; - private isESOUsingEphemeralEncryptionKey?: boolean; + private isESOCanEncrypt?: boolean; private security?: SecurityPluginSetup; private readonly alertsClientFactory: AlertsClientFactory; private readonly telemetryLogger: Logger; @@ -189,12 +189,11 @@ export class AlertingPlugin { }; }); - this.isESOUsingEphemeralEncryptionKey = - plugins.encryptedSavedObjects.usingEphemeralEncryptionKey; + this.isESOCanEncrypt = plugins.encryptedSavedObjects.canEncrypt; - if (this.isESOUsingEphemeralEncryptionKey) { + if (!this.isESOCanEncrypt) { this.logger.warn( - 'APIs are disabled because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' + 'APIs are disabled because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' ); } @@ -311,7 +310,7 @@ export class AlertingPlugin { public start(core: CoreStart, plugins: AlertingPluginsStart): PluginStartContract { const { - isESOUsingEphemeralEncryptionKey, + isESOCanEncrypt, logger, taskRunnerFactory, alertTypeRegistry, @@ -353,9 +352,9 @@ export class AlertingPlugin { }); const getAlertsClientWithRequest = (request: KibanaRequest) => { - if (isESOUsingEphemeralEncryptionKey === true) { + if (isESOCanEncrypt !== true) { throw new Error( - `Unable to create alerts client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` + `Unable to create alerts client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` ); } return alertsClientFactory!.create(request, core.savedObjects); diff --git a/x-pack/plugins/alerts/server/routes/health.test.ts b/x-pack/plugins/alerts/server/routes/health.test.ts index 38bae896e40ba..22df0e6a00046 100644 --- a/x-pack/plugins/alerts/server/routes/health.test.ts +++ b/x-pack/plugins/alerts/server/routes/health.test.ts @@ -47,8 +47,7 @@ describe('healthRoute', () => { const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup(); - encryptedSavedObjects.usingEphemeralEncryptionKey = false; + const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); healthRoute(router, licenseState, encryptedSavedObjects); const [config] = router.get.mock.calls[0]; @@ -60,8 +59,7 @@ describe('healthRoute', () => { const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup(); - encryptedSavedObjects.usingEphemeralEncryptionKey = false; + const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); healthRoute(router, licenseState, encryptedSavedObjects); const [, handler] = router.get.mock.calls[0]; @@ -85,12 +83,11 @@ describe('healthRoute', () => { `); }); - it('evaluates whether Encrypted Saved Objects is using an ephemeral encryption key', async () => { + it('evaluates whether Encrypted Saved Objects is missing encryption key', async () => { const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup(); - encryptedSavedObjects.usingEphemeralEncryptionKey = true; + const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: false }); healthRoute(router, licenseState, encryptedSavedObjects); const [, handler] = router.get.mock.calls[0]; @@ -129,8 +126,7 @@ describe('healthRoute', () => { const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup(); - encryptedSavedObjects.usingEphemeralEncryptionKey = false; + const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); healthRoute(router, licenseState, encryptedSavedObjects); const [, handler] = router.get.mock.calls[0]; @@ -169,8 +165,7 @@ describe('healthRoute', () => { const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup(); - encryptedSavedObjects.usingEphemeralEncryptionKey = false; + const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); healthRoute(router, licenseState, encryptedSavedObjects); const [, handler] = router.get.mock.calls[0]; @@ -209,8 +204,7 @@ describe('healthRoute', () => { const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup(); - encryptedSavedObjects.usingEphemeralEncryptionKey = false; + const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); healthRoute(router, licenseState, encryptedSavedObjects); const [, handler] = router.get.mock.calls[0]; @@ -249,8 +243,7 @@ describe('healthRoute', () => { const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup(); - encryptedSavedObjects.usingEphemeralEncryptionKey = false; + const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); healthRoute(router, licenseState, encryptedSavedObjects); const [, handler] = router.get.mock.calls[0]; @@ -291,8 +284,7 @@ describe('healthRoute', () => { const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup(); - encryptedSavedObjects.usingEphemeralEncryptionKey = false; + const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); healthRoute(router, licenseState, encryptedSavedObjects); const [, handler] = router.get.mock.calls[0]; diff --git a/x-pack/plugins/alerts/server/routes/health.ts b/x-pack/plugins/alerts/server/routes/health.ts index 24b3642ca2085..9e1f01041e091 100644 --- a/x-pack/plugins/alerts/server/routes/health.ts +++ b/x-pack/plugins/alerts/server/routes/health.ts @@ -55,7 +55,7 @@ export function healthRoute( const frameworkHealth: AlertingFrameworkHealth = { isSufficientlySecure: !isSecurityEnabled || (isSecurityEnabled && isTLSEnabled), - hasPermanentEncryptionKey: !encryptedSavedObjects.usingEphemeralEncryptionKey, + hasPermanentEncryptionKey: encryptedSavedObjects.canEncrypt, alertingFrameworkHeath, }; diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index f585515f79b0c..a1b3af6a9f943 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -162,7 +162,24 @@ export class ApmPlugin implements Plugin { order: 8500, euiIconType: 'logoObservability', category: DEFAULT_APP_CATEGORIES.observability, - + meta: { + keywords: [ + 'RUM', + 'Real User Monitoring', + 'DEM', + 'Digital Experience Monitoring', + 'EUM', + 'End User Monitoring', + 'UX', + 'Javascript', + 'APM', + 'Mobile', + 'digital', + 'performance', + 'web performance', + 'web perf', + ], + }, async mount(params: AppMountParameters) { // Load application bundle and Get start service const [{ renderApp }, [coreStart, corePlugins]] = await Promise.all([ diff --git a/x-pack/plugins/beats_management/public/application.tsx b/x-pack/plugins/beats_management/public/application.tsx index 6e81809b9c493..5a9b0a768856e 100644 --- a/x-pack/plugins/beats_management/public/application.tsx +++ b/x-pack/plugins/beats_management/public/application.tsx @@ -7,11 +7,13 @@ import * as euiVars from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; import ReactDOM from 'react-dom'; import { Router } from 'react-router-dom'; import { ThemeProvider } from 'styled-components'; import { Provider as UnstatedProvider, Subscribe } from 'unstated'; +import { EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui'; import { Background } from './components/layouts/background'; import { BreadcrumbProvider } from './components/navigation/breadcrumb'; import { Breadcrumb } from './components/navigation/breadcrumb/breadcrumb'; @@ -37,6 +39,38 @@ export const renderApp = ({ element, history }: ManagementAppMountParams, libs: defaultMessage: 'Management', })} /> + +

+ + + + ), + }} + /> +

+
+ )} diff --git a/x-pack/plugins/cross_cluster_replication/tsconfig.json b/x-pack/plugins/cross_cluster_replication/tsconfig.json new file mode 100644 index 0000000000000..9c7590b9c2553 --- /dev/null +++ b/x-pack/plugins/cross_cluster_replication/tsconfig.json @@ -0,0 +1,31 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*", + ], + "references": [ + { "path": "../../../src/core/tsconfig.json" }, + // required plugins + { "path": "../../../src/plugins/home/tsconfig.json" }, + { "path": "../licensing/tsconfig.json" }, + { "path": "../../../src/plugins/management/tsconfig.json" }, + { "path": "../remote_clusters/tsconfig.json" }, + { "path": "../index_management/tsconfig.json" }, + { "path": "../features/tsconfig.json" }, + // optional plugins + { "path": "../../../src/plugins/usage_collection/tsconfig.json" }, + // required bundles + { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, + { "path": "../../../src/plugins/es_ui_shared/tsconfig.json" }, + { "path": "../../../src/plugins/data/tsconfig.json" }, + ] +} diff --git a/x-pack/plugins/encrypted_saved_objects/server/config.test.ts b/x-pack/plugins/encrypted_saved_objects/server/config.test.ts index 3633dae824a2b..1cc5f7974cb13 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/config.test.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/config.test.ts @@ -5,10 +5,7 @@ * 2.0. */ -jest.mock('crypto', () => ({ randomBytes: jest.fn() })); - -import { loggingSystemMock } from 'src/core/server/mocks'; -import { createConfig, ConfigSchema } from './config'; +import { ConfigSchema } from './config'; describe('config schema', () => { it('generates proper defaults', () => { @@ -32,6 +29,17 @@ describe('config schema', () => { } `); + expect(ConfigSchema.validate({ encryptionKey: 'z'.repeat(32) }, { dist: true })) + .toMatchInlineSnapshot(` + Object { + "enabled": true, + "encryptionKey": "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", + "keyRotation": Object { + "decryptionOnlyKeys": Array [], + }, + } + `); + expect(ConfigSchema.validate({}, { dist: true })).toMatchInlineSnapshot(` Object { "enabled": true, @@ -79,6 +87,18 @@ describe('config schema', () => { ); }); + it('should not allow `null` value for the encryption key', () => { + expect(() => ConfigSchema.validate({ encryptionKey: null })).toThrowErrorMatchingInlineSnapshot( + `"[encryptionKey]: expected value of type [string] but got [null]"` + ); + + expect(() => + ConfigSchema.validate({ encryptionKey: null }, { dist: true }) + ).toThrowErrorMatchingInlineSnapshot( + `"[encryptionKey]: expected value of type [string] but got [null]"` + ); + }); + it('should throw error if any of the xpack.encryptedSavedObjects.keyRotation.decryptionOnlyKeys is less than 32 characters', () => { expect(() => ConfigSchema.validate({ @@ -121,43 +141,3 @@ describe('config schema', () => { ); }); }); - -describe('createConfig()', () => { - it('should log a warning, set xpack.encryptedSavedObjects.encryptionKey and usingEphemeralEncryptionKey=true when encryptionKey is not set', () => { - const mockRandomBytes = jest.requireMock('crypto').randomBytes; - mockRandomBytes.mockReturnValue('ab'.repeat(16)); - - const logger = loggingSystemMock.create().get(); - const config = createConfig(ConfigSchema.validate({}, { dist: true }), logger); - expect(config).toEqual({ - enabled: true, - encryptionKey: 'ab'.repeat(16), - keyRotation: { decryptionOnlyKeys: [] }, - usingEphemeralEncryptionKey: true, - }); - - expect(loggingSystemMock.collect(logger).warn).toMatchInlineSnapshot(` - Array [ - Array [ - "Generating a random key for xpack.encryptedSavedObjects.encryptionKey. To decrypt encrypted saved objects attributes after restart, please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.", - ], - ] - `); - }); - - it('should not log a warning and set usingEphemeralEncryptionKey=false when encryptionKey is set', async () => { - const logger = loggingSystemMock.create().get(); - const config = createConfig( - ConfigSchema.validate({ encryptionKey: 'supersecret'.repeat(3) }, { dist: true }), - logger - ); - expect(config).toEqual({ - enabled: true, - encryptionKey: 'supersecret'.repeat(3), - keyRotation: { decryptionOnlyKeys: [] }, - usingEphemeralEncryptionKey: false, - }); - - expect(loggingSystemMock.collect(logger).warn).toEqual([]); - }); -}); diff --git a/x-pack/plugins/encrypted_saved_objects/server/config.ts b/x-pack/plugins/encrypted_saved_objects/server/config.ts index 40db0187162d0..2bcf0e9b69511 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/config.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/config.ts @@ -5,11 +5,9 @@ * 2.0. */ -import crypto from 'crypto'; import { schema, TypeOf } from '@kbn/config-schema'; -import { Logger } from 'src/core/server'; -export type ConfigType = ReturnType; +export type ConfigType = TypeOf; export const ConfigSchema = schema.object( { @@ -33,23 +31,3 @@ export const ConfigSchema = schema.object( }, } ); - -export function createConfig(config: TypeOf, logger: Logger) { - let encryptionKey = config.encryptionKey; - const usingEphemeralEncryptionKey = encryptionKey === undefined; - if (encryptionKey === undefined) { - logger.warn( - 'Generating a random key for xpack.encryptedSavedObjects.encryptionKey. ' + - 'To decrypt encrypted saved objects attributes after restart, ' + - 'please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' - ); - - encryptionKey = crypto.randomBytes(16).toString('hex'); - } - - return { - ...config, - encryptionKey, - usingEphemeralEncryptionKey, - }; -} diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts index 1760a85806786..f70810943d179 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts @@ -226,6 +226,72 @@ describe('#stripOrDecryptAttributes', () => { ); }); }); + + describe('without encryption key', () => { + beforeEach(() => { + service = new EncryptedSavedObjectsService({ + logger: loggingSystemMock.create().get(), + audit: mockAuditLogger, + }); + }); + + it('does not fail if none of attributes are supposed to be encrypted', async () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + + service.registerType({ type: 'known-type-1', attributesToEncrypt: new Set(['attrFour']) }); + + await expect( + service.stripOrDecryptAttributes({ id: 'known-id', type: 'known-type-1' }, attributes) + ).resolves.toEqual({ attributes: { attrOne: 'one', attrTwo: 'two', attrThree: 'three' } }); + }); + + it('does not fail if there are attributes are supposed to be encrypted, but should be stripped', async () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + + service.registerType({ + type: 'known-type-1', + attributesToEncrypt: new Set(['attrOne', 'attrThree']), + }); + + await expect( + service.stripOrDecryptAttributes({ id: 'known-id', type: 'known-type-1' }, attributes) + ).resolves.toEqual({ attributes: { attrTwo: 'two' } }); + }); + + it('fails if needs to decrypt any attribute', async () => { + service.registerType({ + type: 'known-type-1', + attributesToEncrypt: new Set([ + 'attrOne', + { key: 'attrThree', dangerouslyExposeValue: true }, + ]), + }); + + const mockUser = mockAuthenticatedUser(); + const { attributes, error } = await service.stripOrDecryptAttributes( + { type: 'known-type-1', id: 'object-id' }, + { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }, + undefined, + { user: mockUser } + ); + + expect(attributes).toEqual({ attrTwo: 'two' }); + + const encryptionError = error as EncryptionError; + expect(encryptionError.attributeName).toBe('attrThree'); + expect(encryptionError.message).toBe('Unable to decrypt attribute "attrThree"'); + expect(encryptionError.cause).toEqual( + new Error('Decryption is disabled because of missing decryption keys.') + ); + + expect(mockAuditLogger.decryptAttributeFailure).toHaveBeenCalledTimes(1); + expect(mockAuditLogger.decryptAttributeFailure).toHaveBeenCalledWith( + 'attrThree', + { type: 'known-type-1', id: 'object-id' }, + mockUser + ); + }); + }); }); describe('#encryptAttributes', () => { @@ -465,6 +531,58 @@ describe('#encryptAttributes', () => { mockUser ); }); + + describe('without encryption key', () => { + beforeEach(() => { + service = new EncryptedSavedObjectsService({ + logger: loggingSystemMock.create().get(), + audit: mockAuditLogger, + }); + }); + + it('does not fail if none of attributes are supposed to be encrypted', async () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + + service.registerType({ type: 'known-type-1', attributesToEncrypt: new Set(['attrFour']) }); + + await expect( + service.encryptAttributes({ type: 'known-type-1', id: 'object-id' }, attributes) + ).resolves.toEqual({ + attrOne: 'one', + attrTwo: 'two', + attrThree: 'three', + }); + expect(mockAuditLogger.encryptAttributesSuccess).not.toHaveBeenCalled(); + }); + + it('fails if needs to encrypt any attribute', async () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + service.registerType({ + type: 'known-type-1', + attributesToEncrypt: new Set(['attrOne', 'attrThree']), + }); + + const mockUser = mockAuthenticatedUser(); + await expect( + service.encryptAttributes({ type: 'known-type-1', id: 'object-id' }, attributes, { + user: mockUser, + }) + ).rejects.toThrowError(EncryptionError); + + expect(attributes).toEqual({ + attrOne: 'one', + attrTwo: 'two', + attrThree: 'three', + }); + expect(mockAuditLogger.encryptAttributesSuccess).not.toHaveBeenCalled(); + expect(mockAuditLogger.encryptAttributeFailure).toHaveBeenCalledTimes(1); + expect(mockAuditLogger.encryptAttributeFailure).toHaveBeenCalledWith( + 'attrOne', + { type: 'known-type-1', id: 'object-id' }, + mockUser + ); + }); + }); }); describe('#decryptAttributes', () => { @@ -1099,6 +1217,88 @@ describe('#decryptAttributes', () => { expect(decryptionOnlyCryptoTwo.decrypt).not.toHaveBeenCalled(); }); }); + + describe('without encryption key', () => { + beforeEach(() => { + service = new EncryptedSavedObjectsService({ + logger: loggingSystemMock.create().get(), + audit: mockAuditLogger, + }); + }); + + it('does not fail if none of attributes are supposed to be decrypted', async () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + + service = new EncryptedSavedObjectsService({ + decryptionOnlyCryptos: [], + logger: loggingSystemMock.create().get(), + audit: mockAuditLogger, + }); + service.registerType({ type: 'known-type-1', attributesToEncrypt: new Set(['attrFour']) }); + + await expect( + service.decryptAttributes({ type: 'known-type-1', id: 'object-id' }, attributes) + ).resolves.toEqual({ + attrOne: 'one', + attrTwo: 'two', + attrThree: 'three', + }); + expect(mockAuditLogger.decryptAttributesSuccess).not.toHaveBeenCalled(); + }); + + it('does not fail if can decrypt attributes with decryption only keys', async () => { + const decryptionOnlyCryptoOne = createNodeCryptMock('old-key-one'); + decryptionOnlyCryptoOne.decrypt.mockImplementation( + async (encryptedOutput: string | Buffer, aad?: string) => `${encryptedOutput}||${aad}` + ); + + service = new EncryptedSavedObjectsService({ + decryptionOnlyCryptos: [decryptionOnlyCryptoOne], + logger: loggingSystemMock.create().get(), + audit: mockAuditLogger, + }); + service.registerType({ + type: 'known-type-1', + attributesToEncrypt: new Set(['attrOne', 'attrThree', 'attrFour']), + }); + + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three', attrFour: null }; + await expect( + service.decryptAttributes({ type: 'known-type-1', id: 'object-id' }, attributes) + ).resolves.toEqual({ + attrOne: 'one||["known-type-1","object-id",{"attrTwo":"two"}]', + attrTwo: 'two', + attrThree: 'three||["known-type-1","object-id",{"attrTwo":"two"}]', + attrFour: null, + }); + expect(mockAuditLogger.decryptAttributesSuccess).toHaveBeenCalledTimes(1); + expect(mockAuditLogger.decryptAttributesSuccess).toHaveBeenCalledWith( + ['attrOne', 'attrThree'], + { type: 'known-type-1', id: 'object-id' }, + undefined + ); + }); + + it('fails if needs to decrypt any attribute', async () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + + service.registerType({ type: 'known-type-1', attributesToEncrypt: new Set(['attrOne']) }); + + const mockUser = mockAuthenticatedUser(); + await expect( + service.decryptAttributes({ type: 'known-type-1', id: 'object-id' }, attributes, { + user: mockUser, + }) + ).rejects.toThrowError(EncryptionError); + + expect(mockAuditLogger.decryptAttributesSuccess).not.toHaveBeenCalled(); + expect(mockAuditLogger.decryptAttributeFailure).toHaveBeenCalledWith( + 'attrOne', + { type: 'known-type-1', id: 'object-id' }, + mockUser + ); + }); + }); }); describe('#encryptAttributesSync', () => { @@ -1283,6 +1483,58 @@ describe('#encryptAttributesSync', () => { attrThree: 'three', }); }); + + describe('without encryption key', () => { + beforeEach(() => { + service = new EncryptedSavedObjectsService({ + logger: loggingSystemMock.create().get(), + audit: mockAuditLogger, + }); + }); + + it('does not fail if none of attributes are supposed to be encrypted', () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + + service.registerType({ type: 'known-type-1', attributesToEncrypt: new Set(['attrFour']) }); + + expect( + service.encryptAttributesSync({ type: 'known-type-1', id: 'object-id' }, attributes) + ).toEqual({ + attrOne: 'one', + attrTwo: 'two', + attrThree: 'three', + }); + expect(mockAuditLogger.encryptAttributesSuccess).not.toHaveBeenCalled(); + }); + + it('fails if needs to encrypt any attribute', () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + service.registerType({ + type: 'known-type-1', + attributesToEncrypt: new Set(['attrOne', 'attrThree']), + }); + + const mockUser = mockAuthenticatedUser(); + expect(() => + service.encryptAttributesSync({ type: 'known-type-1', id: 'object-id' }, attributes, { + user: mockUser, + }) + ).toThrowError(EncryptionError); + + expect(attributes).toEqual({ + attrOne: 'one', + attrTwo: 'two', + attrThree: 'three', + }); + expect(mockAuditLogger.encryptAttributesSuccess).not.toHaveBeenCalled(); + expect(mockAuditLogger.encryptAttributeFailure).toHaveBeenCalledTimes(1); + expect(mockAuditLogger.encryptAttributeFailure).toHaveBeenCalledWith( + 'attrOne', + { type: 'known-type-1', id: 'object-id' }, + mockUser + ); + }); + }); }); describe('#decryptAttributesSync', () => { @@ -1784,4 +2036,86 @@ describe('#decryptAttributesSync', () => { expect(decryptionOnlyCryptoTwo.decryptSync).not.toHaveBeenCalled(); }); }); + + describe('without encryption key', () => { + beforeEach(() => { + service = new EncryptedSavedObjectsService({ + logger: loggingSystemMock.create().get(), + audit: mockAuditLogger, + }); + }); + + it('does not fail if none of attributes are supposed to be decrypted', () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + + service = new EncryptedSavedObjectsService({ + decryptionOnlyCryptos: [], + logger: loggingSystemMock.create().get(), + audit: mockAuditLogger, + }); + service.registerType({ type: 'known-type-1', attributesToEncrypt: new Set(['attrFour']) }); + + expect( + service.decryptAttributesSync({ type: 'known-type-1', id: 'object-id' }, attributes) + ).toEqual({ + attrOne: 'one', + attrTwo: 'two', + attrThree: 'three', + }); + expect(mockAuditLogger.decryptAttributesSuccess).not.toHaveBeenCalled(); + }); + + it('does not fail if can decrypt attributes with decryption only keys', () => { + const decryptionOnlyCryptoOne = createNodeCryptMock('old-key-one'); + decryptionOnlyCryptoOne.decryptSync.mockImplementation( + (encryptedOutput: string | Buffer, aad?: string) => `${encryptedOutput}||${aad}` + ); + + service = new EncryptedSavedObjectsService({ + decryptionOnlyCryptos: [decryptionOnlyCryptoOne], + logger: loggingSystemMock.create().get(), + audit: mockAuditLogger, + }); + service.registerType({ + type: 'known-type-1', + attributesToEncrypt: new Set(['attrOne', 'attrThree', 'attrFour']), + }); + + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three', attrFour: null }; + expect( + service.decryptAttributesSync({ type: 'known-type-1', id: 'object-id' }, attributes) + ).toEqual({ + attrOne: 'one||["known-type-1","object-id",{"attrTwo":"two"}]', + attrTwo: 'two', + attrThree: 'three||["known-type-1","object-id",{"attrTwo":"two"}]', + attrFour: null, + }); + expect(mockAuditLogger.decryptAttributesSuccess).toHaveBeenCalledTimes(1); + expect(mockAuditLogger.decryptAttributesSuccess).toHaveBeenCalledWith( + ['attrOne', 'attrThree'], + { type: 'known-type-1', id: 'object-id' }, + undefined + ); + }); + + it('fails if needs to decrypt any attribute', () => { + const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' }; + + service.registerType({ type: 'known-type-1', attributesToEncrypt: new Set(['attrOne']) }); + + const mockUser = mockAuthenticatedUser(); + expect(() => + service.decryptAttributesSync({ type: 'known-type-1', id: 'object-id' }, attributes, { + user: mockUser, + }) + ).toThrowError(EncryptionError); + + expect(mockAuditLogger.decryptAttributesSuccess).not.toHaveBeenCalled(); + expect(mockAuditLogger.decryptAttributeFailure).toHaveBeenCalledWith( + 'attrOne', + { type: 'known-type-1', id: 'object-id' }, + mockUser + ); + }); + }); }); diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts index 91a3cfc921624..23aef07ff8781 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts @@ -77,7 +77,7 @@ interface EncryptedSavedObjectsServiceOptions { /** * NodeCrypto instance used for both encryption and decryption. */ - primaryCrypto: Crypto; + primaryCrypto?: Crypto; /** * NodeCrypto instances used ONLY for decryption (i.e. rotated encryption keys). @@ -293,12 +293,17 @@ export class EncryptedSavedObjectsService { let iteratorResult = iterator.next(); while (!iteratorResult.done) { const [attributeValue, encryptionAAD] = iteratorResult.value; - try { - iteratorResult = iterator.next( - await this.options.primaryCrypto.encrypt(attributeValue, encryptionAAD) - ); - } catch (err) { - iterator.throw!(err); + // We check this inside of the iterator to throw only if we do need to encrypt anything. + if (this.options.primaryCrypto) { + try { + iteratorResult = iterator.next( + await this.options.primaryCrypto.encrypt(attributeValue, encryptionAAD) + ); + } catch (err) { + iterator.throw!(err); + } + } else { + iterator.throw!(new Error('Encryption is disabled because of missing encryption key.')); } } @@ -324,12 +329,17 @@ export class EncryptedSavedObjectsService { let iteratorResult = iterator.next(); while (!iteratorResult.done) { const [attributeValue, encryptionAAD] = iteratorResult.value; - try { - iteratorResult = iterator.next( - this.options.primaryCrypto.encryptSync(attributeValue, encryptionAAD) - ); - } catch (err) { - iterator.throw!(err); + // We check this inside of the iterator to throw only if we do need to encrypt anything. + if (this.options.primaryCrypto) { + try { + iteratorResult = iterator.next( + this.options.primaryCrypto.encryptSync(attributeValue, encryptionAAD) + ); + } catch (err) { + iterator.throw!(err); + } + } else { + iterator.throw!(new Error('Encryption is disabled because of missing encryption key.')); } } @@ -358,7 +368,11 @@ export class EncryptedSavedObjectsService { while (!iteratorResult.done) { const [attributeValue, encryptionAAD] = iteratorResult.value; - let decryptionError; + // We check this inside of the iterator to throw only if we do need to decrypt anything. + let decryptionError = + decrypters.length === 0 + ? new Error('Decryption is disabled because of missing decryption keys.') + : undefined; for (const decrypter of decrypters) { try { iteratorResult = iterator.next(await decrypter.decrypt(attributeValue, encryptionAAD)); @@ -402,7 +416,11 @@ export class EncryptedSavedObjectsService { while (!iteratorResult.done) { const [attributeValue, encryptionAAD] = iteratorResult.value; - let decryptionError; + // We check this inside of the iterator to throw only if we do need to decrypt anything. + let decryptionError = + decrypters.length === 0 + ? new Error('Decryption is disabled because of missing decryption keys.') + : undefined; for (const decrypter of decrypters) { try { iteratorResult = iterator.next(decrypter.decryptSync(attributeValue, encryptionAAD)); @@ -541,6 +559,9 @@ export class EncryptedSavedObjectsService { return this.options.decryptionOnlyCryptos; } - return [this.options.primaryCrypto, ...(this.options.decryptionOnlyCryptos ?? [])]; + return [ + ...(this.options.primaryCrypto ? [this.options.primaryCrypto] : []), + ...(this.options.decryptionOnlyCryptos ?? []), + ]; } } diff --git a/x-pack/plugins/encrypted_saved_objects/server/mocks.ts b/x-pack/plugins/encrypted_saved_objects/server/mocks.ts index 6c8196b2ae03c..edb55513aabf5 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/mocks.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/mocks.ts @@ -8,11 +8,13 @@ import { EncryptedSavedObjectsPluginSetup, EncryptedSavedObjectsPluginStart } from './plugin'; import { EncryptedSavedObjectsClient, EncryptedSavedObjectsClientOptions } from './saved_objects'; -function createEncryptedSavedObjectsSetupMock() { +function createEncryptedSavedObjectsSetupMock( + { canEncrypt }: { canEncrypt: boolean } = { canEncrypt: false } +) { return { registerType: jest.fn(), __legacyCompat: { registerLegacyAPI: jest.fn() }, - usingEphemeralEncryptionKey: true, + canEncrypt, createMigration: jest.fn(), } as jest.Mocked; } diff --git a/x-pack/plugins/encrypted_saved_objects/server/plugin.test.ts b/x-pack/plugins/encrypted_saved_objects/server/plugin.test.ts index 823a6b0afa9dc..e71332b1c5aa7 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/plugin.test.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/plugin.test.ts @@ -19,12 +19,28 @@ describe('EncryptedSavedObjects Plugin', () => { ); expect(plugin.setup(coreMock.createSetup(), { security: securityMock.createSetup() })) .toMatchInlineSnapshot(` - Object { - "createMigration": [Function], - "registerType": [Function], - "usingEphemeralEncryptionKey": true, - } - `); + Object { + "canEncrypt": false, + "createMigration": [Function], + "registerType": [Function], + } + `); + }); + + it('exposes proper contract when encryption key is set', () => { + const plugin = new EncryptedSavedObjectsPlugin( + coreMock.createPluginInitializerContext( + ConfigSchema.validate({ encryptionKey: 'z'.repeat(32) }, { dist: true }) + ) + ); + expect(plugin.setup(coreMock.createSetup(), { security: securityMock.createSetup() })) + .toMatchInlineSnapshot(` + Object { + "canEncrypt": true, + "createMigration": [Function], + "registerType": [Function], + } + `); }); }); diff --git a/x-pack/plugins/encrypted_saved_objects/server/plugin.ts b/x-pack/plugins/encrypted_saved_objects/server/plugin.ts index e846b133c26e0..c99d6bd32287d 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/plugin.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/plugin.ts @@ -6,10 +6,9 @@ */ import nodeCrypto from '@elastic/node-crypto'; -import { Logger, PluginInitializerContext, CoreSetup, Plugin } from 'src/core/server'; -import { TypeOf } from '@kbn/config-schema'; -import { SecurityPluginSetup } from '../../security/server'; -import { createConfig, ConfigSchema } from './config'; +import type { Logger, PluginInitializerContext, CoreSetup, Plugin } from 'src/core/server'; +import type { SecurityPluginSetup } from '../../security/server'; +import type { ConfigType } from './config'; import { EncryptedSavedObjectsService, EncryptedSavedObjectTypeRegistration, @@ -26,8 +25,11 @@ export interface PluginsSetup { } export interface EncryptedSavedObjectsPluginSetup { + /** + * Indicates if Saved Object encryption is possible. Requires an encryption key to be explicitly set via `xpack.encryptedSavedObjects.encryptionKey`. + */ + canEncrypt: boolean; registerType: (typeRegistration: EncryptedSavedObjectTypeRegistration) => void; - usingEphemeralEncryptionKey: boolean; createMigration: CreateEncryptedSavedObjectsMigrationFn; } @@ -50,19 +52,24 @@ export class EncryptedSavedObjectsPlugin } public setup(core: CoreSetup, deps: PluginsSetup): EncryptedSavedObjectsPluginSetup { - const config = createConfig( - this.initializerContext.config.get>(), - this.initializerContext.logger.get('config') - ); - const auditLogger = new EncryptedSavedObjectsAuditLogger( - deps.security?.audit.getLogger('encryptedSavedObjects') - ); + const config = this.initializerContext.config.get(); + const canEncrypt = config.encryptionKey !== undefined; + if (!canEncrypt) { + this.logger.warn( + 'Saved objects encryption key is not set. This will severely limit Kibana functionality. ' + + 'Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' + ); + } - const primaryCrypto = nodeCrypto({ encryptionKey: config.encryptionKey }); + const primaryCrypto = config.encryptionKey + ? nodeCrypto({ encryptionKey: config.encryptionKey }) + : undefined; const decryptionOnlyCryptos = config.keyRotation.decryptionOnlyKeys.map((decryptionKey) => nodeCrypto({ encryptionKey: decryptionKey }) ); - + const auditLogger = new EncryptedSavedObjectsAuditLogger( + deps.security?.audit.getLogger('encryptedSavedObjects') + ); const service = Object.freeze( new EncryptedSavedObjectsService({ primaryCrypto, @@ -94,9 +101,9 @@ export class EncryptedSavedObjectsPlugin }); return { + canEncrypt, registerType: (typeRegistration: EncryptedSavedObjectTypeRegistration) => service.registerType(typeRegistration), - usingEphemeralEncryptionKey: config.usingEphemeralEncryptionKey, createMigration: getCreateMigration( service, (typeRegistration: EncryptedSavedObjectTypeRegistration) => { diff --git a/x-pack/plugins/encrypted_saved_objects/server/routes/index.mock.ts b/x-pack/plugins/encrypted_saved_objects/server/routes/index.mock.ts index c2dbc4c163b44..32ac1617f4a7e 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/routes/index.mock.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/routes/index.mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ConfigSchema, createConfig } from '../config'; +import { ConfigSchema, ConfigType } from '../config'; import { httpServiceMock, loggingSystemMock } from '../../../../../src/core/server/mocks'; import { encryptionKeyRotationServiceMock } from '../crypto/index.mock'; @@ -14,7 +14,7 @@ export const routeDefinitionParamsMock = { create: (config: Record = {}) => ({ router: httpServiceMock.createRouter(), logger: loggingSystemMock.create().get(), - config: createConfig(ConfigSchema.validate(config), loggingSystemMock.create().get()), + config: ConfigSchema.validate(config) as ConfigType, encryptionKeyRotationService: encryptionKeyRotationServiceMock.create(), }), }; diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts index f284fef370f02..ecc7b991f0761 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts @@ -11,11 +11,11 @@ * NOTE: These variable names MUST start with 'mock*' in order for * Jest to accept its use within a jest.mock() */ +import { mockFlashMessagesValues, mockFlashMessagesActions } from './flash_messages_logic.mock'; +import { mockHttpValues } from './http_logic.mock'; import { mockKibanaValues } from './kibana_logic.mock'; import { mockLicensingValues } from './licensing_logic.mock'; -import { mockHttpValues } from './http_logic.mock'; import { mockTelemetryActions } from './telemetry_logic.mock'; -import { mockFlashMessagesValues, mockFlashMessagesActions } from './flash_messages_logic.mock'; export const mockAllValues = { ...mockKibanaValues, diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts index a201a2b56c25c..d8d66e5ee1998 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts @@ -6,6 +6,7 @@ */ import { chartPluginMock } from '../../../../../../src/plugins/charts/public/mocks'; + import { mockHistory } from './'; export const mockKibanaValues = { diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_async.mock.tsx b/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_async.mock.tsx index 27e8a1421f462..2b5c06df37e8c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_async.mock.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_async.mock.tsx @@ -6,8 +6,9 @@ */ import React from 'react'; -import { act } from 'react-dom/test-utils'; + import { mount, ReactWrapper } from 'enzyme'; +import { act } from 'react-dom/test-utils'; import { mountWithIntl } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_with_i18n.mock.tsx b/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_with_i18n.mock.tsx index a5a2891d3699c..3a98616082412 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_with_i18n.mock.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_with_i18n.mock.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { mount } from 'enzyme'; + import { I18nProvider } from '@kbn/i18n/react'; /** diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_with_i18n.mock.tsx b/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_with_i18n.mock.tsx index 224d71ac579a0..0127804374163 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_with_i18n.mock.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_with_i18n.mock.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { shallow, mount, ReactWrapper } from 'enzyme'; + import { I18nProvider, __IntlProvider } from '@kbn/i18n/react'; // Use fake component to extract `intl` property to use in tests. diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.test.ts index 86f3993728e06..e5b0a702897bf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.test.ts @@ -5,9 +5,9 @@ * 2.0. */ +import { DEFAULT_INITIAL_APP_DATA } from '../../../common/__mocks__'; import { LogicMounter } from '../__mocks__'; -import { DEFAULT_INITIAL_APP_DATA } from '../../../common/__mocks__'; import { AppLogic } from './app_logic'; describe('AppLogic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.ts index 8a55b7c0add94..c33a0e89d2aee 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.ts @@ -8,6 +8,7 @@ import { kea, MakeLogicType } from 'kea'; import { InitialAppData } from '../../../common/types'; + import { ConfiguredLimits, Account, Role } from './types'; import { getRoleAbilities } from './utils/role'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_layout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_layout.test.tsx index 5248833d827b2..1a4e05c04f319 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_layout.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_layout.test.tsx @@ -11,14 +11,15 @@ import { mockKibanaValues, setMockValues, setMockActions, rerender } from '../.. import React from 'react'; import { useParams } from 'react-router-dom'; + import { shallow } from 'enzyme'; -import { Loading } from '../../../shared/loading'; import { FlashMessages } from '../../../shared/flash_messages'; +import { Loading } from '../../../shared/loading'; import { LogRetentionCallout } from '../log_retention'; -import { AnalyticsHeader, AnalyticsUnavailable } from './components'; import { AnalyticsLayout } from './analytics_layout'; +import { AnalyticsHeader, AnalyticsUnavailable } from './components'; describe('AnalyticsLayout', () => { const { history } = mockKibanaValues; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_layout.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_layout.tsx index 88d0f77541166..0c90267c1dbad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_layout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_layout.tsx @@ -7,18 +7,21 @@ import React, { useEffect } from 'react'; import { useParams } from 'react-router-dom'; + import { useValues, useActions } from 'kea'; + import { EuiSpacer } from '@elastic/eui'; -import { KibanaLogic } from '../../../shared/kibana'; import { FlashMessages } from '../../../shared/flash_messages'; +import { KibanaLogic } from '../../../shared/kibana'; import { Loading } from '../../../shared/loading'; import { LogRetentionCallout, LogRetentionOptions } from '../log_retention'; -import { AnalyticsLogic } from './'; import { AnalyticsHeader, AnalyticsUnavailable } from './components'; +import { AnalyticsLogic } from './'; + interface Props { title: string; isQueryView?: boolean; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts index 6ca9eb23c962b..ad612e48c770a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts @@ -19,6 +19,7 @@ jest.mock('../engine', () => ({ import { nextTick } from '@kbn/test/jest'; import { DEFAULT_START_DATE, DEFAULT_END_DATE } from './constants'; + import { AnalyticsLogic } from './'; describe('AnalyticsLogic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.ts index e978d2c65398e..de0828f6d71ea 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.ts @@ -8,9 +8,9 @@ import { kea, MakeLogicType } from 'kea'; import queryString from 'query-string'; -import { KibanaLogic } from '../../../shared/kibana'; -import { HttpLogic } from '../../../shared/http'; import { flashAPIErrors } from '../../../shared/flash_messages'; +import { HttpLogic } from '../../../shared/http'; +import { KibanaLogic } from '../../../shared/kibana'; import { EngineLogic } from '../engine'; import { DEFAULT_START_DATE, DEFAULT_END_DATE } from './constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.test.tsx index 3f6bf77024c1e..3940151d3b7cd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.test.tsx @@ -8,9 +8,11 @@ import '../../__mocks__/engine_logic.mock'; import React from 'react'; -import { shallow } from 'enzyme'; + import { Route, Switch } from 'react-router-dom'; +import { shallow } from 'enzyme'; + import { AnalyticsRouter } from './'; describe('AnalyticsRouter', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.test.tsx index 84ee392c2419e..8883d0d1ffcbd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiStat } from '@elastic/eui'; import { AnalyticsCards } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.tsx index 417fa0cc48f65..b08e391f845e6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat } from '@elastic/eui'; interface Props { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_chart.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_chart.test.tsx index dcea1f81e53eb..51238d62bdac7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_chart.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_chart.test.tsx @@ -8,7 +8,9 @@ import { mockKibanaValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { Chart, Settings, LineSeries, Axis } from '@elastic/charts'; import { AnalyticsChart } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_chart.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_chart.tsx index 686cadda02f63..fa33389503beb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_chart.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_chart.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; + import { useValues } from 'kea'; import moment from 'moment'; + import { Chart, Settings, LineSeries, CurveType, Axis } from '@elastic/charts'; import { KibanaLogic } from '../../../../shared/kibana'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_header.test.tsx index 3faf2b03097f7..952c4c2517a0e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_header.test.tsx @@ -8,13 +8,16 @@ import { setMockValues, mockKibanaValues } from '../../../../__mocks__'; import React, { ReactElement } from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; import moment, { Moment } from 'moment'; + import { EuiPageHeader, EuiSelect, EuiDatePickerRange, EuiButton } from '@elastic/eui'; import { LogRetentionTooltip } from '../../log_retention'; import { DEFAULT_START_DATE, DEFAULT_END_DATE } from '../constants'; + import { AnalyticsHeader } from './'; describe('AnalyticsHeader', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_header.tsx index 3986f7859bfd2..8a87a5e8c211c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_header.tsx @@ -6,12 +6,11 @@ */ import React, { useState } from 'react'; -import { useValues } from 'kea'; -import queryString from 'query-string'; +import { useValues } from 'kea'; import moment from 'moment'; +import queryString from 'query-string'; -import { i18n } from '@kbn/i18n'; import { EuiPageHeader, EuiPageHeaderSection, @@ -23,11 +22,12 @@ import { EuiDatePicker, EuiButton, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { AnalyticsLogic } from '../'; import { KibanaLogic } from '../../../../shared/kibana'; import { LogRetentionTooltip, LogRetentionOptions } from '../../log_retention'; -import { AnalyticsLogic } from '../'; import { DEFAULT_START_DATE, DEFAULT_END_DATE, SERVER_DATE_FORMAT } from '../constants'; import { convertTagsToSelectOptions } from '../utils'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_search.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_search.test.tsx index 4a3bbda5120bc..89fa5b4cc4b73 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_search.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_search.test.tsx @@ -9,7 +9,9 @@ import { mockKibanaValues } from '../../../../__mocks__'; import '../../../__mocks__/engine_logic.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFieldSearch } from '@elastic/eui'; import { AnalyticsSearch } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_search.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_search.tsx index 922e096701e84..4f2b525aaa168 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_search.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_search.tsx @@ -6,10 +6,11 @@ */ import React, { useState } from 'react'; + import { useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiFieldSearch, EuiButton, EuiSpacer } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { KibanaLogic } from '../../../../shared/kibana'; import { ENGINE_ANALYTICS_QUERY_DETAIL_PATH } from '../../../routes'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.test.tsx index 981173e2a915b..56e30e6061173 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { AnalyticsSection } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx index 0788edfdda427..2eac65fc21091 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx @@ -9,6 +9,7 @@ import { mountWithIntl, mockKibanaValues } from '../../../../../__mocks__'; import '../../../../__mocks__/engine_logic.mock'; import React from 'react'; + import { EuiBasicTable, EuiBadge, EuiEmptyPrompt } from '@elastic/eui'; import { AnalyticsTable } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx index 8e9853233cbed..a580047f1f635 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx @@ -6,10 +6,12 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; + import { EuiBasicTable, EuiBasicTableColumn, EuiEmptyPrompt } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { Query } from '../../types'; + import { TERM_COLUMN_PROPS, TAGS_COLUMN, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx index 9ad2cc32f99c5..9204fa6e75fa7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiBadge, EuiToolTip } from '@elastic/eui'; import { InlineTagsList } from './inline_tags_list'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx index 421ff1eedf278..908b096c80a9e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx @@ -6,8 +6,9 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; + import { EuiBadgeGroup, EuiBadge, EuiToolTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { Query } from '../../types'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx index 4396f91136258..cc8f13299c57f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx @@ -9,6 +9,7 @@ import { mountWithIntl } from '../../../../../__mocks__'; import '../../../../__mocks__/engine_logic.mock'; import React from 'react'; + import { EuiBasicTable, EuiLink, EuiBadge, EuiEmptyPrompt } from '@elastic/eui'; import { QueryClicksTable } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.tsx index 7c333623df6c0..4a93724ff5245 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.tsx @@ -7,15 +7,16 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiBasicTable, EuiBasicTableColumn, EuiEmptyPrompt } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { EuiLinkTo } from '../../../../../shared/react_router_helpers'; import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../../../routes'; -import { generateEnginePath } from '../../../engine'; import { DOCUMENTS_TITLE } from '../../../documents'; +import { generateEnginePath } from '../../../engine'; import { QueryClick } from '../../types'; + import { FIRST_COLUMN_PROPS, TAGS_COLUMN, COUNT_COLUMN_PROPS } from './shared_columns'; interface Props { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.test.tsx index fdbbd326c47a1..a5a582d3747bc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.test.tsx @@ -9,6 +9,7 @@ import { mountWithIntl, mockKibanaValues } from '../../../../../__mocks__'; import '../../../../__mocks__/engine_logic.mock'; import React from 'react'; + import { EuiBasicTable, EuiBadge, EuiEmptyPrompt } from '@elastic/eui'; import { RecentQueriesTable } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.tsx index 20e50e633b321..7724ac5c393ec 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.tsx @@ -7,11 +7,12 @@ import React from 'react'; +import { EuiBasicTable, EuiBasicTableColumn, EuiEmptyPrompt } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedDate, FormattedTime } from '@kbn/i18n/react'; -import { EuiBasicTable, EuiBasicTableColumn, EuiEmptyPrompt } from '@elastic/eui'; import { RecentQuery } from '../../types'; + import { TERM_COLUMN_PROPS, TAGS_COLUMN, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx index 0612fac1c07ed..9d8365a2f7af1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx @@ -6,14 +6,15 @@ */ import React from 'react'; + import { i18n } from '@kbn/i18n'; -import { EuiLinkTo } from '../../../../../shared/react_router_helpers'; import { KibanaLogic } from '../../../../../shared/kibana'; +import { EuiLinkTo } from '../../../../../shared/react_router_helpers'; import { ENGINE_ANALYTICS_QUERY_DETAIL_PATH } from '../../../../routes'; import { generateEnginePath } from '../../../engine'; - import { Query, RecentQuery } from '../../types'; + import { InlineTagsList } from './inline_tags_list'; /** diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_unavailable.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_unavailable.test.tsx index ddc0e4636b3ad..e2ff440615dfc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_unavailable.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_unavailable.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiEmptyPrompt } from '@elastic/eui'; import { FlashMessages } from '../../../../shared/flash_messages'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_unavailable.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_unavailable.tsx index 2ef020d2f4992..388570b32b6d2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_unavailable.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_unavailable.tsx @@ -6,8 +6,9 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; + import { EuiEmptyPrompt } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { FlashMessages } from '../../../../shared/flash_messages'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/constants.ts index a04a9474ce5ae..75001f5bc86d6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/constants.ts @@ -6,6 +6,7 @@ */ import moment from 'moment'; + import { i18n } from '@kbn/i18n'; export const ANALYTICS_TITLE = i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/utils.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/utils.ts index 2d00c906b2aec..db679b0f387e8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/utils.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/utils.ts @@ -6,11 +6,12 @@ */ import moment from 'moment'; -import { i18n } from '@kbn/i18n'; + import { EuiSelectProps } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; -import { SERVER_DATE_FORMAT } from './constants'; import { ChartData } from './components/analytics_chart'; +import { SERVER_DATE_FORMAT } from './constants'; interface ConvertToChartData { data: number[]; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.test.tsx index 065b2208648bf..d8921ff0d3723 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.test.tsx @@ -9,6 +9,7 @@ import { setMockValues } from '../../../../__mocks__'; import '../../../__mocks__/engine_logic.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { @@ -18,6 +19,7 @@ import { AnalyticsTable, RecentQueriesTable, } from '../components'; + import { Analytics, ViewAllButton } from './analytics'; describe('Analytics overview', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx index 09b1ff45c6122..a4f0bc356ac78 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx @@ -6,10 +6,11 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiTitle } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { EuiButtonTo } from '../../../../shared/react_router_helpers'; import { @@ -21,6 +22,8 @@ import { } from '../../../routes'; import { generateEnginePath } from '../../engine'; +import { AnalyticsLayout } from '../analytics_layout'; +import { AnalyticsSection, AnalyticsTable, RecentQueriesTable } from '../components'; import { ANALYTICS_TITLE, TOTAL_QUERIES, @@ -32,9 +35,7 @@ import { TOP_QUERIES_NO_CLICKS, RECENT_QUERIES, } from '../constants'; -import { AnalyticsLayout } from '../analytics_layout'; -import { AnalyticsSection, AnalyticsTable, RecentQueriesTable } from '../components'; -import { AnalyticsLogic, AnalyticsCards, AnalyticsChart, convertToChartData } from '../'; +import { AnalyticsLogic, AnalyticsCards, AnalyticsChart, convertToChartData } from '../index'; export const Analytics: React.FC = () => { const { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.test.tsx index 050770944edcd..978f11ddfd5cd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.test.tsx @@ -10,12 +10,14 @@ import { setMockValues } from '../../../../__mocks__'; import React from 'react'; import { useParams } from 'react-router-dom'; + import { shallow } from 'enzyme'; import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome'; import { AnalyticsLayout } from '../analytics_layout'; import { AnalyticsCards, AnalyticsChart, QueryClicksTable } from '../components'; + import { QueryDetail } from './'; describe('QueryDetail', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.tsx index 96587eb528710..f00c4e29a7190 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.tsx @@ -6,10 +6,11 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiSpacer } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome'; import { BreadcrumbTrail } from '../../../../shared/kibana_chrome/generate_breadcrumbs'; @@ -17,7 +18,7 @@ import { useDecodedParams } from '../../../utils/encode_path_params'; import { AnalyticsLayout } from '../analytics_layout'; import { AnalyticsSection, QueryClicksTable } from '../components'; -import { AnalyticsLogic, AnalyticsCards, AnalyticsChart, convertToChartData } from '../'; +import { AnalyticsLogic, AnalyticsCards, AnalyticsChart, convertToChartData } from '../index'; const QUERY_DETAIL_TITLE = i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.analytics.queryDetail.title', diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/recent_queries.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/recent_queries.test.tsx index 40577fb2d4447..21d515a7b9795 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/recent_queries.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/recent_queries.test.tsx @@ -8,9 +8,11 @@ import { setMockValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { RecentQueriesTable } from '../components'; + import { RecentQueries } from './'; describe('RecentQueries', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/recent_queries.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/recent_queries.tsx index e5380258894ae..bb0c3c4d32244 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/recent_queries.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/recent_queries.tsx @@ -6,12 +6,13 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { RECENT_QUERIES } from '../constants'; +import { AnalyticsLogic } from '../'; import { AnalyticsLayout } from '../analytics_layout'; import { AnalyticsSearch, RecentQueriesTable } from '../components'; -import { AnalyticsLogic } from '../'; +import { RECENT_QUERIES } from '../constants'; export const RecentQueries: React.FC = () => { const { recentQueries } = useValues(AnalyticsLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries.test.tsx index b037e6bf1d64e..46b2b37958435 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries.test.tsx @@ -8,9 +8,11 @@ import { setMockValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { AnalyticsTable } from '../components'; + import { TopQueries } from './'; describe('TopQueries', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries.tsx index 76d523d16ee11..6459126560b3a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries.tsx @@ -6,12 +6,13 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { TOP_QUERIES } from '../constants'; +import { AnalyticsLogic } from '../'; import { AnalyticsLayout } from '../analytics_layout'; import { AnalyticsSearch, AnalyticsTable } from '../components'; -import { AnalyticsLogic } from '../'; +import { TOP_QUERIES } from '../constants'; export const TopQueries: React.FC = () => { const { topQueries } = useValues(AnalyticsLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_clicks.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_clicks.test.tsx index 1248a49fc5a9c..83212160d1350 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_clicks.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_clicks.test.tsx @@ -8,9 +8,11 @@ import { setMockValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { AnalyticsTable } from '../components'; + import { TopQueriesNoClicks } from './'; describe('TopQueriesNoClicks', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_clicks.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_clicks.tsx index 604ab96b871e7..8e2591697feaa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_clicks.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_clicks.tsx @@ -6,12 +6,13 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { TOP_QUERIES_NO_CLICKS } from '../constants'; +import { AnalyticsLogic } from '../'; import { AnalyticsLayout } from '../analytics_layout'; import { AnalyticsSearch, AnalyticsTable } from '../components'; -import { AnalyticsLogic } from '../'; +import { TOP_QUERIES_NO_CLICKS } from '../constants'; export const TopQueriesNoClicks: React.FC = () => { const { topQueriesNoClicks } = useValues(AnalyticsLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_results.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_results.test.tsx index 3cb77b3c7afbc..dfc5b9c93ab64 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_results.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_results.test.tsx @@ -8,9 +8,11 @@ import { setMockValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { AnalyticsTable } from '../components'; + import { TopQueriesNoResults } from './'; describe('TopQueriesNoResults', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_results.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_results.tsx index 425fdf8e88559..e093a5130d204 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_results.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_no_results.tsx @@ -6,12 +6,13 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { TOP_QUERIES_NO_RESULTS } from '../constants'; +import { AnalyticsLogic } from '../'; import { AnalyticsLayout } from '../analytics_layout'; import { AnalyticsSearch, AnalyticsTable } from '../components'; -import { AnalyticsLogic } from '../'; +import { TOP_QUERIES_NO_RESULTS } from '../constants'; export const TopQueriesNoResults: React.FC = () => { const { topQueriesNoResults } = useValues(AnalyticsLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_with_clicks.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_with_clicks.test.tsx index 83be03e95d2cf..fb967ca06b387 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_with_clicks.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_with_clicks.test.tsx @@ -8,9 +8,11 @@ import { setMockValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { AnalyticsTable } from '../components'; + import { TopQueriesWithClicks } from './'; describe('TopQueriesWithClicks', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_with_clicks.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_with_clicks.tsx index bec096019035b..87e276a8382c3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_with_clicks.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/top_queries_with_clicks.tsx @@ -6,12 +6,13 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { TOP_QUERIES_WITH_CLICKS } from '../constants'; +import { AnalyticsLogic } from '../'; import { AnalyticsLayout } from '../analytics_layout'; import { AnalyticsSearch, AnalyticsTable } from '../components'; -import { AnalyticsLogic } from '../'; +import { TOP_QUERIES_WITH_CLICKS } from '../constants'; export const TopQueriesWithClicks: React.FC = () => { const { topQueriesWithClicks } = useValues(AnalyticsLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts index 2e28e5a272643..0fb118548a67b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; + import { DOCS_PREFIX } from '../../routes'; export const CREDENTIALS_TITLE = i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.test.tsx index cc783e7c056e2..48fcf4b8c5b66 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.test.tsx @@ -9,12 +9,15 @@ import { setMockValues, setMockActions } from '../../../__mocks__/kea.mock'; import { unmountHandler } from '../../../__mocks__/shallow_useeffect.mock'; import React from 'react'; + import { shallow } from 'enzyme'; -import { Credentials } from './credentials'; import { EuiCopy, EuiLoadingContent, EuiPageContentBody } from '@elastic/eui'; import { externalUrl } from '../../../shared/enterprise_search_url'; + +import { Credentials } from './credentials'; + import { CredentialsFlyout } from './credentials_flyout'; describe('Credentials', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx index 0266b64f97104..266e9467c300d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx @@ -6,6 +6,7 @@ */ import React, { useEffect } from 'react'; + import { useActions, useValues } from 'kea'; import { @@ -24,14 +25,14 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { externalUrl } from '../../../shared/enterprise_search_url/external_url'; import { FlashMessages } from '../../../shared/flash_messages'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; -import { CredentialsLogic } from './credentials_logic'; -import { externalUrl } from '../../../shared/enterprise_search_url/external_url'; import { CREDENTIALS_TITLE } from './constants'; -import { CredentialsList } from './credentials_list'; import { CredentialsFlyout } from './credentials_flyout'; +import { CredentialsList } from './credentials_list'; +import { CredentialsLogic } from './credentials_logic'; export const Credentials: React.FC = () => { const { initializeCredentialsData, resetCredentials, showCredentialsForm } = useActions( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.test.tsx index 8b5a59b82c19b..595bc1bcbb828 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.test.tsx @@ -8,12 +8,15 @@ import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFlyoutBody, EuiForm } from '@elastic/eui'; import { ApiTokenTypes } from '../constants'; import { defaultApiToken } from '../credentials_logic'; +import { CredentialsFlyoutBody } from './body'; import { FormKeyName, FormKeyType, @@ -21,7 +24,6 @@ import { FormKeyEngineAccess, FormKeyUpdateWarning, } from './form_components'; -import { CredentialsFlyoutBody } from './body'; describe('CredentialsFlyoutBody', () => { const values = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.tsx index f3de25fe0a25d..def165f3f82a2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.tsx @@ -6,12 +6,14 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; + import { EuiFlyoutBody, EuiForm } from '@elastic/eui'; import { FlashMessages } from '../../../../shared/flash_messages'; -import { CredentialsLogic } from '../credentials_logic'; import { ApiTokenTypes } from '../constants'; +import { CredentialsLogic } from '../credentials_logic'; import { FormKeyName, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.test.tsx index 036fe881c7d0d..23e85b92bb8b4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.test.tsx @@ -8,7 +8,9 @@ import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFlyoutFooter, EuiButtonEmpty } from '@elastic/eui'; import { CredentialsFlyoutFooter } from './footer'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.tsx index dc2d52a073b36..c05bd82c6206e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; + import { EuiFlyoutFooter, EuiFlexGroup, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx index 51a737ce8c826..7247deb09f12b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx @@ -8,7 +8,9 @@ import { setMockValues, setMockActions, rerender } from '../../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiRadio, EuiCheckbox } from '@elastic/eui'; import { FormKeyEngineAccess, EngineSelection } from './key_engine_access'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.tsx index 2a9e8cf153dca..0d6ebfe437927 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; + import { EuiFormRow, EuiRadio, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.test.tsx index 27f95f2ba7cd8..d54d0c89c90cb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.test.tsx @@ -8,7 +8,9 @@ import { setMockValues, setMockActions } from '../../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFieldText, EuiFormRow } from '@elastic/eui'; import { FormKeyName } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.tsx index cb4dce76dfcc1..f4f4f5f0aaaaa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; + import { EuiFormRow, EuiFieldText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.test.tsx index 8cfa5b3c4571a..cf45576d691cf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.test.tsx @@ -8,7 +8,9 @@ import { setMockValues, setMockActions } from '../../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiCheckbox } from '@elastic/eui'; import { FormKeyReadWriteAccess } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.tsx index f9653159b4403..0b631089c3984 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; + import { EuiCheckbox, EuiText, EuiTitle, EuiSpacer, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.test.tsx index 9cf6c82184579..5de2c7fda53ca 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.test.tsx @@ -8,10 +8,13 @@ import { setMockValues, setMockActions } from '../../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiSelect } from '@elastic/eui'; import { ApiTokenTypes, TOKEN_TYPE_INFO } from '../../constants'; + import { FormKeyType } from './'; describe('FormKeyType', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.tsx index a8cc16b3b30e7..60308274fbb76 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.tsx @@ -6,13 +6,15 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; + import { EuiFormRow, EuiSelect, EuiText, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { AppLogic } from '../../../../app_logic'; -import { CredentialsLogic } from '../../credentials_logic'; import { TOKEN_TYPE_DESCRIPTION, TOKEN_TYPE_INFO, DOCS_HREF } from '../../constants'; +import { CredentialsLogic } from '../../credentials_logic'; export const FormKeyType: React.FC = () => { const { myRole } = useValues(AppLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.test.tsx index 073c4ec1c92bf..38eec0b371576 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiCallOut } from '@elastic/eui'; import { FormKeyUpdateWarning } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.tsx index 87cda9590f5cb..c24eebea9178b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { EuiSpacer, EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.test.tsx index 0772a395dbe71..8ee7f810c1fa5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.test.tsx @@ -8,7 +8,9 @@ import { setMockValues } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFlyoutHeader } from '@elastic/eui'; import { ApiTokenTypes } from '../constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.tsx index a9efcbe371c4f..586ddc5c22b97 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.tsx @@ -6,12 +6,14 @@ */ import React from 'react'; + import { useValues } from 'kea'; + import { EuiFlyoutHeader, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { CredentialsLogic } from '../credentials_logic'; import { FLYOUT_ARIA_LABEL_ID } from '../constants'; +import { CredentialsLogic } from '../credentials_logic'; export const CredentialsFlyoutHeader: React.FC = () => { const { activeApiToken } = useValues(CredentialsLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.test.tsx index 1f7408857857a..9932b8ca227b0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.test.tsx @@ -8,7 +8,9 @@ import { setMockActions } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFlyout } from '@elastic/eui'; import { CredentialsFlyout } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.tsx index 1335a3cdeea18..2ee73a6b80b5a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.tsx @@ -6,14 +6,17 @@ */ import React from 'react'; + import { useActions } from 'kea'; + import { EuiPortal, EuiFlyout } from '@elastic/eui'; -import { CredentialsLogic } from '../credentials_logic'; import { FLYOUT_ARIA_LABEL_ID } from '../constants'; -import { CredentialsFlyoutHeader } from './header'; +import { CredentialsLogic } from '../credentials_logic'; + import { CredentialsFlyoutBody } from './body'; import { CredentialsFlyoutFooter } from './footer'; +import { CredentialsFlyoutHeader } from './header'; export const CredentialsFlyout: React.FC = () => { const { hideCredentialsForm } = useActions(CredentialsLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.test.tsx index dd3d8ef8069ba..8c52df30bfc67 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.test.tsx @@ -8,15 +8,18 @@ import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiBasicTable, EuiCopy, EuiEmptyPrompt } from '@elastic/eui'; -import { ApiToken } from '../types'; +import { HiddenText } from '../../../../shared/hidden_text'; import { ApiTokenTypes } from '../constants'; +import { ApiToken } from '../types'; -import { HiddenText } from '../../../../shared/hidden_text'; import { Key } from './key'; -import { CredentialsList } from './credentials_list'; + +import { CredentialsList } from './'; describe('Credentials', () => { const apiToken: ApiToken = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx index 9d220469347f2..f23479017a680 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx @@ -6,19 +6,21 @@ */ import React, { useMemo } from 'react'; -import { EuiBasicTable, EuiBasicTableColumn, EuiCopy, EuiEmptyPrompt } from '@elastic/eui'; -import { CriteriaWithPagination } from '@elastic/eui/src/components/basic_table/basic_table'; + import { useActions, useValues } from 'kea'; +import { EuiBasicTable, EuiBasicTableColumn, EuiCopy, EuiEmptyPrompt } from '@elastic/eui'; +import { CriteriaWithPagination } from '@elastic/eui/src/components/basic_table/basic_table'; import { i18n } from '@kbn/i18n'; -import { CredentialsLogic } from '../credentials_logic'; -import { Key } from './key'; import { HiddenText } from '../../../../shared/hidden_text'; -import { ApiToken } from '../types'; import { TOKEN_TYPE_DISPLAY_NAMES } from '../constants'; -import { apiTokenSort } from '../utils/api_token_sort'; +import { CredentialsLogic } from '../credentials_logic'; +import { ApiToken } from '../types'; import { getModeDisplayText, getEnginesDisplayText } from '../utils'; +import { apiTokenSort } from '../utils/api_token_sort'; + +import { Key } from './key'; export const CredentialsList: React.FC = () => { const { deleteApiKey, fetchCredentials, showCredentialsForm } = useActions(CredentialsLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/key.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/key.test.tsx index c18302db9ddfd..5e042319ae613 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/key.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/key.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiButtonIcon } from '@elastic/eui'; import { Key } from './key'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/key.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/key.tsx index 940453c83a1fe..ff14379b9aecc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/key.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/key.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { EuiButtonIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts index 005f487772d80..c9d6a43ebbbae 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts @@ -17,6 +17,7 @@ jest.mock('../../app_logic', () => ({ import { nextTick } from '@kbn/test/jest'; import { AppLogic } from '../../app_logic'; + import { ApiTokenTypes } from './constants'; import { CredentialsLogic } from './credentials_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts index 25cd1be93836d..ff4600872c589 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts @@ -7,19 +7,19 @@ import { kea, MakeLogicType } from 'kea'; -import { formatApiName } from '../../utils/format_api_name'; -import { ApiTokenTypes, CREATE_MESSAGE, UPDATE_MESSAGE, DELETE_MESSAGE } from './constants'; - -import { HttpLogic } from '../../../shared/http'; +import { Meta } from '../../../../../common/types'; import { clearFlashMessages, setSuccessMessage, flashAPIErrors, } from '../../../shared/flash_messages'; +import { HttpLogic } from '../../../shared/http'; import { AppLogic } from '../../app_logic'; - -import { Meta } from '../../../../../common/types'; import { Engine } from '../../types'; +import { formatApiName } from '../../utils/format_api_name'; + +import { ApiTokenTypes, CREATE_MESSAGE, UPDATE_MESSAGE, DELETE_MESSAGE } from './constants'; + import { ApiToken, CredentialsDetails, TokenReadWrite } from './types'; export const defaultApiToken: ApiToken = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/types.ts index ddc81658eed2c..0427d25add49b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/types.ts @@ -6,6 +6,7 @@ */ import { Engine } from '../../types'; + import { ApiTokenTypes } from './constants'; export interface CredentialsDetails { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/api_token_sort.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/api_token_sort.test.ts index 1f84caa7e1ef7..70277d6cb7f22 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/api_token_sort.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/api_token_sort.test.ts @@ -5,11 +5,12 @@ * 2.0. */ -import { apiTokenSort } from '.'; import { ApiTokenTypes } from '../constants'; import { ApiToken } from '../types'; +import { apiTokenSort } from '.'; + describe('apiTokenSort', () => { const apiToken: ApiToken = { name: '', diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/get_engines_display_text.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/get_engines_display_text.test.tsx index e92957405a524..71d00efa2a868 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/get_engines_display_text.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/get_engines_display_text.test.tsx @@ -6,22 +6,24 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; -import { getEnginesDisplayText } from './get_engines_display_text'; -import { ApiToken } from '../types'; import { ApiTokenTypes } from '../constants'; +import { ApiToken } from '../types'; -const apiToken: ApiToken = { - name: '', - type: ApiTokenTypes.Private, - read: true, - write: true, - access_all_engines: true, - engines: ['engine1', 'engine2', 'engine3'], -}; +import { getEnginesDisplayText } from './get_engines_display_text'; describe('getEnginesDisplayText', () => { + const apiToken: ApiToken = { + name: '', + type: ApiTokenTypes.Private, + read: true, + write: true, + access_all_engines: true, + engines: ['engine1', 'engine2', 'engine3'], + }; + it('returns "--" when the token is an admin token', () => { const wrapper = shallow(
{getEnginesDisplayText({ ...apiToken, type: ApiTokenTypes.Admin })}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/get_engines_display_text.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/get_engines_display_text.tsx index 34089cacbf180..d3577ec14fec9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/get_engines_display_text.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/utils/get_engines_display_text.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { ApiTokenTypes, ALL } from '../constants'; import { ApiToken } from '../types'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.test.tsx index 7203cf6982086..34afa9d1e39ed 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.test.tsx @@ -9,7 +9,9 @@ import '../../../../__mocks__/enterprise_search_url.mock'; import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; + import { EuiCode, EuiCodeBlock, EuiButtonEmpty } from '@elastic/eui'; import { ApiCodeExample, FlyoutHeader, FlyoutBody, FlyoutFooter } from './api_code_example'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.tsx index 9167df25f75b5..88e9df5c2bbf5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.tsx @@ -5,12 +5,12 @@ * 2.0. */ -import dedent from 'dedent'; import React from 'react'; + +import dedent from 'dedent'; + import { useValues, useActions } from 'kea'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlyoutHeader, EuiTitle, @@ -27,18 +27,19 @@ import { EuiFlexGroup, EuiFlexItem, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { getEnterpriseSearchUrl } from '../../../../shared/enterprise_search_url'; +import { DOCS_PREFIX } from '../../../routes'; import { EngineLogic } from '../../engine'; import { EngineDetails } from '../../engine/types'; - -import { DOCS_PREFIX } from '../../../routes'; import { DOCUMENTS_API_JSON_EXAMPLE, FLYOUT_ARIA_LABEL_ID, FLYOUT_CANCEL_BUTTON, } from '../constants'; -import { DocumentCreationLogic } from '../'; +import { DocumentCreationLogic } from '../index'; export const ApiCodeExample: React.FC = () => ( <> diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.test.tsx index c1c0a554b4794..8b5b36094fbc6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.test.tsx @@ -8,10 +8,13 @@ import { setMockValues, setMockActions, rerender } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiTextArea, EuiButtonEmpty, EuiButton } from '@elastic/eui'; import { Errors } from '../creation_response_components'; + import { PasteJsonText, FlyoutHeader, FlyoutBody, FlyoutFooter } from './paste_json_text'; describe('PasteJsonText', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.tsx index 377d795413714..2d4a6de26333f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.tsx @@ -6,9 +6,9 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiFlyoutHeader, EuiTitle, @@ -22,12 +22,13 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { AppLogic } from '../../../app_logic'; import { FLYOUT_ARIA_LABEL_ID, FLYOUT_CANCEL_BUTTON, FLYOUT_CONTINUE_BUTTON } from '../constants'; import { Errors } from '../creation_response_components'; -import { DocumentCreationLogic } from '../'; +import { DocumentCreationLogic } from '../index'; import './paste_json_text.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/show_creation_modes.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/show_creation_modes.test.tsx index 2c66ae56dd3ce..739580d039a36 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/show_creation_modes.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/show_creation_modes.test.tsx @@ -8,10 +8,13 @@ import { setMockActions } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; + import { EuiButtonEmpty } from '@elastic/eui'; import { DocumentCreationButtons } from '../'; + import { ShowCreationModes } from './'; describe('ShowCreationModes', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/show_creation_modes.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/show_creation_modes.tsx index b67c7689d816f..d46b9acbb63d7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/show_creation_modes.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/show_creation_modes.tsx @@ -6,9 +6,9 @@ */ import React from 'react'; + import { useActions } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiFlyoutHeader, EuiTitle, @@ -16,9 +16,10 @@ import { EuiFlyoutFooter, EuiButtonEmpty, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { FLYOUT_ARIA_LABEL_ID, FLYOUT_CANCEL_BUTTON } from '../constants'; -import { DocumentCreationLogic, DocumentCreationButtons } from '../'; +import { DocumentCreationLogic, DocumentCreationButtons } from '../index'; export const ShowCreationModes: React.FC = () => { const { closeDocumentCreation } = useActions(DocumentCreationLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.test.tsx index cee76ebe6857e..7dc8952a18688 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.test.tsx @@ -8,10 +8,13 @@ import { setMockValues, setMockActions, rerender } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFilePicker, EuiButtonEmpty, EuiButton } from '@elastic/eui'; import { Errors } from '../creation_response_components'; + import { UploadJsonFile, FlyoutHeader, FlyoutBody, FlyoutFooter } from './upload_json_file'; describe('UploadJsonFile', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.tsx index cab79a929f7b9..5d50ae55fcd10 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.tsx @@ -6,9 +6,9 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiFlyoutHeader, EuiTitle, @@ -22,12 +22,13 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { AppLogic } from '../../../app_logic'; import { FLYOUT_ARIA_LABEL_ID, FLYOUT_CANCEL_BUTTON, FLYOUT_CONTINUE_BUTTON } from '../constants'; import { Errors } from '../creation_response_components'; -import { DocumentCreationLogic } from '../'; +import { DocumentCreationLogic } from '../index'; export const UploadJsonFile: React.FC = () => ( <> diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/errors.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/errors.test.tsx index 7ac97ae81b6ca..f03989aeaf5a3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/errors.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/errors.test.tsx @@ -8,7 +8,9 @@ import { setMockValues } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiCallOut } from '@elastic/eui'; import { Errors } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/errors.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/errors.tsx index 618828182e67d..3564d8ad088ee 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/errors.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/errors.tsx @@ -6,12 +6,13 @@ */ import React from 'react'; + import { useValues } from 'kea'; import { EuiCallOut } from '@elastic/eui'; import { DOCUMENT_CREATION_ERRORS, DOCUMENT_CREATION_WARNINGS } from '../constants'; -import { DocumentCreationLogic } from '../'; +import { DocumentCreationLogic } from '../index'; export const Errors: React.FC = () => { const { errors, warnings } = useValues(DocumentCreationLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary.test.tsx index 9558d23fa3a77..f53f94322879c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary.test.tsx @@ -8,15 +8,19 @@ import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFlyoutBody, EuiCallOut, EuiButton } from '@elastic/eui'; +import { FlyoutHeader, FlyoutBody, FlyoutFooter } from './summary'; import { InvalidDocumentsSummary, ValidDocumentsSummary, SchemaFieldsSummary, } from './summary_sections'; -import { Summary, FlyoutHeader, FlyoutBody, FlyoutFooter } from './summary'; + +import { Summary } from './'; describe('Summary', () => { const values = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary.tsx index 673c6726afb5d..8361afe62e1ca 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary.tsx @@ -6,9 +6,9 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiFlyoutHeader, EuiTitle, @@ -19,10 +19,11 @@ import { EuiFlexItem, EuiButton, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { DocumentCreationLogic } from '../'; import { FLYOUT_ARIA_LABEL_ID, FLYOUT_CLOSE_BUTTON, DOCUMENT_CREATION_ERRORS } from '../constants'; import { DocumentCreationStep } from '../types'; -import { DocumentCreationLogic } from '../'; import { InvalidDocumentsSummary, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_documents.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_documents.test.tsx index 0704d465bbac4..cd8209bafed3f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_documents.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_documents.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiCodeBlock, EuiCallOut } from '@elastic/eui'; import { ExampleDocumentJson, MoreDocumentsText } from './summary_documents'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_documents.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_documents.tsx index be19a7677a1ab..0dad75cb1f98f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_documents.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_documents.tsx @@ -7,8 +7,8 @@ import React, { Fragment } from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiCodeBlock, EuiCallOut, EuiTitle, EuiText, EuiSpacer } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; interface ExampleDocumentJsonProps { document: object; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_section.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_section.test.tsx index 41028d61c55f2..24fa2766cb15d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_section.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_section.test.tsx @@ -6,7 +6,9 @@ */ import React, { ReactElement } from 'react'; + import { shallow } from 'enzyme'; + import { EuiAccordion, EuiIcon } from '@elastic/eui'; import { SummarySectionAccordion, SummarySectionEmpty } from './summary_section'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_sections.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_sections.test.tsx index 9ead42f33521f..7eb9f3f46036d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_sections.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_sections.test.tsx @@ -8,11 +8,13 @@ import { setMockValues } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiBadge } from '@elastic/eui'; -import { SummarySectionAccordion, SummarySectionEmpty } from './summary_section'; + import { ExampleDocumentJson, MoreDocumentsText } from './summary_documents'; +import { SummarySectionAccordion, SummarySectionEmpty } from './summary_section'; import { InvalidDocumentsSummary, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_sections.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_sections.tsx index 637188132d6bc..f2e863c2a9983 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_sections.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_response_components/summary_sections.tsx @@ -6,15 +6,16 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiBadge } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { DocumentCreationLogic } from '../'; -import { SummarySectionAccordion, SummarySectionEmpty } from './summary_section'; import { ExampleDocumentJson, MoreDocumentsText } from './summary_documents'; +import { SummarySectionAccordion, SummarySectionEmpty } from './summary_section'; export const InvalidDocumentsSummary: React.FC = () => { const { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.test.tsx index 4b90acfbc37a8..7cbcc6b17e047 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.test.tsx @@ -9,8 +9,11 @@ import { setMockActions } from '../../../__mocks__/kea.mock'; import '../../__mocks__/engine_logic.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiCard } from '@elastic/eui'; + import { EuiCardTo } from '../../../shared/react_router_helpers'; import { DocumentCreationButtons } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.tsx index ec9c6615f5b8c..6d3caca87dcc3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.tsx @@ -6,10 +6,9 @@ */ import React from 'react'; + import { useActions } from 'kea'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; import { EuiText, EuiCode, @@ -20,6 +19,8 @@ import { EuiCard, EuiIcon, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiCardTo } from '../../../shared/react_router_helpers'; import { DOCS_PREFIX, ENGINE_CRAWLER_PATH } from '../../routes'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_flyout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_flyout.test.tsx index 4c5375d78f95f..66995b8d20dfe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_flyout.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_flyout.test.tsx @@ -8,7 +8,9 @@ import { setMockValues, setMockActions } from '../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFlyout } from '@elastic/eui'; import { @@ -18,9 +20,8 @@ import { UploadJsonFile, } from './creation_mode_components'; import { Summary } from './creation_response_components'; -import { DocumentCreationStep } from './types'; - import { DocumentCreationFlyout, FlyoutContent } from './document_creation_flyout'; +import { DocumentCreationStep } from './types'; describe('DocumentCreationFlyout', () => { const values = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_flyout.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_flyout.tsx index 16f805d7e86fd..159f3403d3740 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_flyout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_flyout.tsx @@ -6,14 +6,12 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; import { EuiPortal, EuiFlyout } from '@elastic/eui'; -import { DocumentCreationLogic } from './'; -import { DocumentCreationStep } from './types'; import { FLYOUT_ARIA_LABEL_ID } from './constants'; - import { ShowCreationModes, ApiCodeExample, @@ -21,6 +19,9 @@ import { UploadJsonFile, } from './creation_mode_components'; import { Summary } from './creation_response_components'; +import { DocumentCreationStep } from './types'; + +import { DocumentCreationLogic } from './'; export const DocumentCreationFlyout: React.FC = () => { const { closeDocumentCreation } = useActions(DocumentCreationLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts index 63c59343580d3..37d3d1577767f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts @@ -7,13 +7,9 @@ import { LogicMounter, mockHttpValues } from '../../../__mocks__'; -import { nextTick } from '@kbn/test/jest'; import dedent from 'dedent'; -jest.mock('./utils', () => ({ - readUploadedFileAsText: jest.fn(), -})); -import { readUploadedFileAsText } from './utils'; +import { nextTick } from '@kbn/test/jest'; jest.mock('../engine', () => ({ EngineLogic: { values: { engineName: 'test-engine' } }, @@ -21,6 +17,12 @@ jest.mock('../engine', () => ({ import { DOCUMENTS_API_JSON_EXAMPLE } from './constants'; import { DocumentCreationStep } from './types'; + +jest.mock('./utils', () => ({ + readUploadedFileAsText: jest.fn(), +})); +import { readUploadedFileAsText } from './utils'; + import { DocumentCreationLogic } from './'; describe('DocumentCreationLogic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.ts index 13d2618bcd31f..a0ef73bbcea21 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { kea, MakeLogicType } from 'kea'; import dedent from 'dedent'; +import { kea, MakeLogicType } from 'kea'; import { isPlainObject, chunk, uniq } from 'lodash'; import { HttpLogic } from '../../../shared/http'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.test.tsx index ab1679c455c6e..82fa9d3c82ce9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.test.tsx @@ -8,10 +8,13 @@ import { setMockActions } from '../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; + import { EuiButton } from '@elastic/eui'; import { DocumentCreationFlyout } from '../document_creation'; + import { DocumentCreationButton } from './document_creation_button'; describe('DocumentCreationButton', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.tsx index a05005fefa082..687f589d37594 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.tsx @@ -6,10 +6,11 @@ */ import React from 'react'; + import { useActions } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiButton } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { DocumentCreationLogic, DocumentCreationFlyout } from '../document_creation'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx index 55613077efdba..ba060b7497270 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx @@ -10,14 +10,17 @@ import { setMockValues, setMockActions } from '../../../__mocks__/kea.mock'; import { unmountHandler } from '../../../__mocks__/shallow_useeffect.mock'; import React from 'react'; -import { shallow } from 'enzyme'; import { useParams } from 'react-router-dom'; + +import { shallow } from 'enzyme'; + import { EuiPageContent, EuiBasicTable } from '@elastic/eui'; import { Loading } from '../../../shared/loading'; -import { DocumentDetail } from '.'; import { ResultFieldValue } from '../result'; +import { DocumentDetail } from '.'; + describe('DocumentDetail', () => { const values = { dataLoading: false, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.tsx index ca6af345de7ed..8f80978c29002 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.tsx @@ -6,9 +6,10 @@ */ import React, { useEffect } from 'react'; -import { useActions, useValues } from 'kea'; import { useParams } from 'react-router-dom'; +import { useActions, useValues } from 'kea'; + import { EuiButton, EuiPageHeader, @@ -21,15 +22,15 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { Loading } from '../../../shared/loading'; -import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { FlashMessages } from '../../../shared/flash_messages'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { Loading } from '../../../shared/loading'; import { useDecodedParams } from '../../utils/encode_path_params'; import { ResultFieldValue } from '../result'; +import { DOCUMENTS_TITLE } from './constants'; import { DocumentDetailLogic } from './document_detail_logic'; import { FieldDetails } from './types'; -import { DOCUMENTS_TITLE } from './constants'; const DOCUMENT_DETAIL_TITLE = (documentId: string) => i18n.translate('xpack.enterpriseSearch.appSearch.documentDetail.title', { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts index ef5ebad3aea13..d2683fac649a0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts @@ -15,9 +15,10 @@ import { mockEngineValues } from '../../__mocks__'; import { nextTick } from '@kbn/test/jest'; -import { DocumentDetailLogic } from './document_detail_logic'; import { InternalSchemaTypes } from '../../../shared/types'; +import { DocumentDetailLogic } from './document_detail_logic'; + describe('DocumentDetailLogic', () => { const { mount } = new LogicMounter(DocumentDetailLogic); const { http } = mockHttpValues; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.ts index 8b023fb585f86..17c2c788523d0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.ts @@ -6,11 +6,12 @@ */ import { kea, MakeLogicType } from 'kea'; + import { i18n } from '@kbn/i18n'; import { flashAPIErrors, setQueuedSuccessMessage } from '../../../shared/flash_messages'; -import { KibanaLogic } from '../../../shared/kibana'; import { HttpLogic } from '../../../shared/http'; +import { KibanaLogic } from '../../../shared/kibana'; import { ENGINE_DOCUMENTS_PATH } from '../../routes'; import { EngineLogic, generateEnginePath } from '../engine'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx index 43bbc6cc67895..ace76ae55c046 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx @@ -8,10 +8,12 @@ import { setMockValues } from '../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { DocumentCreationButton } from './document_creation_button'; import { SearchExperience } from './search_experience'; + import { Documents } from '.'; describe('Documents', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx index 7223900911512..8c3ae7fd24f6d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx @@ -7,16 +7,19 @@ import React from 'react'; -import { EuiPageHeader, EuiPageHeaderSection, EuiTitle, EuiCallOut, EuiSpacer } from '@elastic/eui'; import { useValues } from 'kea'; + +import { EuiPageHeader, EuiPageHeaderSection, EuiTitle, EuiCallOut, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { DocumentCreationButton } from './document_creation_button'; -import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { FlashMessages } from '../../../shared/flash_messages'; -import { DOCUMENTS_TITLE } from './constants'; -import { EngineLogic } from '../engine'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; + import { AppLogic } from '../../app_logic'; +import { EngineLogic } from '../engine'; + +import { DOCUMENTS_TITLE } from './constants'; +import { DocumentCreationButton } from './document_creation_button'; import { SearchExperience } from './search_experience'; interface Props { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_search_ui_config.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_search_ui_config.ts index b9577d9d0f07d..9fac068555db5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_search_ui_config.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_search_ui_config.ts @@ -6,6 +6,7 @@ */ import { Schema } from '../../../../shared/types'; + import { Fields } from './types'; export const buildSearchUIConfig = (apiConnector: object, schema: Schema, fields: Fields) => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_sort_options.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_sort_options.ts index ab3a943ef2f55..54cf2bdd4f257 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_sort_options.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_sort_options.ts @@ -7,8 +7,8 @@ import { flatten } from 'lodash'; -import { Fields, SortOption, SortDirection } from './types'; import { ASCENDING, DESCENDING } from './constants'; +import { Fields, SortOption, SortDirection } from './types'; const fieldNameToSortOptions = (fieldName: string): SortOption[] => ['asc', 'desc'].map((direction) => ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.test.tsx index e62e4521927dc..6ed2d7edc9639 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; + import { EuiButton } from '@elastic/eui'; import { CustomizationCallout } from './customization_callout'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.tsx index 8954549f74651..48a9fcdeaa878 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.tsx @@ -6,9 +6,9 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiButton, EuiFlexGroup, EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; interface Props { onClick(): void; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.test.tsx index 11e13f4222abb..332c5b822eb6d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.test.tsx @@ -8,7 +8,9 @@ import { setMockValues, setMockActions } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiButton, EuiButtonEmpty } from '@elastic/eui'; import { CustomizationModal } from './customization_modal'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.tsx index 2d3604b2ba279..e05fc10053ff1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.tsx @@ -7,6 +7,8 @@ import React, { useState, useMemo } from 'react'; +import { useValues } from 'kea'; + import { EuiButton, EuiButtonEmpty, @@ -21,7 +23,6 @@ import { EuiOverlayMask, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { useValues } from 'kea'; import { EngineLogic } from '../../engine'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.test.tsx index aecb4cc154117..028a9af21311f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.test.tsx @@ -25,8 +25,9 @@ jest.mock('react', () => ({ })); import React from 'react'; -import { act } from 'react-dom/test-utils'; + import { mount, ReactWrapper } from 'enzyme'; +import { act } from 'react-dom/test-utils'; import { useSearchContextState, useSearchContextActions } from './hooks'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.test.tsx index 5fe47d5942ab8..b55163ca9843a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; + // @ts-expect-error types are not available for this package yet import { Paging, ResultsPerPage } from '@elastic/react-search-ui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.tsx index 846671c62de82..d81b056842642 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.tsx @@ -10,6 +10,7 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; // @ts-expect-error types are not available for this package yet import { Paging, ResultsPerPage } from '@elastic/react-search-ui'; + import { PagingView, ResultsPerPageView } from './views'; export const Pagination: React.FC<{ 'aria-label': string }> = ({ 'aria-label': ariaLabel }) => ( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx index b0dccf0583e2f..bfa5c8264fece 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx @@ -8,21 +8,24 @@ import '../../../../__mocks__/enterprise_search_url.mock'; import { setMockValues } from '../../../../__mocks__'; +import React from 'react'; + +import { shallow, ShallowWrapper } from 'enzyme'; + +// @ts-expect-error types are not available for this package yet +import { SearchProvider, Facet } from '@elastic/react-search-ui'; + jest.mock('../../../../shared/use_local_storage', () => ({ useLocalStorage: jest.fn(), })); import { useLocalStorage } from '../../../../shared/use_local_storage'; -import React from 'react'; -// @ts-expect-error types are not available for this package yet -import { SearchProvider, Facet } from '@elastic/react-search-ui'; -import { shallow, ShallowWrapper } from 'enzyme'; - import { CustomizationCallout } from './customization_callout'; import { CustomizationModal } from './customization_modal'; + import { Fields } from './types'; -import { SearchExperience } from './search_experience'; +import { SearchExperience } from './'; describe('SearchExperience', () => { const values = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx index 6ae4f264d7c74..6fbc6305edb25 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx @@ -7,13 +7,14 @@ import React, { useState } from 'react'; -import { i18n } from '@kbn/i18n'; import { useValues } from 'kea'; + import { EuiButton, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; // @ts-expect-error types are not available for this package yet; import { SearchProvider, SearchBox, Sorting, Facet } from '@elastic/react-search-ui'; // @ts-expect-error types are not available for this package yet import AppSearchAPIConnector from '@elastic/search-ui-app-search-connector'; +import { i18n } from '@kbn/i18n'; import './search_experience.scss'; @@ -21,14 +22,14 @@ import { externalUrl } from '../../../../shared/enterprise_search_url'; import { useLocalStorage } from '../../../../shared/use_local_storage'; import { EngineLogic } from '../../engine'; -import { Fields, SortOption } from './types'; -import { SearchBoxView, SortingView, MultiCheckboxFacetsView } from './views'; -import { SearchExperienceContent } from './search_experience_content'; import { buildSearchUIConfig } from './build_search_ui_config'; -import { CustomizationCallout } from './customization_callout'; -import { CustomizationModal } from './customization_modal'; import { buildSortOptions } from './build_sort_options'; import { ASCENDING, DESCENDING } from './constants'; +import { CustomizationCallout } from './customization_callout'; +import { CustomizationModal } from './customization_modal'; +import { SearchExperienceContent } from './search_experience_content'; +import { Fields, SortOption } from './types'; +import { SearchBoxView, SortingView, MultiCheckboxFacetsView } from './views'; const RECENTLY_UPLOADED = i18n.translate( 'xpack.enterpriseSearch.appSearch.documents.search.sortBy.option.recentlyUploaded', diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx index 737e3ea1b2999..49f51c2010e3a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx @@ -6,18 +6,20 @@ */ import { setMockValues } from '../../../../__mocks__/kea.mock'; -import { setMockSearchContextState } from './__mocks__/hooks.mock'; import React from 'react'; import { shallow, mount } from 'enzyme'; + // @ts-expect-error types are not available for this package yet import { Results } from '@elastic/react-search-ui'; -import { ResultView } from './views'; -import { Pagination } from './pagination'; import { SchemaTypes } from '../../../../shared/types'; + +import { setMockSearchContextState } from './__mocks__/hooks.mock'; +import { Pagination } from './pagination'; import { SearchExperienceContent } from './search_experience_content'; +import { ResultView } from './views'; describe('SearchExperienceContent', () => { const searchState = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx index 45c20d8ffce2c..91db26ac676c9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx @@ -7,20 +7,22 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; +import { useValues } from 'kea'; + import { EuiFlexGroup, EuiSpacer, EuiButton, EuiEmptyPrompt } from '@elastic/eui'; // @ts-expect-error types are not available for this package yet import { Results, Paging, ResultsPerPage } from '@elastic/react-search-ui'; -import { useValues } from 'kea'; +import { i18n } from '@kbn/i18n'; -import { ResultView } from './views'; -import { Pagination } from './pagination'; -import { useSearchContextState } from './hooks'; -import { DocumentCreationButton } from '../document_creation_button'; import { AppLogic } from '../../../app_logic'; -import { EngineLogic } from '../../engine'; import { DOCS_PREFIX } from '../../../routes'; +import { EngineLogic } from '../../engine'; import { Result } from '../../result/types'; +import { DocumentCreationButton } from '../document_creation_button'; + +import { useSearchContextState } from './hooks'; +import { Pagination } from './pagination'; +import { ResultView } from './views'; export const SearchExperienceContent: React.FC = () => { const { resultSearchTerm, totalResults, wasSearched } = useSearchContextState(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.test.tsx index 03b9e33f89fef..28cd126e5c004 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; + import { EuiPagination } from '@elastic/eui'; import { PagingView } from './paging_view'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.test.tsx index e06603894c288..24685aef71078 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.test.tsx @@ -9,10 +9,11 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { ResultView } from '.'; import { SchemaTypes } from '../../../../../shared/types'; import { Result } from '../../../result/result'; +import { ResultView } from '.'; + describe('ResultView', () => { const result = { id: { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.tsx index 9dd3fcea5f754..b133780310a4c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.tsx @@ -7,9 +7,9 @@ import React from 'react'; -import { Result as ResultType } from '../../../result/types'; import { Schema } from '../../../../../shared/types'; import { Result } from '../../../result/result'; +import { Result as ResultType } from '../../../result/types'; export interface Props { result: ResultType; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.test.tsx index 70e4d7e4e1878..24db762e26e32 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; + import { EuiSelect } from '@elastic/eui'; import { ResultsPerPageView } from '.'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.tsx index b57944042e67f..5056d56d1f3d0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.tsx @@ -7,8 +7,8 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiSelect, EuiSelectOption } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; const wrapResultsPerPageOptionForEuiSelect: (option: number) => EuiSelectOption = (option) => ({ text: option, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/search_box_view.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/search_box_view.test.tsx index 182e2ea222f90..a35fcefb30ac6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/search_box_view.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/search_box_view.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; + import { EuiFieldSearch } from '@elastic/eui'; import { SearchBoxView } from './search_box_view'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/sorting_view.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/sorting_view.test.tsx index 4f7317a2bf5d0..a147f45feef14 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/sorting_view.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/sorting_view.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; + import { EuiSelect } from '@elastic/eui'; import { SortingView } from '.'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/sorting_view.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/sorting_view.tsx index 047caf6ca1e3b..e3f21b67a6530 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/sorting_view.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/sorting_view.tsx @@ -7,8 +7,8 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiSelect, EuiSelectOption } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; interface Option { label: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts index fbe08cbeb939f..664a3006cfa2c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts @@ -10,6 +10,7 @@ import { kea, MakeLogicType } from 'kea'; import { HttpLogic } from '../../../shared/http'; import { IIndexingStatus } from '../../../shared/types'; + import { EngineDetails } from './types'; interface EngineValues { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx index 8ed36ad5ab006..1781883aa6532 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx @@ -9,7 +9,9 @@ import { setMockValues, rerender } from '../../../__mocks__'; import { mockEngineValues } from '../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiBadge, EuiIcon } from '@elastic/eui'; import { EngineNav } from './engine_nav'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx index b1b31c245eb99..447e4d678bcdb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx @@ -6,11 +6,13 @@ */ import React from 'react'; + import { useValues } from 'kea'; import { EuiText, EuiBadge, EuiIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { getAppSearchUrl } from '../../../shared/enterprise_search_url'; import { SideNavLink, SideNavItem } from '../../../shared/layout'; import { AppLogic } from '../../app_logic'; import { @@ -27,23 +29,23 @@ import { ENGINE_SEARCH_UI_PATH, ENGINE_API_LOGS_PATH, } from '../../routes'; -import { getAppSearchUrl } from '../../../shared/enterprise_search_url'; -import { ENGINES_TITLE } from '../engines'; -import { OVERVIEW_TITLE } from '../engine_overview'; import { ANALYTICS_TITLE } from '../analytics'; -import { DOCUMENTS_TITLE } from '../documents'; -import { SCHEMA_TITLE } from '../schema'; +import { API_LOGS_TITLE } from '../api_logs'; import { CRAWLER_TITLE } from '../crawler'; -import { RELEVANCE_TUNING_TITLE } from '../relevance_tuning'; -import { SYNONYMS_TITLE } from '../synonyms'; import { CURATIONS_TITLE } from '../curations'; +import { DOCUMENTS_TITLE } from '../documents'; +import { OVERVIEW_TITLE } from '../engine_overview'; +import { ENGINES_TITLE } from '../engines'; +import { RELEVANCE_TUNING_TITLE } from '../relevance_tuning'; import { RESULT_SETTINGS_TITLE } from '../result_settings'; +import { SCHEMA_TITLE } from '../schema'; import { SEARCH_UI_TITLE } from '../search_ui'; -import { API_LOGS_TITLE } from '../api_logs'; +import { SYNONYMS_TITLE } from '../synonyms'; -import { EngineLogic, generateEnginePath } from './'; import { EngineDetails } from './types'; +import { EngineLogic, generateEnginePath } from './'; + import './engine_nav.scss'; export const EngineNav: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx index cff05b296846b..3740882dee3db 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx @@ -6,17 +6,18 @@ */ import '../../../__mocks__/react_router_history.mock'; -import { unmountHandler } from '../../../__mocks__/shallow_useeffect.mock'; import { mockFlashMessageHelpers, setMockValues, setMockActions } from '../../../__mocks__'; +import { unmountHandler } from '../../../__mocks__/shallow_useeffect.mock'; import { mockEngineValues } from '../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; import { Switch, Redirect, useParams } from 'react-router-dom'; +import { shallow } from 'enzyme'; + import { Loading } from '../../../shared/loading'; -import { EngineOverview } from '../engine_overview'; import { AnalyticsRouter } from '../analytics'; +import { EngineOverview } from '../engine_overview'; import { RelevanceTuning } from '../relevance_tuning'; import { EngineRouter } from './engine_router'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx index 257bb1e69ad7f..2f1c3bc57d331 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx @@ -7,12 +7,14 @@ import React, { useEffect } from 'react'; import { Route, Switch, Redirect, useParams } from 'react-router-dom'; + import { useValues, useActions } from 'kea'; import { i18n } from '@kbn/i18n'; -import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { setQueuedErrorMessage } from '../../../shared/flash_messages'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { Loading } from '../../../shared/loading'; import { AppLogic } from '../../app_logic'; // TODO: Uncomment and add more routes as we migrate them @@ -31,13 +33,11 @@ import { // ENGINE_SEARCH_UI_PATH, // ENGINE_API_LOGS_PATH, } from '../../routes'; -import { ENGINES_TITLE } from '../engines'; -import { OVERVIEW_TITLE } from '../engine_overview'; - -import { Loading } from '../../../shared/loading'; -import { EngineOverview } from '../engine_overview'; import { AnalyticsRouter } from '../analytics'; import { DocumentDetail, Documents } from '../documents'; +import { OVERVIEW_TITLE } from '../engine_overview'; +import { EngineOverview } from '../engine_overview'; +import { ENGINES_TITLE } from '../engines'; import { RelevanceTuning } from '../relevance_tuning'; import { EngineLogic } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/types.ts index d20f9890cd4db..b50e8eb555dc9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ApiToken } from '../credentials/types'; import { Schema, SchemaConflicts, IIndexingStatus } from '../../../shared/types'; +import { ApiToken } from '../credentials/types'; export interface Engine { name: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.test.tsx index 7b52a04d07958..42fa9777563db 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.test.tsx @@ -8,6 +8,7 @@ import '../../../__mocks__/engine_logic.mock'; import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; import { EuiButtonTo } from '../../../../shared/react_router_helpers'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx index d7290533f4f7b..625ba2e905840 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx @@ -17,9 +17,9 @@ import { import { EuiButtonTo } from '../../../../shared/react_router_helpers'; import { ENGINE_API_LOGS_PATH } from '../../../routes'; +import { RECENT_API_EVENTS } from '../../api_logs/constants'; import { generateEnginePath } from '../../engine'; -import { RECENT_API_EVENTS } from '../../api_logs/constants'; import { VIEW_API_LOGS } from '../constants'; export const RecentApiLogs: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx index 867b78f859a22..a2f35b4709939 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx @@ -9,6 +9,7 @@ import { setMockValues } from '../../../../__mocks__/kea.mock'; import '../../../__mocks__/engine_logic.mock'; import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; import { EuiButtonTo } from '../../../../shared/react_router_helpers'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx index 4fa2246ee6170..6bd973ae142a8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { useValues } from 'kea'; import { @@ -21,12 +22,12 @@ import { import { EuiButtonTo } from '../../../../shared/react_router_helpers'; import { ENGINE_ANALYTICS_PATH, ENGINE_API_LOGS_PATH } from '../../../routes'; +import { AnalyticsChart, convertToChartData } from '../../analytics'; +import { TOTAL_QUERIES, TOTAL_API_OPERATIONS } from '../../analytics/constants'; import { generateEnginePath } from '../../engine'; -import { TOTAL_QUERIES, TOTAL_API_OPERATIONS } from '../../analytics/constants'; import { VIEW_ANALYTICS, VIEW_API_LOGS, LAST_7_DAYS } from '../constants'; -import { AnalyticsChart, convertToChartData } from '../../analytics'; -import { EngineOverviewLogic } from '../'; +import { EngineOverviewLogic } from '../index'; export const TotalCharts: React.FC = () => { const { startDate, queriesPerDay, operationsPerDay } = useValues(EngineOverviewLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_stats.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_stats.test.tsx index a897c635eeadd..7fcda61073c5b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_stats.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_stats.test.tsx @@ -8,9 +8,11 @@ import { setMockValues } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { AnalyticsCards } from '../../analytics'; + import { TotalStats } from './total_stats'; describe('TotalStats', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_stats.tsx index 3eb208fa86504..35c6fa439a416 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_stats.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_stats.tsx @@ -6,12 +6,12 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { TOTAL_QUERIES, TOTAL_DOCUMENTS, TOTAL_CLICKS } from '../../analytics/constants'; import { AnalyticsCards } from '../../analytics'; - -import { EngineOverviewLogic } from '../'; +import { TOTAL_QUERIES, TOTAL_DOCUMENTS, TOTAL_CLICKS } from '../../analytics/constants'; +import { EngineOverviewLogic } from '../index'; export const TotalStats: React.FC = () => { const { totalQueries, documentCount, totalClicks } = useValues(EngineOverviewLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/unavailable_prompt.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/unavailable_prompt.test.tsx index 7cd042a646e73..4c61a713b3793 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/unavailable_prompt.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/unavailable_prompt.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiEmptyPrompt } from '@elastic/eui'; import { UnavailablePrompt } from './unavailable_prompt'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/unavailable_prompt.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/unavailable_prompt.tsx index 2916be92ead99..69e79ecfc580d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/unavailable_prompt.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/unavailable_prompt.tsx @@ -7,8 +7,8 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiEmptyPrompt } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; export const UnavailablePrompt: React.FC = () => ( { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx index 9e673d48a7e5b..77552b36af239 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx @@ -6,16 +6,19 @@ */ import React, { useEffect } from 'react'; + import { useActions, useValues } from 'kea'; +import { Loading } from '../../../shared/loading'; import { AppLogic } from '../../app_logic'; import { EngineLogic } from '../engine'; -import { Loading } from '../../../shared/loading'; -import { EngineOverviewLogic } from './'; import { EmptyEngineOverview } from './engine_overview_empty'; + import { EngineOverviewMetrics } from './engine_overview_metrics'; +import { EngineOverviewLogic } from './'; + export const EngineOverview: React.FC = () => { const { myRole: { canManageEngineDocuments, canViewEngineCredentials }, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.test.tsx index 5947618e59c16..9066283229a04 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.test.tsx @@ -6,12 +6,15 @@ */ import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; + import { EuiButton } from '@elastic/eui'; import { docLinks } from '../../../shared/doc_links'; import { DocumentCreationButtons, DocumentCreationFlyout } from '../document_creation'; + import { EmptyEngineOverview } from './engine_overview_empty'; describe('EmptyEngineOverview', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx index 6a0c46286907d..81bf3716edfb8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx @@ -7,7 +7,6 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiPageHeader, EuiPageHeaderSection, @@ -15,6 +14,7 @@ import { EuiTitle, EuiButton, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { DOCS_PREFIX } from '../../routes'; import { DocumentCreationButtons, DocumentCreationFlyout } from '../document_creation'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.test.tsx index ebcdbaf1f7f09..638c8b0da87ce 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.test.tsx @@ -8,6 +8,7 @@ import { setMockValues } from '../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { UnavailablePrompt, TotalStats, TotalCharts, RecentApiLogs } from './components'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx index ffb1a25d21cae..34a154ca83741 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx @@ -6,15 +6,16 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiPageHeader, EuiTitle, EuiSpacer } from '@elastic/eui'; - -import { EngineOverviewLogic } from './'; +import { i18n } from '@kbn/i18n'; import { UnavailablePrompt, TotalStats, TotalCharts, RecentApiLogs } from './components'; +import { EngineOverviewLogic } from './'; + export const EngineOverviewMetrics: React.FC = () => { const { apiLogsUnavailable } = useValues(EngineOverviewLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/icons.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/icons.test.tsx index 9c2818f9907a4..33ca5bd8248c9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/icons.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/icons.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EngineIcon } from './engine_icon'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx index b04226b6b1dfb..ac540eec3ff91 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx @@ -9,7 +9,9 @@ import '../../../../__mocks__/kea.mock'; import { mockTelemetryActions } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiEmptyPrompt, EuiButton } from '@elastic/eui'; import { EmptyState } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx index 60a454a5707c9..5419a175c9eff 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx @@ -6,13 +6,15 @@ */ import React from 'react'; + import { useActions } from 'kea'; + import { EuiPageContent, EuiEmptyPrompt, EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { TelemetryLogic } from '../../../../shared/telemetry'; import { getAppSearchUrl } from '../../../../shared/enterprise_search_url'; import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome'; +import { TelemetryLogic } from '../../../../shared/telemetry'; import { CREATE_ENGINES_PATH } from '../../../routes'; import { EnginesOverviewHeader } from './header'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.test.tsx index 6dedb90690ace..5ccd2c552ef02 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.test.tsx @@ -10,6 +10,7 @@ import '../../../../__mocks__/enterprise_search_url.mock'; import { mockTelemetryActions } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { EnginesOverviewHeader } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx index 8a8227821b492..290270c08258c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { useActions } from 'kea'; + import { EuiPageHeader, EuiPageHeaderSection, @@ -17,8 +19,8 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { TelemetryLogic } from '../../../../shared/telemetry'; import { getAppSearchUrl } from '../../../../shared/enterprise_search_url'; +import { TelemetryLogic } from '../../../../shared/telemetry'; export const EnginesOverviewHeader: React.FC = () => { const { sendAppSearchTelemetry } = useActions(TelemetryLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.test.tsx index 4adc8c11fa0dd..f7ccfea4bb4d4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiLoadingContent } from '@elastic/eui'; import { LoadingState } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.tsx index 48160602106cd..155d8263c484d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; + import { EuiPageContent, EuiSpacer, EuiLoadingContent } from '@elastic/eui'; import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome'; + import { EnginesOverviewHeader } from './header'; export const LoadingState: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.test.ts index c25f60e47598e..9e9bfc4973124 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.test.ts @@ -10,6 +10,7 @@ import { LogicMounter, mockHttpValues } from '../../../__mocks__'; import { nextTick } from '@kbn/test/jest'; import { EngineDetails } from '../engine/types'; + import { EnginesLogic } from './'; describe('EnginesLogic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx index f4aeb60a88250..cdc06dbbe3921 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx @@ -9,6 +9,7 @@ import '../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions, rerender } from '../../../__mocks__'; import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; import { LoadingState, EmptyState } from './components'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx index c13db688fc2b6..2835c8b7cb3c4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx @@ -6,7 +6,9 @@ */ import React, { useEffect } from 'react'; + import { useValues, useActions } from 'kea'; + import { EuiPageContent, EuiPageContentHeader, @@ -15,17 +17,17 @@ import { EuiSpacer, } from '@elastic/eui'; -import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; -import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { FlashMessages } from '../../../shared/flash_messages'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { LicensingLogic } from '../../../shared/licensing'; +import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { EngineIcon } from './assets/engine_icon'; import { MetaEngineIcon } from './assets/meta_engine_icon'; -import { ENGINES_TITLE, META_ENGINES_TITLE } from './constants'; import { EnginesOverviewHeader, LoadingState, EmptyState } from './components'; -import { EnginesTable } from './engines_table'; +import { ENGINES_TITLE, META_ENGINES_TITLE } from './constants'; import { EnginesLogic } from './engines_logic'; +import { EnginesTable } from './engines_table'; import './engines_overview.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx index 65b96035eaaee..d6f0946164ea4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx @@ -9,10 +9,13 @@ import '../../../__mocks__/enterprise_search_url.mock'; import { mockTelemetryActions, mountWithIntl } from '../../../__mocks__'; import React from 'react'; + import { EuiBasicTable, EuiPagination, EuiButtonEmpty } from '@elastic/eui'; + import { EuiLinkTo } from '../../../shared/react_router_helpers'; import { EngineDetails } from '../engine/types'; + import { EnginesTable } from './engines_table'; describe('EnginesTable', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx index b439d7e6bdf33..d41c5c908c08f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx @@ -6,18 +6,19 @@ */ import React from 'react'; + import { useActions } from 'kea'; + import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui'; -import { FormattedMessage, FormattedDate, FormattedNumber } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; - -import { TelemetryLogic } from '../../../shared/telemetry'; -import { EuiLinkTo } from '../../../shared/react_router_helpers'; -import { generateEncodedPath } from '../../utils/encode_path_params'; -import { ENGINE_PATH } from '../../routes'; +import { FormattedMessage, FormattedDate, FormattedNumber } from '@kbn/i18n/react'; import { ENGINES_PAGE_SIZE } from '../../../../../common/constants'; +import { EuiLinkTo } from '../../../shared/react_router_helpers'; +import { TelemetryLogic } from '../../../shared/telemetry'; import { UNIVERSAL_LANGUAGE } from '../../constants'; +import { ENGINE_PATH } from '../../routes'; +import { generateEncodedPath } from '../../utils/encode_path_params'; import { EngineDetails } from '../engine/types'; interface EnginesTablePagination { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/error_connecting/error_connecting.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/error_connecting/error_connecting.test.tsx index 6ff33385df9a5..9ec3fdda63656 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/error_connecting/error_connecting.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/error_connecting/error_connecting.test.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { ErrorStatePrompt } from '../../../shared/error_state'; + import { ErrorConnecting } from './'; describe('ErrorConnecting', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/error_connecting/error_connecting.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/error_connecting/error_connecting.tsx index ad5eff6c4dacf..d7fde0cd5dd25 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/error_connecting/error_connecting.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/error_connecting/error_connecting.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { EuiPageContent } from '@elastic/eui'; import { ErrorStatePrompt } from '../../../shared/error_state'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx index 2d39b5a9aa05c..f76ad78c847d1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import React from 'react'; + import { EuiSpacer, EuiPageHeader, @@ -13,7 +15,6 @@ import { EuiPageContentBody, EuiPageContent, } from '@elastic/eui'; -import React from 'react'; import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { Schema } from '../../../shared/types'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.test.tsx index d0bc1c9a88c5f..124edb6871453 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.test.tsx @@ -6,14 +6,16 @@ */ import '../../../../__mocks__/shallow_useeffect.mock'; -import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; -import { mountWithIntl } from '../../../../__mocks__'; +import { setMockValues, setMockActions, mountWithIntl } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiCallOut, EuiLink } from '@elastic/eui'; import { LogRetentionOptions } from '../'; + import { LogRetentionCallout } from './'; describe('LogRetentionCallout', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.tsx index 0252a788f75ef..235d977793161 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.tsx @@ -6,11 +6,12 @@ */ import React, { useEffect } from 'react'; + import { useValues, useActions } from 'kea'; +import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import { EuiLinkTo } from '../../../../shared/react_router_helpers'; @@ -19,7 +20,7 @@ import { SETTINGS_PATH } from '../../../routes'; import { ANALYTICS_TITLE } from '../../analytics'; import { API_LOGS_TITLE } from '../../api_logs'; -import { LogRetentionLogic, LogRetentionOptions, renderLogRetentionDate } from '../'; +import { LogRetentionLogic, LogRetentionOptions, renderLogRetentionDate } from '../index'; const TITLE_MAP = { [LogRetentionOptions.Analytics]: ANALYTICS_TITLE, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.test.tsx index 14615f6ac2dd9..854a9f1d8d162 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.test.tsx @@ -9,10 +9,13 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow, mount } from 'enzyme'; + import { EuiIconTip } from '@elastic/eui'; import { LogRetentionOptions, LogRetentionMessage } from '../'; + import { LogRetentionTooltip } from './'; describe('LogRetentionTooltip', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.tsx index e3b428baa6d9a..bf074ba0272f2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.tsx @@ -6,10 +6,11 @@ */ import React, { useEffect } from 'react'; + import { useValues, useActions } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiIconTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { LogRetentionLogic, LogRetentionMessage, LogRetentionOptions } from '../'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts index 9615aba5fdef4..19bd2af50aad9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts @@ -10,7 +10,8 @@ import { LogicMounter, mockHttpValues, mockFlashMessageHelpers } from '../../../ import { nextTick } from '@kbn/test/jest'; import { LogRetentionOptions } from './types'; -import { LogRetentionLogic } from './log_retention_logic'; + +import { LogRetentionLogic } from './'; describe('LogRetentionLogic', () => { const { mount } = new LogicMounter(LogRetentionLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.ts index 77d4cf395196a..ec078842dab55 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.ts @@ -7,8 +7,8 @@ import { kea, MakeLogicType } from 'kea'; -import { HttpLogic } from '../../../shared/http'; import { flashAPIErrors } from '../../../shared/flash_messages'; +import { HttpLogic } from '../../../shared/http'; import { LogRetentionOptions, LogRetention, LogRetentionServer } from './types'; import { convertLogRetentionFromServerToClient } from './utils/convert_log_retention'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.tsx index 0f231092a36e2..c7c4d90d91ce8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.tsx @@ -6,8 +6,9 @@ */ import React from 'react'; -import { FormattedDate, FormattedMessage } from '@kbn/i18n/react'; + import { i18n } from '@kbn/i18n'; +import { FormattedDate, FormattedMessage } from '@kbn/i18n/react'; import { LogRetentionOptions, LogRetentionSettings, LogRetentionPolicy } from '../types'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.test.tsx index be95261a35c25..cd71e37108927 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.test.tsx @@ -5,13 +5,14 @@ * 2.0. */ -import { setMockValues } from '../../../../__mocks__/kea.mock'; -import { mountWithIntl } from '../../../../__mocks__'; +import { setMockValues, mountWithIntl } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { LogRetentionOptions } from '../types'; + import { LogRetentionMessage } from './'; describe('LogRetentionMessage', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.tsx index 62bac44b122af..7d34a2567ba14 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { useValues } from 'kea'; import { AppLogic } from '../../../app_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx index 56e31ec6bf970..83e83c0f9ea43 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { EuiPageHeader, EuiPageHeaderSection, @@ -14,8 +15,8 @@ import { EuiPageContent, } from '@elastic/eui'; -import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { FlashMessages } from '../../../shared/flash_messages'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { RELEVANCE_TUNING_TITLE } from './constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts index 586a845ce382a..7f7bce1b7ba95 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts @@ -9,7 +9,7 @@ import { LogicMounter } from '../../../__mocks__'; import { BoostType } from './types'; -import { RelevanceTuningLogic } from './relevance_tuning_logic'; +import { RelevanceTuningLogic } from './'; describe('RelevanceTuningLogic', () => { const { mount } = new LogicMounter(RelevanceTuningLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx index 0c3749d1ccb3d..41428999b1e40 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx @@ -6,15 +6,17 @@ */ import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; + import { EuiPanel } from '@elastic/eui'; -import { ResultField } from './result_field'; -import { ResultHeader } from './result_header'; import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components'; import { SchemaTypes } from '../../../shared/types'; import { Result } from './result'; +import { ResultField } from './result_field'; +import { ResultHeader } from './result_header'; describe('Result', () => { const props = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx index d84b079ea9d72..7288fdf39f3ff 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx @@ -6,6 +6,7 @@ */ import React, { useState, useMemo } from 'react'; + import classNames from 'classnames'; import './result.scss'; @@ -14,13 +15,14 @@ import { EuiPanel, EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components'; -import { generateEncodedPath } from '../../utils/encode_path_params'; -import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../routes'; import { Schema } from '../../../shared/types'; -import { FieldValue, Result as ResultType } from './types'; +import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../routes'; +import { generateEncodedPath } from '../../utils/encode_path_params'; + import { ResultField } from './result_field'; import { ResultHeader } from './result_header'; +import { FieldValue, Result as ResultType } from './types'; interface Props { result: ResultType; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.test.tsx index 6869708627b8d..1e79266dd7e7d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { ResultField } from './result_field'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx index a1c3ccd93622a..003810ec40a8d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; -import { ResultFieldValue } from '.'; + import { FieldType, Raw, Snippet } from './types'; +import { ResultFieldValue } from '.'; + import './result_field.scss'; interface Props { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field_value.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field_value.test.tsx index e1cefa1d79469..c732c9c8216c0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field_value.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field_value.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; import { ResultFieldValue } from '.'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx index 9d90b3ae35a8f..dcefd0f6bc0b0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { ResultHeader } from './result_header'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx index e8cc8796440a9..52fa81943bb2e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { mount } from 'enzyme'; import { ResultHeaderItem } from './result_header_item'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/generic_confirmation_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/generic_confirmation_modal.test.tsx index 3e450b7a7bb70..8477f0e8e2ce2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/generic_confirmation_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/generic_confirmation_modal.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { GenericConfirmationModal } from './generic_confirmation_modal'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/generic_confirmation_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/generic_confirmation_modal.tsx index b792ace4dac3f..eb64fe6421d80 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/generic_confirmation_modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/generic_confirmation_modal.tsx @@ -6,7 +6,6 @@ */ import React, { ReactNode, useState } from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiButton, @@ -21,6 +20,7 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; interface GenericConfirmationModalProps { description: ReactNode; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.test.tsx index a6d0cab532729..494517a438372 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.test.tsx @@ -8,9 +8,11 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { LogRetentionOptions } from '../../log_retention'; + import { GenericConfirmationModal } from './generic_confirmation_modal'; import { LogRetentionConfirmationModal } from './log_retention_confirmation_modal'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.tsx index 52a2478d7158e..ca1fa9a8d0737 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.tsx @@ -6,12 +6,14 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiTextColor, EuiOverlayMask } from '@elastic/eui'; import { useActions, useValues } from 'kea'; +import { EuiTextColor, EuiOverlayMask } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + import { LogRetentionLogic, LogRetentionOptions } from '../../log_retention'; + import { GenericConfirmationModal } from './generic_confirmation_modal'; export const LogRetentionConfirmationModal: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx index 882b82979a511..aee23e61e76fe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx @@ -9,9 +9,11 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { LogRetention } from '../../log_retention/types'; + import { LogRetentionPanel } from './log_retention_panel'; describe('', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx index 3a40be9efd5db..76fdcdac58ad4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx @@ -6,11 +6,12 @@ */ import React, { useEffect } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiLink, EuiSpacer, EuiSwitch, EuiText, EuiTextColor, EuiTitle } from '@elastic/eui'; import { useActions, useValues } from 'kea'; +import { EuiLink, EuiSpacer, EuiSwitch, EuiText, EuiTextColor, EuiTitle } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + import { DOCS_PREFIX } from '../../../routes'; import { LogRetentionLogic, LogRetentionOptions, LogRetentionMessage } from '../../log_retention'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.test.tsx index fead8cda0c0e2..41d446b8e36fc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiPageContentBody } from '@elastic/eui'; import { Settings } from './settings'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx index c029cf344f18b..510075eba4abf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx @@ -15,10 +15,11 @@ import { EuiTitle, } from '@elastic/eui'; -import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { FlashMessages } from '../../../shared/flash_messages'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { LogRetentionPanel, LogRetentionConfirmationModal } from './log_retention'; + import { SETTINGS_TITLE } from './'; export const Settings: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.test.tsx index e8dcb6ff98358..0b4a86870a69d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.test.tsx @@ -6,10 +6,12 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SetupGuideLayout } from '../../../shared/setup_guide'; + import { SetupGuide } from './'; describe('SetupGuide', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx index befb06c719a39..3d96b22859fad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx @@ -6,15 +6,17 @@ */ import React from 'react'; + import { EuiSpacer, EuiTitle, EuiText } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { APP_SEARCH_PLUGIN } from '../../../../../common/constants'; -import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide'; import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide'; import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { DOCS_PREFIX } from '../../routes'; + import GettingStarted from './assets/getting_started.png'; export const SetupGuide: React.FC = () => ( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx index dc3c0b03148d9..0e8220266d613 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx @@ -11,13 +11,16 @@ import { setMockValues, setMockActions } from '../__mocks__'; import React from 'react'; import { Redirect } from 'react-router-dom'; + import { shallow } from 'enzyme'; import { Layout, SideNav, SideNavLink } from '../shared/layout'; -import { SetupGuide } from './components/setup_guide'; -import { ErrorConnecting } from './components/error_connecting'; -import { EnginesOverview } from './components/engines'; + import { EngineRouter } from './components/engine'; +import { EnginesOverview } from './components/engines'; +import { ErrorConnecting } from './components/error_connecting'; +import { SetupGuide } from './components/setup_guide'; + import { AppSearch, AppSearchUnconfigured, AppSearchConfigured, AppSearchNav } from './'; describe('AppSearch', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx index 918697422af6b..36ac3fb4dbc5b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx @@ -7,18 +7,26 @@ import React, { useEffect } from 'react'; import { Route, Redirect, Switch } from 'react-router-dom'; + import { useActions, useValues } from 'kea'; +import { APP_SEARCH_PLUGIN } from '../../../common/constants'; +import { InitialAppData } from '../../../common/types'; import { getAppSearchUrl } from '../shared/enterprise_search_url'; -import { KibanaLogic } from '../shared/kibana'; import { HttpLogic } from '../shared/http'; -import { AppLogic } from './app_logic'; -import { InitialAppData } from '../../../common/types'; - -import { APP_SEARCH_PLUGIN } from '../../../common/constants'; +import { KibanaLogic } from '../shared/kibana'; import { Layout, SideNav, SideNavLink } from '../shared/layout'; -import { EngineNav, EngineRouter } from './components/engine'; +import { NotFound } from '../shared/not_found'; +import { AppLogic } from './app_logic'; +import { Credentials, CREDENTIALS_TITLE } from './components/credentials'; +import { EngineNav, EngineRouter } from './components/engine'; +import { EnginesOverview, ENGINES_TITLE } from './components/engines'; +import { ErrorConnecting } from './components/error_connecting'; +import { Library } from './components/library'; +import { ROLE_MAPPINGS_TITLE } from './components/role_mappings'; +import { Settings, SETTINGS_TITLE } from './components/settings'; +import { SetupGuide } from './components/setup_guide'; import { ROOT_PATH, SETUP_GUIDE_PATH, @@ -30,15 +38,6 @@ import { LIBRARY_PATH, } from './routes'; -import { SetupGuide } from './components/setup_guide'; -import { ErrorConnecting } from './components/error_connecting'; -import { NotFound } from '../shared/not_found'; -import { EnginesOverview, ENGINES_TITLE } from './components/engines'; -import { Settings, SETTINGS_TITLE } from './components/settings'; -import { Credentials, CREDENTIALS_TITLE } from './components/credentials'; -import { ROLE_MAPPINGS_TITLE } from './components/role_mappings'; -import { Library } from './components/library'; - export const AppSearch: React.FC = (props) => { const { config } = useValues(KibanaLogic); return !config.host ? : ; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.test.tsx index 6ff33385df9a5..9ec3fdda63656 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.test.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { ErrorStatePrompt } from '../../../shared/error_state'; + import { ErrorConnecting } from './'; describe('ErrorConnecting', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx index cb1abc275d37f..afee20df106e8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx @@ -6,10 +6,11 @@ */ import React from 'react'; + import { EuiPage, EuiPageContent } from '@elastic/eui'; -import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { ErrorStatePrompt } from '../../../shared/error_state'; +import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; export const ErrorConnecting: React.FC = () => ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx index a9098689b3d0e..8631e6e2a51d4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx @@ -8,11 +8,13 @@ import { setMockValues, mockTelemetryActions } from '../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiCard } from '@elastic/eui'; -import { EuiButtonTo } from '../../../shared/react_router_helpers'; + import { APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; +import { EuiButtonTo } from '../../../shared/react_router_helpers'; import { ProductCard } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx index d31daeef54de9..20727e37460f1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx @@ -6,14 +6,16 @@ */ import React from 'react'; + import { useValues, useActions } from 'kea'; import { snakeCase } from 'lodash'; -import { i18n } from '@kbn/i18n'; + import { EuiCard, EuiTextColor } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { KibanaLogic } from '../../../shared/kibana'; import { EuiButtonTo } from '../../../shared/react_router_helpers'; import { TelemetryLogic } from '../../../shared/telemetry'; -import { KibanaLogic } from '../../../shared/kibana'; import './product_card.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx index 0d55e2ce21c74..9ee34634e3797 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx @@ -8,11 +8,13 @@ import { setMockValues } from '../../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiPage } from '@elastic/eui'; -import { SetupGuideCta } from '../setup_guide'; import { ProductCard } from '../product_card'; +import { SetupGuideCta } from '../setup_guide'; import { ProductSelector } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx index 910840f023bb2..f2476a5770c25 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { useValues } from 'kea'; + import { EuiPage, EuiPageBody, @@ -25,11 +27,10 @@ import { KibanaLogic } from '../../../shared/kibana'; import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; -import { ProductCard } from '../product_card'; -import { SetupGuideCta } from '../setup_guide'; - import AppSearchImage from '../../assets/app_search.png'; import WorkplaceSearchImage from '../../assets/workplace_search.png'; +import { ProductCard } from '../product_card'; +import { SetupGuideCta } from '../setup_guide'; interface ProductSelectorProps { access: { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.test.tsx index e2f3595d26974..44f06de7ff137 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.test.tsx @@ -6,10 +6,12 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SetupGuideLayout } from '../../../shared/setup_guide'; + import { SetupGuide } from './'; describe('SetupGuide', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx index 02327e01c5ede..c59742d7ccbea 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx @@ -6,14 +6,16 @@ */ import React from 'react'; + import { EuiSpacer, EuiTitle, EuiText } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { ENTERPRISE_SEARCH_PLUGIN } from '../../../../../common/constants'; -import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide'; import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide'; import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; + import GettingStarted from './assets/getting_started.png'; export const SetupGuide: React.FC = () => ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.test.tsx index 140e779df55d2..659af6d23c6d0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { SetupGuideCta } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.tsx index 7d32b11ba7ae8..17260cc15793a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.tsx @@ -6,8 +6,10 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; + import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + import { EuiPanelTo } from '../../../shared/react_router_helpers'; import CtaImage from './assets/getting_started.png'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx index e4508f4e99276..2d8dbd55f4366 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx @@ -5,15 +5,17 @@ * 2.0. */ +import { setMockValues, rerender } from '../__mocks__'; + import React from 'react'; -import { shallow } from 'enzyme'; -import { setMockValues, rerender } from '../__mocks__'; +import { shallow } from 'enzyme'; -import { EnterpriseSearch } from './'; -import { SetupGuide } from './components/setup_guide'; import { ErrorConnecting } from './components/error_connecting'; import { ProductSelector } from './components/product_selector'; +import { SetupGuide } from './components/setup_guide'; + +import { EnterpriseSearch } from './'; describe('EnterpriseSearch', () => { it('renders the Setup Guide and Product Selector', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx index 50ed0bce75cf8..b21e46429672a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx @@ -7,18 +7,17 @@ import React from 'react'; import { Route, Switch } from 'react-router-dom'; + import { useValues } from 'kea'; -import { KibanaLogic } from '../shared/kibana'; import { InitialAppData } from '../../../common/types'; - import { HttpLogic } from '../shared/http'; - -import { ROOT_PATH, SETUP_GUIDE_PATH } from './routes'; +import { KibanaLogic } from '../shared/kibana'; import { ErrorConnecting } from './components/error_connecting'; import { ProductSelector } from './components/product_selector'; import { SetupGuide } from './components/setup_guide'; +import { ROOT_PATH, SETUP_GUIDE_PATH } from './routes'; import './index.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx index f36561787eb69..2e0940b9c4af2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx @@ -6,17 +6,19 @@ */ import React from 'react'; + import { getContext } from 'kea'; -import { coreMock } from 'src/core/public/mocks'; -import { licensingMock } from '../../../licensing/public/mocks'; +import { coreMock } from '../../../../../src/core/public/mocks'; import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks'; +import { licensingMock } from '../../../licensing/public/mocks'; -import { renderApp, renderHeaderActions } from './'; -import { EnterpriseSearch } from './enterprise_search'; import { AppSearch } from './app_search'; -import { WorkplaceSearch } from './workplace_search'; +import { EnterpriseSearch } from './enterprise_search'; import { KibanaLogic } from './shared/kibana'; +import { WorkplaceSearch } from './workplace_search'; + +import { renderApp, renderHeaderActions } from './'; describe('renderApp', () => { const kibanaDeps = { diff --git a/x-pack/plugins/enterprise_search/public/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/index.tsx index 97e43f758e5b8..155ff5b92ba27 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.tsx @@ -7,21 +7,23 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { Router } from 'react-router-dom'; import { Provider } from 'react-redux'; -import { Store } from 'redux'; +import { Router } from 'react-router-dom'; + import { getContext, resetContext } from 'kea'; +import { Store } from 'redux'; + import { I18nProvider } from '@kbn/i18n/react'; -import { AppMountParameters, CoreStart } from 'src/core/public'; -import { PluginsStart, ClientConfigType, ClientData } from '../plugin'; +import { AppMountParameters, CoreStart } from '../../../../../src/core/public'; import { InitialAppData } from '../../common/types'; +import { PluginsStart, ClientConfigType, ClientData } from '../plugin'; +import { externalUrl } from './shared/enterprise_search_url'; +import { mountFlashMessagesLogic } from './shared/flash_messages'; +import { mountHttpLogic } from './shared/http'; import { mountKibanaLogic } from './shared/kibana'; import { mountLicensingLogic } from './shared/licensing'; -import { mountHttpLogic } from './shared/http'; -import { mountFlashMessagesLogic } from './shared/flash_messages'; -import { externalUrl } from './shared/enterprise_search_url'; /** * This file serves as a reusable wrapper to share Kibana-level context and other helpers diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/error_state/error_state_prompt.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/error_state/error_state_prompt.test.tsx index 9870264eb1c2f..d9d31f5a45d4b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/error_state/error_state_prompt.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/error_state/error_state_prompt.test.tsx @@ -8,7 +8,9 @@ import '../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiEmptyPrompt } from '@elastic/eui'; import { ErrorStatePrompt } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/error_state/error_state_prompt.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/error_state/error_state_prompt.tsx index cf8b234442002..f855c7b67dc6e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/error_state/error_state_prompt.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/error_state/error_state_prompt.tsx @@ -6,12 +6,14 @@ */ import React from 'react'; + import { useValues } from 'kea'; + import { EuiEmptyPrompt, EuiCode } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiButtonTo } from '../react_router_helpers'; import { KibanaLogic } from '../../shared/kibana'; +import { EuiButtonTo } from '../react_router_helpers'; import './error_state_prompt.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx index 2a31c0ecd66a8..aa45ce58af86a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx @@ -8,7 +8,9 @@ import { setMockValues } from '../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiCallOut } from '@elastic/eui'; import { FlashMessages } from './flash_messages'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.tsx index 5f38961b8a341..60d80487a2593 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.tsx @@ -6,7 +6,9 @@ */ import React, { Fragment } from 'react'; + import { useValues } from 'kea'; + import { EuiCallOut, EuiCallOutProps, EuiSpacer } from '@elastic/eui'; import { FlashMessagesLogic } from './flash_messages_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.test.ts index 61f667719e3e6..7fc78c99fb242 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.test.ts @@ -5,12 +5,14 @@ * 2.0. */ +import { mockKibanaValues } from '../../__mocks__/kibana_logic.mock'; + import { resetContext } from 'kea'; -import { mockKibanaValues } from '../../__mocks__/kibana_logic.mock'; const { history } = mockKibanaValues; -import { FlashMessagesLogic, mountFlashMessagesLogic, IFlashMessage } from './flash_messages_logic'; +import { FlashMessagesLogic, mountFlashMessagesLogic } from './flash_messages_logic'; +import { IFlashMessage } from './types'; describe('FlashMessagesLogic', () => { const mount = () => mountFlashMessagesLogic(); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.ts index 26af4103aada1..5993e67b28a39 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.ts @@ -6,15 +6,10 @@ */ import { kea, MakeLogicType } from 'kea'; -import { ReactNode } from 'react'; import { KibanaLogic } from '../kibana'; -export interface IFlashMessage { - type: 'success' | 'info' | 'warning' | 'error'; - message: ReactNode; - description?: ReactNode; -} +import { IFlashMessage } from './types'; interface FlashMessagesValues { messages: IFlashMessage[]; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts index 1df1c6a7a680e..b6b0e23ce7d6a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts @@ -8,6 +8,7 @@ import '../../__mocks__/kibana_logic.mock'; import { FlashMessagesLogic } from './flash_messages_logic'; + import { flashAPIErrors } from './handle_api_errors'; describe('flashAPIErrors', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts index 5fb824ebde9a0..11003d0fcc171 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts @@ -7,7 +7,8 @@ import { HttpResponse } from 'src/core/public'; -import { FlashMessagesLogic, IFlashMessage } from './flash_messages_logic'; +import { FlashMessagesLogic } from './flash_messages_logic'; +import { IFlashMessage } from './types'; /** * The API errors we are handling can come from one of two ways: diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/index.ts index 8d3605a19c22c..40317eb390547 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/index.ts @@ -6,7 +6,8 @@ */ export { FlashMessages } from './flash_messages'; -export { FlashMessagesLogic, IFlashMessage, mountFlashMessagesLogic } from './flash_messages_logic'; +export { FlashMessagesLogic, mountFlashMessagesLogic } from './flash_messages_logic'; +export { IFlashMessage } from './types'; export { flashAPIErrors } from './handle_api_errors'; export { setSuccessMessage, diff --git a/x-pack/plugins/maps_file_upload/server/client/errors.js b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/types.ts similarity index 60% rename from x-pack/plugins/maps_file_upload/server/client/errors.js rename to x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/types.ts index 8f8516158b303..c1d2f8420198d 100644 --- a/x-pack/plugins/maps_file_upload/server/client/errors.js +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/types.ts @@ -5,8 +5,10 @@ * 2.0. */ -import { boomify } from '@hapi/boom'; +import { ReactNode } from 'react'; -export function wrapError(error) { - return boomify(error, { statusCode: error.status }); +export interface IFlashMessage { + type: 'success' | 'info' | 'warning' | 'error'; + message: ReactNode; + description?: ReactNode; } diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/hidden_text/hidden_text.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/hidden_text/hidden_text.test.tsx index 1888edca53034..af63b9a801edd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/hidden_text/hidden_text.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/hidden_text/hidden_text.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { HiddenText } from '.'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/hidden_text/hidden_text.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/hidden_text/hidden_text.tsx index 5503baf0bdae4..35901496c5fbd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/hidden_text/hidden_text.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/hidden_text/hidden_text.tsx @@ -6,6 +6,7 @@ */ import React, { useState, ReactElement } from 'react'; + import { i18n } from '@kbn/i18n'; interface ChildrenProps { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.test.tsx index d8f02be60ef92..44bd8b78320d6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.test.tsx @@ -9,13 +9,14 @@ import '../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiPanel } from '@elastic/eui'; +import { IndexingStatus } from './indexing_status'; import { IndexingStatusContent } from './indexing_status_content'; import { IndexingStatusErrors } from './indexing_status_errors'; -import { IndexingStatus } from './indexing_status'; describe('IndexingStatus', () => { const getItemDetailPath = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.tsx index 3898eda126415..ee0557e15396c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.tsx @@ -11,12 +11,12 @@ import { useValues, useActions } from 'kea'; import { EuiPanel, EuiSpacer } from '@elastic/eui'; +import { IIndexingStatus } from '../types'; + import { IndexingStatusContent } from './indexing_status_content'; import { IndexingStatusErrors } from './indexing_status_errors'; import { IndexingStatusLogic } from './indexing_status_logic'; -import { IIndexingStatus } from '../types'; - export interface IIndexingStatusProps { viewLinkPath: string; itemId: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_content.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_content.test.tsx index a744ddf8b5290..8998e640d6c35 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_content.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_content.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiProgress, EuiTitle } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_errors.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_errors.test.tsx index 3747fe020af20..eb5fa9d70f026 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_errors.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_errors.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiCallOut } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.ts index 11ba1304d0a22..a436b669bcbe5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.ts @@ -7,9 +7,9 @@ import { kea, MakeLogicType } from 'kea'; +import { flashAPIErrors } from '../flash_messages'; import { HttpLogic } from '../http'; import { IIndexingStatus } from '../types'; -import { flashAPIErrors } from '../flash_messages'; interface IndexingStatusProps { statusPath: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.test.ts index 10b550fc93eb3..a5f54d16b2fad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.test.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { resetContext } from 'kea'; - import { mockKibanaValues } from '../../__mocks__'; +import { resetContext } from 'kea'; + import { KibanaLogic, mountKibanaLogic } from './kibana_logic'; describe('KibanaLogic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts index 4bb1859df09ea..8015d22f7c44a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts @@ -5,12 +5,13 @@ * 2.0. */ -import { kea, MakeLogicType } from 'kea'; - import { FC } from 'react'; + import { History } from 'history'; -import { ApplicationStart, ChromeBreadcrumb } from 'src/core/public'; -import { ChartsPluginStart } from 'src/plugins/charts/public'; +import { kea, MakeLogicType } from 'kea'; + +import { ApplicationStart, ChromeBreadcrumb } from '../../../../../../../src/core/public'; +import { ChartsPluginStart } from '../../../../../../../src/plugins/charts/public'; import { CloudSetup } from '../../../../../cloud/public'; import { HttpLogic } from '../http'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts index 64f53c767b17c..908cc0601ab9c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts @@ -6,10 +6,8 @@ */ import { useValues } from 'kea'; -import { EuiBreadcrumb } from '@elastic/eui'; -import { KibanaLogic } from '../kibana'; -import { HttpLogic } from '../http'; +import { EuiBreadcrumb } from '@elastic/eui'; import { ENTERPRISE_SEARCH_PLUGIN, @@ -18,6 +16,8 @@ import { } from '../../../../common/constants'; import { stripLeadingSlash } from '../../../../common/strip_slashes'; +import { HttpLogic } from '../http'; +import { KibanaLogic } from '../kibana'; import { letBrowserHandleEvent, createHref } from '../react_router_helpers'; /** diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx index 5b1aa64c42d64..c9743e6824018 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx @@ -9,6 +9,7 @@ import '../../__mocks__/shallow_useeffect.mock'; import { setMockValues, mockKibanaValues, mockHistory } from '../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; jest.mock('./generate_breadcrumbs', () => ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx index fa127566b1b02..e639f9d22fb4b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx @@ -6,6 +6,7 @@ */ import React, { useEffect } from 'react'; + import { useValues } from 'kea'; import { KibanaLogic } from '../kibana'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.test.tsx index c67518e977de2..28092f75cdede 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiPageSideBar, EuiButton, EuiPageBody, EuiCallOut } from '@elastic/eui'; import { Layout, INavContext } from './layout'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.tsx index 1af85905e6ccb..9cf5fccddbd5b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.tsx @@ -6,6 +6,7 @@ */ import React, { useState } from 'react'; + import classNames from 'classnames'; import { EuiPage, EuiPageSideBar, EuiPageBody, EuiButton, EuiCallOut } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.test.tsx index ceb5f21ce056f..451b49738029d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.test.tsx @@ -9,11 +9,13 @@ import '../../__mocks__/react_router_history.mock'; import React from 'react'; import { useLocation } from 'react-router-dom'; + import { shallow } from 'enzyme'; import { EuiLink } from '@elastic/eui'; -import { EuiLinkTo } from '../react_router_helpers'; + import { ENTERPRISE_SEARCH_PLUGIN, APP_SEARCH_PLUGIN } from '../../../../common/constants'; +import { EuiLinkTo } from '../react_router_helpers'; import { SideNav, SideNavLink, SideNavItem } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.tsx index 605d3940a8cc7..58a5c7bbb229f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.tsx @@ -7,14 +7,15 @@ import React, { useContext } from 'react'; import { useLocation } from 'react-router-dom'; + import classNames from 'classnames'; -import { i18n } from '@kbn/i18n'; import { EuiIcon, EuiTitle, EuiText, EuiLink } from '@elastic/eui'; // TODO: Remove EuiLink after full Kibana transition -import { EuiLinkTo } from '../react_router_helpers'; +import { i18n } from '@kbn/i18n'; import { ENTERPRISE_SEARCH_PLUGIN } from '../../../../common/constants'; import { stripTrailingSlash } from '../../../../common/strip_slashes'; +import { EuiLinkTo } from '../react_router_helpers'; import { NavContext, INavContext } from './layout'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/loading/loading.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/loading/loading.test.tsx index c443467d5cb32..eab5694a27968 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/loading/loading.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/loading/loading.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiLoadingSpinner } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/loading/loading.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/loading/loading.tsx index cfcbeaee72095..27a4dfdec0c07 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/loading/loading.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/loading/loading.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { EuiLoadingSpinner } from '@elastic/eui'; import './loading.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx index 0bda848bc8d6c..7e75b2b47bb7a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx @@ -8,12 +8,14 @@ import { setMockValues } from '../../__mocks__/kea.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiButton as EuiButtonExternal, EuiEmptyPrompt } from '@elastic/eui'; import { APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN } from '../../../../common/constants'; import { SetAppSearchChrome } from '../kibana_chrome'; + import { AppSearchLogo } from './assets/app_search_logo'; import { WorkplaceSearchLogo } from './assets/workplace_search_logo'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx index 6102987464f55..5699568c40558 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx @@ -6,8 +6,9 @@ */ import React from 'react'; + import { useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; + import { EuiPageContent, EuiEmptyPrompt, @@ -16,6 +17,7 @@ import { EuiFlexItem, EuiButton, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { APP_SEARCH_PLUGIN, @@ -23,11 +25,11 @@ import { LICENSED_SUPPORT_URL, } from '../../../../common/constants'; -import { EuiButtonTo } from '../react_router_helpers'; -import { BreadcrumbTrail } from '../kibana_chrome/generate_breadcrumbs'; import { SetAppSearchChrome, SetWorkplaceSearchChrome } from '../kibana_chrome'; -import { SendAppSearchTelemetry, SendWorkplaceSearchTelemetry } from '../telemetry'; +import { BreadcrumbTrail } from '../kibana_chrome/generate_breadcrumbs'; import { LicensingLogic } from '../licensing'; +import { EuiButtonTo } from '../react_router_helpers'; +import { SendAppSearchTelemetry, SendWorkplaceSearchTelemetry } from '../telemetry'; import { AppSearchLogo } from './assets/app_search_logo'; import { WorkplaceSearchLogo } from './assets/workplace_search_logo'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/create_href.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/create_href.test.ts index 0619dab19e2bd..fe2973cfdee32 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/create_href.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/create_href.test.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { httpServiceMock } from 'src/core/public/mocks'; import { mockHistory } from '../../__mocks__'; +import { httpServiceMock } from 'src/core/public/mocks'; + import { createHref } from './'; describe('createHref', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/create_href.ts b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/create_href.ts index e36a65c2457db..ea28fc4d440c5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/create_href.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/create_href.ts @@ -6,6 +6,7 @@ */ import { History } from 'history'; + import { HttpSetup } from 'src/core/public'; /** diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_components.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_components.test.tsx index 4de43ce997b48..75639ffeb9d6b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_components.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_components.test.tsx @@ -7,11 +7,13 @@ import '../../__mocks__/kea.mock'; +import { mockKibanaValues, mockHistory } from '../../__mocks__'; + import React from 'react'; + import { shallow, mount } from 'enzyme'; -import { EuiLink, EuiButton, EuiButtonEmpty, EuiPanel, EuiCard } from '@elastic/eui'; -import { mockKibanaValues, mockHistory } from '../../__mocks__'; +import { EuiLink, EuiButton, EuiButtonEmpty, EuiPanel, EuiCard } from '@elastic/eui'; import { EuiLinkTo, EuiButtonTo, EuiButtonEmptyTo, EuiPanelTo, EuiCardTo } from './eui_components'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_components.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_components.tsx index 384eb79c993c1..b9fee9d16273b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_components.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_components.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { useValues } from 'kea'; + import { EuiLink, EuiButton, @@ -20,8 +22,9 @@ import { } from '@elastic/eui'; import { EuiPanelProps } from '@elastic/eui/src/components/panel/panel'; -import { KibanaLogic } from '../kibana'; import { HttpLogic } from '../http'; +import { KibanaLogic } from '../kibana'; + import { letBrowserHandleEvent, createHref } from './'; /** diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_add_field_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_add_field_modal.test.tsx index c0bd1f3671f15..88c170b059d9c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_add_field_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_add_field_modal.test.tsx @@ -6,16 +6,17 @@ */ import React from 'react'; + import { shallow, mount } from 'enzyme'; +import { EuiFieldText, EuiModal, EuiSelect } from '@elastic/eui'; + import { NUMBER } from '../constants/field_types'; import { FIELD_NAME_CORRECTED_PREFIX } from './constants'; import { SchemaAddFieldModal } from './'; -import { EuiFieldText, EuiModal, EuiSelect } from '@elastic/eui'; - describe('SchemaAddFieldModal', () => { const addNewField = jest.fn(); const closeAddFieldModal = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_errors_accordion.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_errors_accordion.test.tsx index b1fde05906d44..a82f9e9b6113b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_errors_accordion.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_errors_accordion.test.tsx @@ -6,11 +6,13 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiAccordion, EuiTableRow } from '@elastic/eui'; import { EuiLinkTo } from '../react_router_helpers'; + import { SchemaErrorsAccordion } from './schema_errors_accordion'; describe('SchemaErrorsAccordion', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_existing_field.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_existing_field.test.tsx index 62f66bc95a5eb..5e89dce24bd4a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_existing_field.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/schema/schema_existing_field.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiSelect } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.test.tsx index 5d69a8ea84acf..0136f9745c322 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.test.tsx @@ -5,11 +5,13 @@ * 2.0. */ +import { mountWithIntl } from '../../../__mocks__'; + import React from 'react'; + import { shallow } from 'enzyme'; -import { EuiSteps, EuiLink } from '@elastic/eui'; -import { mountWithIntl } from '../../../__mocks__'; +import { EuiSteps, EuiLink } from '@elastic/eui'; import { CloudSetupInstructions } from './instructions'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.tsx index 24ba5bd4e5d0a..b355c88943a54 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.tsx @@ -6,9 +6,10 @@ */ import React from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; + import { EuiPageContent, EuiSteps, EuiText, EuiLink, EuiCallOut } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { docLinks } from '../../doc_links'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/instructions.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/instructions.test.tsx index 74fb74ce8cf70..fd31ca720b82b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/instructions.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/instructions.test.tsx @@ -5,11 +5,13 @@ * 2.0. */ +import { mountWithIntl } from '../../__mocks__'; + import React from 'react'; + import { shallow } from 'enzyme'; -import { EuiSteps, EuiLink } from '@elastic/eui'; -import { mountWithIntl } from '../../__mocks__'; +import { EuiSteps, EuiLink } from '@elastic/eui'; import { SetupInstructions } from './instructions'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/instructions.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/instructions.tsx index 83c244ea24ff1..5e39d1acdf189 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/instructions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/instructions.tsx @@ -6,8 +6,7 @@ */ import React from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; + import { EuiPageContent, EuiSpacer, @@ -18,6 +17,8 @@ import { EuiAccordion, EuiLink, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; interface Props { productName: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.test.tsx index 0b70bb70f8441..90ddddd7d20aa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.test.tsx @@ -8,11 +8,13 @@ import { setMockValues, rerender } from '../../__mocks__'; import React from 'react'; + import { shallow, ShallowWrapper } from 'enzyme'; + import { EuiIcon } from '@elastic/eui'; -import { SetupInstructions } from './instructions'; import { CloudSetupInstructions } from './cloud/instructions'; +import { SetupInstructions } from './instructions'; import { SetupGuideLayout } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.tsx index a0e89bfd8e57d..2140b3392abae 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { useValues } from 'kea'; import { @@ -22,9 +23,9 @@ import { import { KibanaLogic } from '../kibana'; -import { SetupInstructions } from './instructions'; import { CloudSetupInstructions } from './cloud/instructions'; import { SETUP_GUIDE_TITLE } from './constants'; +import { SetupInstructions } from './instructions'; import './setup_guide.scss'; /** diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/table_header/table_header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/table_header/table_header.test.tsx index d2588ed8d4aca..a481f22095aa3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/table_header/table_header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/table_header/table_header.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiTableHeader, EuiTableHeaderCell } from '@elastic/eui'; import { TableHeader } from './table_header'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/send_telemetry.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/send_telemetry.test.tsx index 60f4d404a917a..5fc8074d0a4d7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/send_telemetry.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/send_telemetry.test.tsx @@ -9,6 +9,7 @@ import '../../__mocks__/shallow_useeffect.mock'; import { mockTelemetryActions } from '../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/send_telemetry.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/send_telemetry.tsx index e0f54a9e421bf..1759b4075deca 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/send_telemetry.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/send_telemetry.tsx @@ -6,6 +6,7 @@ */ import React, { useEffect } from 'react'; + import { useActions } from 'kea'; import { TelemetryLogic, SendTelemetryHelper } from './telemetry_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/telemetry_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/telemetry_logic.test.ts index 52aec2c384adb..e516daedc1ba6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/telemetry_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/telemetry_logic.test.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { JSON_HEADER as headers } from '../../../../common/constants'; import { LogicMounter, mockHttpValues } from '../../__mocks__'; +import { JSON_HEADER as headers } from '../../../../common/constants'; + import { TelemetryLogic } from './telemetry_logic'; describe('Telemetry logic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/truncate/truncate.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/truncate/truncate.test.tsx index 71ed60cbd1c93..f9bf55b4fe800 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/truncate/truncate.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/truncate/truncate.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { TruncatedContent } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts index c249f5ee20588..ce92f62d3a017 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts @@ -5,10 +5,11 @@ * 2.0. */ -import { mergeServerAndStaticData } from '../views/content_sources/sources_logic'; -import { staticSourceData } from '../views/content_sources/source_data'; import { groups } from './groups.mock'; +import { staticSourceData } from '../views/content_sources/source_data'; +import { mergeServerAndStaticData } from '../views/content_sources/sources_logic'; + export const contentSources = [ { id: '123', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts index f1e6ca237681f..8ba94e83d26cf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts @@ -5,9 +5,9 @@ * 2.0. */ +import { DEFAULT_INITIAL_APP_DATA } from '../../../common/__mocks__'; import { LogicMounter } from '../__mocks__'; -import { DEFAULT_INITIAL_APP_DATA } from '../../../common/__mocks__'; import { AppLogic } from './app_logic'; describe('AppLogic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx index c2c645ebe439a..a7a788b48789a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx @@ -5,12 +5,14 @@ * 2.0. */ -import { externalUrl } from '../../../shared/enterprise_search_url'; - import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiButtonEmpty } from '@elastic/eui'; +import { externalUrl } from '../../../shared/enterprise_search_url'; + import { WorkplaceSearchHeaderActions } from './'; describe('WorkplaceSearchHeaderActions', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx index c1912deb8d40a..c79865d25ecd7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx @@ -6,10 +6,10 @@ */ import React from 'react'; + import { EuiButtonEmpty, EuiText } from '@elastic/eui'; import { externalUrl, getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; - import { NAV } from '../../constants'; export const WorkplaceSearchHeaderActions: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx index d2b2da1a48176..8f37f608f4e28 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx @@ -8,9 +8,11 @@ import '../../../__mocks__/enterprise_search_url.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { SideNav, SideNavLink } from '../../../shared/layout'; + import { WorkplaceSearchNav } from './'; describe('WorkplaceSearchNav', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx index 2696e5acf1c12..c184247b253d6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx @@ -12,9 +12,7 @@ import { EuiSpacer } from '@elastic/eui'; import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; import { SideNav, SideNavLink } from '../../../shared/layout'; - import { NAV } from '../../constants'; - import { SOURCES_PATH, SECURITY_PATH, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/api_key/api_key.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/api_key/api_key.test.tsx index 66e9ac9ed7a8b..32f21c158736f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/api_key/api_key.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/api_key/api_key.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiCodeBlock, EuiFormLabel } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/component_loader/component_loader.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/component_loader/component_loader.test.tsx index cb3fc32432999..991c7a061b4bb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/component_loader/component_loader.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/component_loader/component_loader.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiLoadingSpinner, EuiTextColor } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/content_section/content_section.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/content_section/content_section.test.tsx index c21e8b8d3449f..21280926d7aae 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/content_section/content_section.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/content_section/content_section.test.tsx @@ -6,12 +6,15 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiSpacer } from '@elastic/eui'; -import { ContentSection } from './'; import { ViewContentHeader } from '../view_content_header'; +import { ContentSection } from './'; + const props = { children:
, testSubj: 'contentSection', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/content_section/content_section.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/content_section/content_section.tsx index b0ab18bbfde95..e606263ac6f1c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/content_section/content_section.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/content_section/content_section.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { EuiSpacer } from '@elastic/eui'; import { SpacerSizeTypes } from '../../../types'; - import { ViewContentHeader } from '../view_content_header'; import './content_section.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/credential_item/credential_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/credential_item/credential_item.test.tsx index 79c4abdf2e223..13e2a229b3a76 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/credential_item/credential_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/credential_item/credential_item.test.tsx @@ -6,6 +6,7 @@ */ import * as React from 'react'; + import { shallow } from 'enzyme'; import { EuiCopy, EuiButtonIcon, EuiFieldText } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_badge/license_badge.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_badge/license_badge.test.tsx index 4e38894766d86..6deb37d850076 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_badge/license_badge.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_badge/license_badge.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiBadge } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_callout/license_callout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_callout/license_callout.test.tsx index d8266127a0f42..6a69178ad07da 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_callout/license_callout.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_callout/license_callout.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiLink, EuiText } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.test.tsx index 5ef191d0d0fe8..0bced6a7fc4e0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.test.tsx @@ -9,7 +9,9 @@ import '../../../../__mocks__/kea.mock'; import { mockTelemetryActions } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.tsx index ded4278c35e14..3611bfb2a3f69 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.tsx @@ -6,13 +6,14 @@ */ import React from 'react'; + import { useActions } from 'kea'; import { EuiButton, EuiButtonProps, EuiLinkProps } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { TelemetryLogic } from '../../../../shared/telemetry'; import { getWorkplaceSearchUrl } from '../../../../shared/enterprise_search_url'; +import { TelemetryLogic } from '../../../../shared/telemetry'; export const ProductButton: React.FC = () => { const { sendWorkplaceSearchTelemetry } = useActions(TelemetryLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_config_fields/source_config_fields.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_config_fields/source_config_fields.test.tsx index e5cd2bb2e0461..9af91107d7304 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_config_fields/source_config_fields.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_config_fields/source_config_fields.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { ApiKey } from '../api_key'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_config_fields/source_config_fields.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_config_fields/source_config_fields.tsx index 8c6e2b0174eb0..236d475b8f687 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_config_fields/source_config_fields.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_config_fields/source_config_fields.tsx @@ -16,7 +16,6 @@ import { CLIENT_ID_LABEL, CLIENT_SECRET_LABEL, } from '../../../constants'; - import { ApiKey } from '../api_key'; import { CredentialItem } from '../credential_item'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_icon/source_icon.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_icon/source_icon.test.tsx index f8cf9d63915d6..3bea6f224dc2b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_icon/source_icon.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_icon/source_icon.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiIcon } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.test.tsx index cfac7148bf88a..9661471bb1dd7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.test.tsx @@ -5,11 +5,13 @@ * 2.0. */ +import { contentSources } from '../../../__mocks__/content_sources.mock'; + import React from 'react'; + import { shallow } from 'enzyme'; import { EuiTableRow, EuiSwitch, EuiIcon } from '@elastic/eui'; -import { contentSources } from '../../../__mocks__/content_sources.mock'; import { SourceIcon } from '../source_icon'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.tsx index 11d71481751b0..6cfc68b45ee3c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.tsx @@ -26,14 +26,13 @@ import { import { EuiLinkTo } from '../../../../shared/react_router_helpers'; import { SOURCE_STATUSES as statuses } from '../../../constants'; -import { ContentSourceDetails } from '../../../types'; import { ADD_SOURCE_PATH, SOURCE_DETAILS_PATH, getContentSourcePath, getSourcesPath, } from '../../../routes'; - +import { ContentSourceDetails } from '../../../types'; import { SourceIcon } from '../source_icon'; import './source_row.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/sources_table/sources_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/sources_table/sources_table.test.tsx index efe529bcfb289..f54f7ccdf24bd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/sources_table/sources_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/sources_table/sources_table.test.tsx @@ -5,13 +5,15 @@ * 2.0. */ +import { contentSources } from '../../../__mocks__/content_sources.mock'; + import React from 'react'; + import { shallow } from 'enzyme'; import { EuiTable } from '@elastic/eui'; -import { TableHeader } from '../../../../shared/table_header/table_header'; -import { contentSources } from '../../../__mocks__/content_sources.mock'; +import { TableHeader } from '../../../../shared/table_header/table_header'; import { SourceRow } from '../source_row'; import { SourcesTable } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/sources_table/sources_table.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/sources_table/sources_table.tsx index a0aba097d17f4..66e7e2e752a1e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/sources_table/sources_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/sources_table/sources_table.tsx @@ -10,8 +10,8 @@ import React from 'react'; import { EuiTable, EuiTableBody } from '@elastic/eui'; import { TableHeader } from '../../../../shared/table_header/table_header'; -import { SourceRow, ISourceRow } from '../source_row'; import { ContentSourceDetails } from '../../../types'; +import { SourceRow, ISourceRow } from '../source_row'; interface SourcesTableProps extends ISourceRow { sources: ContentSourceDetails[]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/table_pagination_bar/table_pagination_bar.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/table_pagination_bar/table_pagination_bar.test.tsx index 343c9b68bc834..d22ddcce49dc4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/table_pagination_bar/table_pagination_bar.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/table_pagination_bar/table_pagination_bar.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiFlexGroup, EuiTablePagination } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_icon/user_icon.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_icon/user_icon.test.tsx index d8046bd88cf4a..5ce83b641cf8f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_icon/user_icon.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_icon/user_icon.test.tsx @@ -5,10 +5,11 @@ * 2.0. */ +import { users } from '../../../__mocks__/users.mock'; + import React from 'react'; -import { shallow } from 'enzyme'; -import { users } from '../../../__mocks__/users.mock'; +import { shallow } from 'enzyme'; import { UserIcon } from './user_icon'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_row/user_row.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_row/user_row.test.tsx index fe2bfd27db55a..f15c74ed1054b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_row/user_row.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_row/user_row.test.tsx @@ -5,13 +5,14 @@ * 2.0. */ +import { users } from '../../../__mocks__/users.mock'; + import React from 'react'; + import { shallow } from 'enzyme'; import { EuiTableRow } from '@elastic/eui'; -import { users } from '../../../__mocks__/users.mock'; - import { UserRow } from './'; describe('SourcesTable', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/view_content_header/view_content_header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/view_content_header/view_content_header.test.tsx index 01a05a5d94c75..fda1a27e103c2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/view_content_header/view_content_header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/view_content_header/view_content_header.test.tsx @@ -6,7 +6,9 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFlexGroup } from '@elastic/eui'; import { ViewContentHeader } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/view_content_header/view_content_header.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/view_content_header/view_content_header.tsx index ed2989de5ce3c..fa3a1d3ccb2e4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/view_content_header/view_content_header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/view_content_header/view_content_header.tsx @@ -8,7 +8,6 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle, EuiSpacer } from '@elastic/eui'; - import { FlexGroupAlignItems } from '@elastic/eui/src/components/flex/flex_group'; interface ViewContentHeaderProps { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx index 73ee7662888bb..5678ad545d50d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx @@ -10,13 +10,15 @@ import { setMockValues, setMockActions, mockKibanaValues } from '../__mocks__'; import React from 'react'; import { Redirect } from 'react-router-dom'; + import { shallow } from 'enzyme'; import { Layout } from '../shared/layout'; + import { WorkplaceSearchHeaderActions } from './components/layout'; -import { SetupGuide } from './views/setup_guide'; import { ErrorState } from './views/error_state'; import { Overview } from './views/overview'; +import { SetupGuide } from './views/setup_guide'; import { WorkplaceSearch, WorkplaceSearchUnconfigured, WorkplaceSearchConfigured } from './'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx index a4c12f1d71d4e..d690dee4dc98c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx @@ -7,16 +7,18 @@ import React, { useEffect } from 'react'; import { Route, Redirect, Switch, useLocation } from 'react-router-dom'; + import { useActions, useValues } from 'kea'; import { WORKPLACE_SEARCH_PLUGIN } from '../../../common/constants'; import { InitialAppData } from '../../../common/types'; -import { KibanaLogic } from '../shared/kibana'; import { HttpLogic } from '../shared/http'; -import { AppLogic } from './app_logic'; +import { KibanaLogic } from '../shared/kibana'; import { Layout } from '../shared/layout'; -import { WorkplaceSearchNav, WorkplaceSearchHeaderActions } from './components/layout'; +import { NotFound } from '../shared/not_found'; +import { AppLogic } from './app_logic'; +import { WorkplaceSearchNav, WorkplaceSearchHeaderActions } from './components/layout'; import { GROUPS_PATH, SETUP_GUIDE_PATH, @@ -25,19 +27,16 @@ import { ORG_SETTINGS_PATH, SECURITY_PATH, } from './routes'; - -import { SetupGuide } from './views/setup_guide'; +import { SourcesRouter } from './views/content_sources'; +import { SourceSubNav } from './views/content_sources/components/source_sub_nav'; import { ErrorState } from './views/error_state'; -import { NotFound } from '../shared/not_found'; -import { Overview } from './views/overview'; import { GroupsRouter } from './views/groups'; +import { GroupSubNav } from './views/groups/components/group_sub_nav'; +import { Overview } from './views/overview'; import { Security } from './views/security'; -import { SourcesRouter } from './views/content_sources'; import { SettingsRouter } from './views/settings'; - -import { GroupSubNav } from './views/groups/components/group_sub_nav'; -import { SourceSubNav } from './views/content_sources/components/source_sub_nav'; import { SettingsSubNav } from './views/settings/components/settings_sub_nav'; +import { SetupGuide } from './views/setup_guide'; export const WorkplaceSearch: React.FC = (props) => { const { config } = useValues(KibanaLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.test.tsx index d9c1dbeefad92..68bec94270a01 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiLink } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx index aa219a475406f..41f53523bca4e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx @@ -7,10 +7,10 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { mockKibanaValues, setMockActions, setMockValues } from '../../../../../__mocks__'; - import { sourceConfigData } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { Loading } from '../../../../../shared/loading'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.tsx index 0664c930775bc..b00f9807f0acd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.tsx @@ -9,16 +9,16 @@ import React, { useEffect } from 'react'; import { useActions, useValues } from 'kea'; -import { AppLogic } from '../../../../app_logic'; import { KibanaLogic } from '../../../../../shared/kibana'; import { Loading } from '../../../../../shared/loading'; +import { AppLogic } from '../../../../app_logic'; import { CUSTOM_SERVICE_TYPE } from '../../../../constants'; -import { staticSourceData } from '../../source_data'; -import { AddSourceLogic, AddSourceProps, AddSourceSteps } from './add_source_logic'; -import { SourceDataItem } from '../../../../types'; import { SOURCE_ADDED_PATH, getSourcesPath } from '../../../../routes'; +import { SourceDataItem } from '../../../../types'; +import { staticSourceData } from '../../source_data'; import { AddSourceHeader } from './add_source_header'; +import { AddSourceLogic, AddSourceProps, AddSourceSteps } from './add_source_logic'; import { ConfigCompleted } from './config_completed'; import { ConfigurationIntro } from './configuration_intro'; import { ConfigureCustom } from './configure_custom'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_header.test.tsx index 7167fcf3bc252..879f7993f3dc1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_header.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiText, EuiTextColor } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.test.tsx index fe24eeb5c7cb5..90da349ea4f27 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.test.tsx @@ -14,23 +14,23 @@ import { } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiEmptyPrompt, EuiFieldSearch } from '@elastic/eui'; -import { Loading } from '../../../../../../applications/shared/loading'; +import { Loading } from '../../../../../shared/loading'; import { ViewContentHeader } from '../../../../components/shared/view_content_header'; +import { AddSourceList } from './add_source_list'; +import { AvailableSourcesList } from './available_sources_list'; +import { ConfiguredSourcesList } from './configured_sources_list'; import { ADD_SOURCE_NEW_SOURCE_DESCRIPTION, ADD_SOURCE_ORG_SOURCE_DESCRIPTION, ADD_SOURCE_PRIVATE_SOURCE_DESCRIPTION, } from './constants'; -import { AddSourceList } from './add_source_list'; -import { AvailableSourcesList } from './available_sources_list'; -import { ConfiguredSourcesList } from './configured_sources_list'; - describe('AddSourceList', () => { const initializeSources = jest.fn(); const resetSourcesState = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.tsx index 3a0db0f44047d..372187485f277 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.tsx @@ -18,15 +18,18 @@ import { EuiPanel, EuiEmptyPrompt, } from '@elastic/eui'; -import noSharedSourcesIcon from '../../../../assets/share_circle.svg'; +import { Loading } from '../../../../../shared/loading'; import { AppLogic } from '../../../../app_logic'; +import noSharedSourcesIcon from '../../../../assets/share_circle.svg'; import { ContentSection } from '../../../../components/shared/content_section'; import { ViewContentHeader } from '../../../../components/shared/view_content_header'; -import { Loading } from '../../../../../../applications/shared/loading'; import { CUSTOM_SERVICE_TYPE } from '../../../../constants'; import { SourceDataItem } from '../../../../types'; +import { SourcesLogic } from '../../sources_logic'; +import { AvailableSourcesList } from './available_sources_list'; +import { ConfiguredSourcesList } from './configured_sources_list'; import { ADD_SOURCE_NEW_SOURCE_DESCRIPTION, ADD_SOURCE_ORG_SOURCE_DESCRIPTION, @@ -39,10 +42,6 @@ import { ADD_SOURCE_EMPTY_BODY, } from './constants'; -import { SourcesLogic } from '../../sources_logic'; -import { AvailableSourcesList } from './available_sources_list'; -import { ConfiguredSourcesList } from './configured_sources_list'; - export const AddSourceList: React.FC = () => { const { contentSources, dataLoading, availableSources, configuredSources } = useValues( SourcesLogic diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts index a3fd35503ea0d..ed67eb9994bc8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts @@ -11,20 +11,18 @@ import { mockHttpValues, mockKibanaValues, } from '../../../../../__mocks__'; +import { sourceConfigData } from '../../../../__mocks__/content_sources.mock'; + +import { nextTick } from '@kbn/test/jest'; -import { AppLogic } from '../../../../app_logic'; jest.mock('../../../../app_logic', () => ({ AppLogic: { values: { isOrganization: true } }, })); +import { AppLogic } from '../../../../app_logic'; -import { SourcesLogic } from '../../sources_logic'; - -import { nextTick } from '@kbn/test/jest'; - -import { CustomSource } from '../../../../types'; import { SOURCES_PATH, getSourcesPath } from '../../../../routes'; - -import { sourceConfigData } from '../../../../__mocks__/content_sources.mock'; +import { CustomSource } from '../../../../types'; +import { SourcesLogic } from '../../sources_logic'; import { AddSourceLogic, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts index f10e81487567e..4e996aff6f5b0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts @@ -5,33 +5,27 @@ * 2.0. */ -import { keys, pickBy } from 'lodash'; - -import { kea, MakeLogicType } from 'kea'; - import { Search } from 'history'; +import { kea, MakeLogicType } from 'kea'; +import { keys, pickBy } from 'lodash'; import { i18n } from '@kbn/i18n'; - import { HttpFetchQuery } from 'src/core/public'; -import { HttpLogic } from '../../../../../shared/http'; -import { KibanaLogic } from '../../../../../shared/kibana'; -import { parseQueryParams } from '../../../../../shared/query_params'; - import { flashAPIErrors, setSuccessMessage, clearFlashMessages, } from '../../../../../shared/flash_messages'; - -import { staticSourceData } from '../../source_data'; -import { SOURCES_PATH, getSourcesPath } from '../../../../routes'; -import { CUSTOM_SERVICE_TYPE, WORKPLACE_SEARCH_URL_PREFIX } from '../../../../constants'; - +import { HttpLogic } from '../../../../../shared/http'; +import { KibanaLogic } from '../../../../../shared/kibana'; +import { parseQueryParams } from '../../../../../shared/query_params'; import { AppLogic } from '../../../../app_logic'; -import { SourcesLogic } from '../../sources_logic'; +import { CUSTOM_SERVICE_TYPE, WORKPLACE_SEARCH_URL_PREFIX } from '../../../../constants'; +import { SOURCES_PATH, getSourcesPath } from '../../../../routes'; import { CustomSource } from '../../../../types'; +import { staticSourceData } from '../../source_data'; +import { SourcesLogic } from '../../sources_logic'; export interface AddSourceProps { sourceIndex: number; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.test.tsx index 43f1486644c72..fcb55f24ddb03 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.test.tsx @@ -7,10 +7,10 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues } from '../../../../../__mocks__'; - import { mergedAvailableSources } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiCard, EuiToolTip, EuiTitle } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.tsx index 8060f765a91b0..fafc1ea54a6cf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.tsx @@ -7,7 +7,7 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; +import { useValues } from 'kea'; import { EuiCard, @@ -18,15 +18,13 @@ import { EuiText, EuiToolTip, } from '@elastic/eui'; - -import { useValues } from 'kea'; +import { i18n } from '@kbn/i18n'; import { LicensingLogic } from '../../../../../shared/licensing'; import { EuiLinkTo } from '../../../../../shared/react_router_helpers'; - import { SourceIcon } from '../../../../components/shared/source_icon'; -import { SourceDataItem } from '../../../../types'; import { ADD_CUSTOM_PATH, getSourcesPath } from '../../../../routes'; +import { SourceDataItem } from '../../../../types'; import { AVAILABLE_SOURCE_EMPTY_STATE, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_completed.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_completed.test.tsx index cd40da7f6b376..163da5297e370 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_completed.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_completed.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { ConfigCompleted } from './config_completed'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_completed.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_completed.tsx index bd85b3c7c2dd5..1d4f1f2fca980 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_completed.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_completed.tsx @@ -7,9 +7,6 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - import { EuiButton, EuiFlexGroup, @@ -20,7 +17,10 @@ import { EuiText, EuiTextAlign, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiLinkTo, EuiButtonTo } from '../../../../../shared/react_router_helpers'; import { getSourcesPath, ADD_SOURCE_PATH, @@ -28,8 +28,6 @@ import { PRIVATE_SOURCES_DOCS_URL, } from '../../../../routes'; -import { EuiLinkTo, EuiButtonTo } from '../../../../../shared/react_router_helpers'; - import { CONFIG_COMPLETED_PRIVATE_SOURCES_DOCS_LINK, CONFIG_COMPLETED_CONFIGURE_NEW_BUTTON, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_docs_links.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_docs_links.test.tsx index b56f36df5486e..914eca94ad6f3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_docs_links.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_docs_links.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiButtonEmpty } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_docs_links.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_docs_links.tsx index 259e911d6d54f..043d28e9dba03 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_docs_links.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/config_docs_links.tsx @@ -7,9 +7,8 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; - import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { DOCUMENTATION_LINK_TITLE } from '../../../../constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configuration_intro.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configuration_intro.test.tsx index 2d26982cbc2f5..2ebc021925abf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configuration_intro.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configuration_intro.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiText, EuiTitle } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configuration_intro.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configuration_intro.tsx index ff1caafb91bdb..914eee74dfc4e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configuration_intro.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configuration_intro.tsx @@ -7,9 +7,6 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - import { EuiBadge, EuiButton, @@ -20,6 +17,10 @@ import { EuiText, EuiTitle, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import connectionIllustration from '../../../../assets/connection_illustration.svg'; import { CONFIG_INTRO_ALT_TEXT, @@ -31,8 +32,6 @@ import { CONFIG_INTRO_STEP2_TEXT, } from './constants'; -import connectionIllustration from '../../../../assets/connection_illustration.svg'; - interface ConfigurationIntroProps { header: React.ReactNode; name: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.test.tsx index a3b572737bdeb..099989255bf47 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.test.tsx @@ -9,6 +9,7 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiForm, EuiFieldText } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.tsx index 2d0113f1d0e7d..36242f5523e77 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.tsx @@ -9,8 +9,6 @@ import React, { ChangeEvent, FormEvent } from 'react'; import { useActions, useValues } from 'kea'; -import { FormattedMessage } from '@kbn/i18n/react'; - import { EuiButton, EuiFieldText, @@ -20,8 +18,10 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; import { CUSTOM_SOURCE_DOCS_URL } from '../../../../routes'; + import { AddSourceLogic } from './add_source_logic'; import { CONFIG_CUSTOM_BUTTON } from './constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.test.tsx index a57ff390150ea..533dfcda70db1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.test.tsx @@ -9,11 +9,12 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiCheckboxGroup } from '@elastic/eui'; -import { Loading } from '../../../../../../applications/shared/loading'; +import { Loading } from '../../../../../shared/loading'; import { ConfigureOauth } from './configure_oauth'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.tsx index 3eae438eb960c..69a2fbd1495c7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.tsx @@ -6,10 +6,10 @@ */ import React, { useEffect, useState, FormEvent } from 'react'; +import { useLocation } from 'react-router-dom'; import { Location } from 'history'; import { useActions, useValues } from 'kea'; -import { useLocation } from 'react-router-dom'; import { EuiButton, @@ -19,13 +19,12 @@ import { EuiFormRow, EuiSpacer, } from '@elastic/eui'; - import { EuiCheckboxGroupIdToSelectedMap } from '@elastic/eui/src/components/form/checkbox/checkbox_group'; -import { parseQueryParams } from '../../../../../../applications/shared/query_params'; -import { Loading } from '../../../../../../applications/shared/loading'; -import { AddSourceLogic } from './add_source_logic'; +import { Loading } from '../../../../../shared/loading'; +import { parseQueryParams } from '../../../../../shared/query_params'; +import { AddSourceLogic } from './add_source_logic'; import { CONFIG_OAUTH_LABEL, CONFIG_OAUTH_BUTTON } from './constants'; interface OauthQueryParams { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.test.tsx index 3bb7d42748f25..2e2e04556cdb7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.test.tsx @@ -5,13 +5,14 @@ * 2.0. */ +import { mergedConfiguredSources } from '../../../../__mocks__/content_sources.mock'; + import React from 'react'; + import { shallow } from 'enzyme'; import { EuiPanel } from '@elastic/eui'; -import { mergedConfiguredSources } from '../../../../__mocks__/content_sources.mock'; - import { ConfiguredSourcesList } from './configured_sources_list'; describe('ConfiguredSourcesList', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.tsx index cb5e96a4019a1..5f64913410d4c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.tsx @@ -21,8 +21,8 @@ import { import { EuiButtonEmptyTo } from '../../../../../shared/react_router_helpers'; import { SourceIcon } from '../../../../components/shared/source_icon'; -import { SourceDataItem } from '../../../../types'; import { getSourcesPath } from '../../../../routes'; +import { SourceDataItem } from '../../../../types'; import { CONFIGURED_SOURCES_LIST_UNCONNECTED_TOOLTIP, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.test.tsx index cff95136968db..b795b0af09944 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.test.tsx @@ -9,12 +9,14 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiBadge, EuiCallOut, EuiSwitch } from '@elastic/eui'; import { FeatureIds } from '../../../../types'; import { staticSourceData } from '../../source_data'; + import { ConnectInstance } from './connect_instance'; describe('ConnectInstance', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.tsx index ea5d556350759..08b29075f3d0d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.tsx @@ -8,8 +8,6 @@ import React, { useState, useEffect, FormEvent } from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButton, @@ -27,16 +25,16 @@ import { EuiBadge, EuiBadgeGroup, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; -import { LicensingLogic } from '../../../../../../applications/shared/licensing'; - +import { LicensingLogic } from '../../../../../shared/licensing'; import { AppLogic } from '../../../../app_logic'; -import { AddSourceLogic } from './add_source_logic'; -import { FeatureIds, Configuration, Features } from '../../../../types'; import { DOCUMENT_PERMISSIONS_DOCS_URL } from '../../../../routes'; -import { SourceFeatures } from './source_features'; - +import { FeatureIds, Configuration, Features } from '../../../../types'; import { LEARN_MORE_LINK } from '../../constants'; + +import { AddSourceLogic } from './add_source_logic'; import { CONNECT_REMOTE, CONNECT_PRIVATE, @@ -47,6 +45,7 @@ import { CONNECT_NOT_SYNCED_TITLE, CONNECT_NOT_SYNCED_TEXT, } from './constants'; +import { SourceFeatures } from './source_features'; interface ConnectInstanceProps { header: React.ReactNode; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.test.tsx index 94c2e734751ee..38b6925008181 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.test.tsx @@ -9,6 +9,7 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { ReAuthenticate } from './re_authenticate'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.tsx index 0cdf461f2d64c..eb6736d84a197 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.tsx @@ -6,14 +6,15 @@ */ import React, { useEffect, useState, FormEvent } from 'react'; +import { useLocation } from 'react-router-dom'; import { Location } from 'history'; import { useActions, useValues } from 'kea'; -import { useLocation } from 'react-router-dom'; -import { i18n } from '@kbn/i18n'; import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSpacer } from '@elastic/eui'; -import { parseQueryParams } from '../../../../../../applications/shared/query_params'; +import { i18n } from '@kbn/i18n'; + +import { parseQueryParams } from '../../../../../shared/query_params'; import { AddSourceLogic } from './add_source_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.test.tsx index 4d1955d7928a8..c0f7f1139cb73 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.test.tsx @@ -7,18 +7,18 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../../../../__mocks__'; +import { sourceConfigData } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiSteps, EuiButton, EuiButtonEmpty } from '@elastic/eui'; -import { sourceConfigData } from '../../../../__mocks__/content_sources.mock'; +import { ApiKey } from '../../../../components/shared/api_key'; import { staticSourceData } from '../../source_data'; -import { ApiKey } from '../../../../components/shared/api_key'; import { ConfigDocsLinks } from './config_docs_links'; - import { SaveConfig } from './save_config'; describe('SaveConfig', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.tsx index f6d5d0f4066ab..956d5143ef2c5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.tsx @@ -8,7 +8,6 @@ import React, { FormEvent } from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiButton, @@ -21,7 +20,10 @@ import { EuiSpacer, EuiSteps, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { LicensingLogic } from '../../../../../shared/licensing'; +import { ApiKey } from '../../../../components/shared/api_key'; import { PUBLIC_KEY_LABEL, CONSUMER_KEY_LABEL, @@ -31,16 +33,11 @@ import { CLIENT_SECRET_LABEL, REMOVE_BUTTON, } from '../../../../constants'; - -import { OAUTH_SAVE_CONFIG_BUTTON, OAUTH_BACK_BUTTON, OAUTH_STEP_2 } from './constants'; - -import { LicensingLogic } from '../../../../../../applications/shared/licensing'; - -import { ApiKey } from '../../../../components/shared/api_key'; -import { AddSourceLogic } from './add_source_logic'; import { Configuration } from '../../../../types'; +import { AddSourceLogic } from './add_source_logic'; import { ConfigDocsLinks } from './config_docs_links'; +import { OAUTH_SAVE_CONFIG_BUTTON, OAUTH_BACK_BUTTON, OAUTH_STEP_2 } from './constants'; interface SaveConfigProps { header: React.ReactNode; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.test.tsx index 551bd7f1bb006..5ed777322cc08 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiLink, EuiPanel, EuiTitle } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx index a61ad1aeb728a..b42bd674109fe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx @@ -7,9 +7,6 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - import { EuiFlexGroup, EuiFlexItem, @@ -22,12 +19,12 @@ import { EuiLink, EuiPanel, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiLinkTo } from '../../../../../shared/react_router_helpers'; import { CredentialItem } from '../../../../components/shared/credential_item'; import { LicenseBadge } from '../../../../components/shared/license_badge'; - -import { CustomSource } from '../../../../types'; import { SOURCES_PATH, SOURCE_DISPLAY_SETTINGS_PATH, @@ -36,7 +33,7 @@ import { getContentSourcePath, getSourcesPath, } from '../../../../routes'; - +import { CustomSource } from '../../../../types'; import { ACCESS_TOKEN_LABEL, ID_LABEL, LEARN_CUSTOM_FEATURES_BUTTON } from '../../constants'; import { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.test.tsx index ccc6d05df5f9a..cd8ba37695ac6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.test.tsx @@ -11,10 +11,10 @@ import React from 'react'; import { EuiPanel } from '@elastic/eui'; -import { SourceFeatures } from './source_features'; - import { staticSourceData } from '../../source_data'; +import { SourceFeatures } from './source_features'; + describe('SourceFeatures', () => { const { features, objTypes } = staticSourceData[0]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.tsx index 186e8fcdc3790..0838ab2ccdae2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.tsx @@ -8,7 +8,6 @@ import React from 'react'; import { useValues } from 'kea'; -import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlexGroup, @@ -19,13 +18,13 @@ import { EuiText, EuiTitle, } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; -import { LicensingLogic } from '../../../../../../applications/shared/licensing'; - +import { LicensingLogic } from '../../../../../shared/licensing'; import { AppLogic } from '../../../../app_logic'; import { LicenseBadge } from '../../../../components/shared/license_badge'; -import { Features, FeatureIds } from '../../../../types'; import { ENT_SEARCH_LICENSE_MANAGEMENT } from '../../../../routes'; +import { Features, FeatureIds } from '../../../../types'; import { SOURCE_FEATURES_SEARCHABLE, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/custom_source_icon.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/custom_source_icon.test.tsx index 6567f74bd8790..fcce69d70ad50 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/custom_source_icon.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/custom_source_icon.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { CustomSourceIcon } from './custom_source_icon'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.test.tsx index 72744690baf30..feebc7f8d445e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.test.tsx @@ -8,24 +8,21 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { mockKibanaValues } from '../../../../../__mocks__'; - import { setMockValues, setMockActions } from '../../../../../__mocks__'; import { unmountHandler } from '../../../../../__mocks__/shallow_useeffect.mock'; - -import { shallow } from 'enzyme'; +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; -import { EuiButton, EuiTabbedContent } from '@elastic/eui'; +import { shallow } from 'enzyme'; -import { exampleResult } from '../../../../__mocks__/content_sources.mock'; +import { EuiButton, EuiTabbedContent } from '@elastic/eui'; import { Loading } from '../../../../../shared/loading'; import { ViewContentHeader } from '../../../../components/shared/view_content_header'; -import { FieldEditorModal } from './field_editor_modal'; - import { DisplaySettings } from './display_settings'; +import { FieldEditorModal } from './field_editor_modal'; describe('DisplaySettings', () => { const { navigateToUrl } = mockKibanaValues; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.tsx index 62beb4e40793b..29266cdefe584 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.tsx @@ -19,21 +19,18 @@ import { EuiTabbedContentTab, } from '@elastic/eui'; +import { clearFlashMessages } from '../../../../../shared/flash_messages'; +import { KibanaLogic } from '../../../../../shared/kibana'; +import { Loading } from '../../../../../shared/loading'; +import { AppLogic } from '../../../../app_logic'; +import { ViewContentHeader } from '../../../../components/shared/view_content_header'; +import { SAVE_BUTTON } from '../../../../constants'; import { DISPLAY_SETTINGS_RESULT_DETAIL_PATH, DISPLAY_SETTINGS_SEARCH_RESULT_PATH, getContentSourcePath, } from '../../../../routes'; -import { clearFlashMessages } from '../../../../../shared/flash_messages'; - -import { KibanaLogic } from '../../../../../shared/kibana'; -import { AppLogic } from '../../../../app_logic'; - -import { Loading } from '../../../../../shared/loading'; -import { ViewContentHeader } from '../../../../components/shared/view_content_header'; - -import { SAVE_BUTTON } from '../../../../constants'; import { UNSAVED_MESSAGE, DISPLAY_SETTINGS_TITLE, @@ -43,9 +40,7 @@ import { SEARCH_RESULTS_LABEL, RESULT_DETAIL_LABEL, } from './constants'; - import { DisplaySettingsLogic } from './display_settings_logic'; - import { FieldEditorModal } from './field_editor_modal'; import { ResultDetail } from './result_detail'; import { SearchResults } from './search_results'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.test.ts index c51f3e97bf155..73df0298ecd19 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.test.ts @@ -5,25 +5,22 @@ * 2.0. */ -import { LogicMounter } from '../../../../../__mocks__/kea.mock'; +import { LogicMounter, mockFlashMessageHelpers, mockHttpValues } from '../../../../../__mocks__'; +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; -import { mockFlashMessageHelpers, mockHttpValues } from '../../../../../__mocks__'; +import { nextTick } from '@kbn/test/jest'; const contentSource = { id: 'source123' }; jest.mock('../../source_logic', () => ({ SourceLogic: { values: { contentSource } }, })); -import { AppLogic } from '../../../../app_logic'; jest.mock('../../../../app_logic', () => ({ AppLogic: { values: { isOrganization: true } }, })); +import { AppLogic } from '../../../../app_logic'; -import { nextTick } from '@kbn/test/jest'; - -import { exampleResult } from '../../../../__mocks__/content_sources.mock'; import { LEAVE_UNASSIGNED_FIELD } from './constants'; - import { DisplaySettingsLogic, defaultSearchResultConfig } from './display_settings_logic'; describe('DisplaySettingsLogic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts index 7c5946d08292c..62d959083af59 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts @@ -5,24 +5,23 @@ * 2.0. */ -import { cloneDeep, isEqual, differenceBy } from 'lodash'; import { DropResult } from 'react-beautiful-dnd'; import { kea, MakeLogicType } from 'kea'; - -import { HttpLogic } from '../../../../../shared/http'; +import { cloneDeep, isEqual, differenceBy } from 'lodash'; import { setSuccessMessage, clearFlashMessages, flashAPIErrors, } from '../../../../../shared/flash_messages'; - +import { HttpLogic } from '../../../../../shared/http'; import { AppLogic } from '../../../../app_logic'; +import { DetailField, SearchResultConfig, OptionValue, Result } from '../../../../types'; import { SourceLogic } from '../../source_logic'; -import { DetailField, SearchResultConfig, OptionValue, Result } from '../../../../types'; import { LEAVE_UNASSIGNED_FIELD, SUCCESS_MESSAGE } from './constants'; + export interface DisplaySettingsResponseProps { sourceName: string; searchResultConfig: SearchResultConfig; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_router.test.tsx index f216cbf286b94..f04afe60aa49d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_router.test.tsx @@ -10,12 +10,11 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues } from '../../../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; - import { Route, Switch } from 'react-router-dom'; -import { DisplaySettings } from './display_settings'; +import { shallow } from 'enzyme'; +import { DisplaySettings } from './display_settings'; import { DisplaySettingsRouter } from './display_settings_router'; describe('DisplaySettingsRouter', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_router.tsx index fa9817494ee09..bd753631ed48c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_router.tsx @@ -6,12 +6,11 @@ */ import React from 'react'; +import { Route, Switch } from 'react-router-dom'; import { useValues } from 'kea'; -import { Route, Switch } from 'react-router-dom'; import { AppLogic } from '../../../../app_logic'; - import { DISPLAY_SETTINGS_RESULT_DETAIL_PATH, DISPLAY_SETTINGS_SEARCH_RESULT_PATH, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx index 381e4fe4c0b25..15e1fe0ed417c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx @@ -8,11 +8,11 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues } from '../../../../../__mocks__'; -import { shallow } from 'enzyme'; +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; -import { exampleResult } from '../../../../__mocks__/content_sources.mock'; +import { shallow } from 'enzyme'; import { ExampleResultDetailCard } from './example_result_detail_card'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx index 46c06f28af6d6..93a7d660215f0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx @@ -14,9 +14,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elasti import { URL_LABEL } from '../../../../constants'; -import { DisplaySettingsLogic } from './display_settings_logic'; - import { CustomSourceIcon } from './custom_source_icon'; +import { DisplaySettingsLogic } from './display_settings_logic'; import { TitleField } from './title_field'; export const ExampleResultDetailCard: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.test.tsx index d08195f3e83bc..6f90c1045ae31 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.test.tsx @@ -8,14 +8,13 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues } from '../../../../../__mocks__'; -import { shallow } from 'enzyme'; +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; -import { exampleResult } from '../../../../__mocks__/content_sources.mock'; +import { shallow } from 'enzyme'; import { CustomSourceIcon } from './custom_source_icon'; - import { ExampleSearchResultGroup } from './example_search_result_group'; describe('ExampleSearchResultGroup', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.tsx index 5d5f73467f82c..df89eed38ae92 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.tsx @@ -7,15 +7,15 @@ import React from 'react'; -import { isColorDark, hexToRgb } from '@elastic/eui'; import classNames from 'classnames'; import { useValues } from 'kea'; -import { DESCRIPTION_LABEL } from '../../../../constants'; +import { isColorDark, hexToRgb } from '@elastic/eui'; -import { DisplaySettingsLogic } from './display_settings_logic'; +import { DESCRIPTION_LABEL } from '../../../../constants'; import { CustomSourceIcon } from './custom_source_icon'; +import { DisplaySettingsLogic } from './display_settings_logic'; import { SubtitleField } from './subtitle_field'; import { TitleField } from './title_field'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.test.tsx index 6241bcf05fbff..49845e79d86aa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.test.tsx @@ -8,14 +8,13 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues } from '../../../../../__mocks__'; -import { shallow } from 'enzyme'; +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; -import { exampleResult } from '../../../../__mocks__/content_sources.mock'; +import { shallow } from 'enzyme'; import { CustomSourceIcon } from './custom_source_icon'; - import { ExampleStandoutResult } from './example_standout_result'; describe('ExampleStandoutResult', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.tsx index 3c139001d3ea2..48c3149e622bd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.tsx @@ -14,9 +14,8 @@ import { isColorDark, hexToRgb } from '@elastic/eui'; import { DESCRIPTION_LABEL } from '../../../../constants'; -import { DisplaySettingsLogic } from './display_settings_logic'; - import { CustomSourceIcon } from './custom_source_icon'; +import { DisplaySettingsLogic } from './display_settings_logic'; import { SubtitleField } from './subtitle_field'; import { TitleField } from './title_field'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/field_editor_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/field_editor_modal.test.tsx index 82687165d0535..fe7bced843841 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/field_editor_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/field_editor_modal.test.tsx @@ -8,13 +8,13 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../../__mocks__'; -import { shallow } from 'enzyme'; +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; -import { EuiModal, EuiSelect, EuiFieldText } from '@elastic/eui'; +import { shallow } from 'enzyme'; -import { exampleResult } from '../../../../__mocks__/content_sources.mock'; +import { EuiModal, EuiSelect, EuiFieldText } from '@elastic/eui'; import { FieldEditorModal } from './field_editor_modal'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.test.tsx index 217a8142af5d5..768573ce80fee 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.test.tsx @@ -6,9 +6,8 @@ */ import '../../../../../__mocks__/shallow_useeffect.mock'; - import { setMockValues, setMockActions } from '../../../../../__mocks__'; -import { shallow, mount } from 'enzyme'; +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; /** * Mocking necessary due to console warnings from react d-n-d, which EUI uses @@ -40,12 +39,11 @@ jest.mock('react-beautiful-dnd', () => ({ import React from 'react'; -import { EuiTextColor } from '@elastic/eui'; +import { shallow, mount } from 'enzyme'; -import { exampleResult } from '../../../../__mocks__/content_sources.mock'; +import { EuiTextColor } from '@elastic/eui'; import { ExampleResultDetailCard } from './example_result_detail_card'; - import { ResultDetail } from './result_detail'; describe('ResultDetail', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.tsx index 8382ddc9e82b3..6832f075476e7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.tsx @@ -28,10 +28,9 @@ import { } from '@elastic/eui'; import { ADD_FIELD_LABEL, EDIT_FIELD_LABEL, REMOVE_FIELD_LABEL } from '../../../../constants'; -import { VISIBLE_FIELDS_TITLE, EMPTY_FIELDS_DESCRIPTION, PREVIEW_TITLE } from './constants'; +import { VISIBLE_FIELDS_TITLE, EMPTY_FIELDS_DESCRIPTION, PREVIEW_TITLE } from './constants'; import { DisplaySettingsLogic } from './display_settings_logic'; - import { ExampleResultDetailCard } from './example_result_detail_card'; export const ResultDetail: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.test.tsx index 26116a7e736bc..28de0006f162f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.test.tsx @@ -8,16 +8,15 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../../__mocks__'; -import { shallow } from 'enzyme'; +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; -import { exampleResult } from '../../../../__mocks__/content_sources.mock'; +import { shallow } from 'enzyme'; +import { LEAVE_UNASSIGNED_FIELD } from './constants'; import { ExampleSearchResultGroup } from './example_search_result_group'; import { ExampleStandoutResult } from './example_standout_result'; - -import { LEAVE_UNASSIGNED_FIELD } from './constants'; import { SearchResults } from './search_results'; describe('SearchResults', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx index b2ba2b13e5ec3..859fb2d5d2a20 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx @@ -21,9 +21,8 @@ import { EuiTitle, } from '@elastic/eui'; -import { DisplaySettingsLogic } from './display_settings_logic'; - import { DESCRIPTION_LABEL } from '../../../../constants'; + import { LEAVE_UNASSIGNED_FIELD, SEARCH_RESULTS_TITLE, @@ -34,7 +33,7 @@ import { STANDARD_RESULTS_TITLE, STANDARD_RESULTS_DESCRIPTION, } from './constants'; - +import { DisplaySettingsLogic } from './display_settings_logic'; import { ExampleSearchResultGroup } from './example_search_result_group'; import { ExampleStandoutResult } from './example_standout_result'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/subtitle_field.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/subtitle_field.test.tsx index 812af1b1fd26b..76c28ae3d4060 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/subtitle_field.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/subtitle_field.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { SubtitleField } from './subtitle_field'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/title_field.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/title_field.test.tsx index f2a82f058c0de..2ed4aa0b0fad1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/title_field.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/title_field.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { TitleField } from './title_field'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.test.tsx index 0e91d2a3a4a28..a30f1bfbd596a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.test.tsx @@ -8,14 +8,14 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues } from '../../../../__mocks__'; +import { fullContentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiEmptyPrompt, EuiPanel, EuiTable } from '@elastic/eui'; -import { fullContentSources } from '../../../__mocks__/content_sources.mock'; - import { Loading } from '../../../../shared/loading'; import { ComponentLoader } from '../../../components/shared/component_loader'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.tsx index a67adfdd3802a..34d7edd99c376 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.tsx @@ -9,8 +9,6 @@ import React from 'react'; import { useValues } from 'kea'; -import { FormattedMessage } from '@kbn/i18n/react'; - import { EuiEmptyPrompt, EuiFlexGroup, @@ -30,7 +28,21 @@ import { EuiTextColor, EuiTitle, } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { Loading } from '../../../../shared/loading'; +import { EuiPanelTo } from '../../../../shared/react_router_helpers'; +import { AppLogic } from '../../../app_logic'; +import aclImage from '../../../assets/supports_acl.svg'; +import { ComponentLoader } from '../../../components/shared/component_loader'; +import { CredentialItem } from '../../../components/shared/credential_item'; +import { LicenseBadge } from '../../../components/shared/license_badge'; +import { ViewContentHeader } from '../../../components/shared/view_content_header'; +import { + RECENT_ACTIVITY_TITLE, + CREDENTIALS_TITLE, + DOCUMENTATION_LINK_TITLE, +} from '../../../constants'; import { CUSTOM_SOURCE_DOCS_URL, DOCUMENT_PERMISSIONS_DOCS_URL, @@ -38,12 +50,6 @@ import { EXTERNAL_IDENTITIES_DOCS_URL, getGroupPath, } from '../../../routes'; - -import { - RECENT_ACTIVITY_TITLE, - CREDENTIALS_TITLE, - DOCUMENTATION_LINK_TITLE, -} from '../../../constants'; import { SOURCES_NO_CONTENT_TITLE, CONTENT_SUMMARY_TITLE, @@ -70,17 +76,6 @@ import { DOC_PERMISSIONS_DESCRIPTION, CUSTOM_CALLOUT_TITLE, } from '../constants'; - -import { AppLogic } from '../../../app_logic'; - -import { ComponentLoader } from '../../../components/shared/component_loader'; -import { CredentialItem } from '../../../components/shared/credential_item'; -import { ViewContentHeader } from '../../../components/shared/view_content_header'; -import { LicenseBadge } from '../../../components/shared/license_badge'; -import { Loading } from '../../../../shared/loading'; -import { EuiPanelTo } from '../../../../shared/react_router_helpers'; - -import aclImage from '../../../assets/supports_acl.svg'; import { SourceLogic } from '../source_logic'; export const Overview: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema.test.tsx index b30c5d78fd42f..ccf3275ffd96f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema.test.tsx @@ -8,21 +8,20 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../../__mocks__'; +import { mostRecentIndexJob } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiEmptyPrompt, EuiFieldSearch } from '@elastic/eui'; -import { mostRecentIndexJob } from '../../../../__mocks__/content_sources.mock'; - import { IndexingStatus } from '../../../../../shared/indexing_status'; import { Loading } from '../../../../../shared/loading'; import { SchemaAddFieldModal } from '../../../../../shared/schema/schema_add_field_modal'; -import { SchemaFieldsTable } from './schema_fields_table'; - import { Schema } from './schema'; +import { SchemaFieldsTable } from './schema_fields_table'; describe('Schema', () => { const initializeSchema = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema.tsx index fe48e1c14ff41..77d1002a9ad26 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema.tsx @@ -20,17 +20,12 @@ import { EuiPanel, } from '@elastic/eui'; -import { getReindexJobRoute } from '../../../../routes'; -import { AppLogic } from '../../../../app_logic'; - +import { IndexingStatus } from '../../../../../shared/indexing_status'; import { Loading } from '../../../../../shared/loading'; -import { ViewContentHeader } from '../../../../components/shared/view_content_header'; - import { SchemaAddFieldModal } from '../../../../../shared/schema/schema_add_field_modal'; -import { IndexingStatus } from '../../../../../shared/indexing_status'; - -import { SchemaFieldsTable } from './schema_fields_table'; -import { SchemaLogic } from './schema_logic'; +import { AppLogic } from '../../../../app_logic'; +import { ViewContentHeader } from '../../../../components/shared/view_content_header'; +import { getReindexJobRoute } from '../../../../routes'; import { SCHEMA_ADD_FIELD_BUTTON, @@ -42,6 +37,8 @@ import { SCHEMA_EMPTY_SCHEMA_TITLE, SCHEMA_EMPTY_SCHEMA_DESCRIPTION, } from './constants'; +import { SchemaFieldsTable } from './schema_fields_table'; +import { SchemaLogic } from './schema_logic'; export const Schema: React.FC = () => { const { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_change_errors.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_change_errors.test.tsx index 421aa04692bd7..e9276b8ec3878 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_change_errors.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_change_errors.test.tsx @@ -10,9 +10,10 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; import { useParams } from 'react-router-dom'; +import { shallow } from 'enzyme'; + import { SchemaErrorsAccordion } from '../../../../../shared/schema/schema_errors_accordion'; import { SchemaChangeErrors } from './schema_change_errors'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_change_errors.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_change_errors.tsx index a212052e1beba..29cb2b7589220 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_change_errors.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_change_errors.tsx @@ -14,8 +14,9 @@ import { EuiSpacer } from '@elastic/eui'; import { SchemaErrorsAccordion } from '../../../../../shared/schema/schema_errors_accordion'; import { ViewContentHeader } from '../../../../components/shared/view_content_header'; -import { SchemaLogic } from './schema_logic'; + import { SCHEMA_ERRORS_HEADING } from './constants'; +import { SchemaLogic } from './schema_logic'; export const SchemaChangeErrors: React.FC = () => { const { activeReindexJobId, sourceId } = useParams() as { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_fields_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_fields_table.test.tsx index a9d6494dcee00..bc0363d55da69 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_fields_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_fields_table.test.tsx @@ -10,6 +10,7 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { SchemaExistingField } from '../../../../../shared/schema/schema_existing_field'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_fields_table.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_fields_table.tsx index a683d9384f636..3f56a2cfc745b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_fields_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_fields_table.tsx @@ -9,8 +9,6 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { EuiFlexGroup, EuiFlexItem, @@ -21,13 +19,15 @@ import { EuiTableRow, EuiTableRowCell, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { SchemaExistingField } from '../../../../../shared/schema/schema_existing_field'; -import { SchemaLogic } from './schema_logic'; + import { SCHEMA_ERRORS_TABLE_FIELD_NAME_HEADER, SCHEMA_ERRORS_TABLE_DATA_TYPE_HEADER, } from './constants'; +import { SchemaLogic } from './schema_logic'; export const SchemaFieldsTable: React.FC = () => { const { updateExistingFieldType } = useActions(SchemaLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.test.ts index 5957822eb8d49..af650d95efaf6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.test.ts @@ -6,6 +6,7 @@ */ import { LogicMounter, mockFlashMessageHelpers, mockHttpValues } from '../../../../../__mocks__'; +import { mostRecentIndexJob } from '../../../../__mocks__/content_sources.mock'; import { nextTick } from '@kbn/test/jest'; @@ -14,7 +15,6 @@ jest.mock('../../source_logic', () => ({ SourceLogic: { values: { contentSource } }, })); -import { AppLogic } from '../../../../app_logic'; jest.mock('../../../../app_logic', () => ({ AppLogic: { values: { isOrganization: true } }, })); @@ -22,16 +22,15 @@ jest.mock('../../../../app_logic', () => ({ const spyScrollTo = jest.fn(); Object.defineProperty(global.window, 'scrollTo', { value: spyScrollTo }); -import { mostRecentIndexJob } from '../../../../__mocks__/content_sources.mock'; import { TEXT } from '../../../../../shared/constants/field_types'; import { ADD, UPDATE } from '../../../../../shared/constants/operations'; +import { AppLogic } from '../../../../app_logic'; import { SCHEMA_FIELD_ERRORS_ERROR_MESSAGE, SCHEMA_FIELD_ADDED_MESSAGE, SCHEMA_UPDATED_MESSAGE, } from './constants'; - import { SchemaLogic, dataTypeOptions } from './schema_logic'; describe('SchemaLogic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.ts index 09b608af43536..9906efe707d85 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.ts @@ -5,23 +5,20 @@ * 2.0. */ -import { cloneDeep, isEqual } from 'lodash'; import { kea, MakeLogicType } from 'kea'; - -import { HttpLogic } from '../../../../../shared/http'; +import { cloneDeep, isEqual } from 'lodash'; import { TEXT } from '../../../../../shared/constants/field_types'; import { ADD, UPDATE } from '../../../../../shared/constants/operations'; -import { IndexJob, TOperation, Schema, SchemaTypes } from '../../../../../shared/types'; -import { OptionValue } from '../../../../types'; - import { flashAPIErrors, setSuccessMessage, clearFlashMessages, } from '../../../../../shared/flash_messages'; - +import { HttpLogic } from '../../../../../shared/http'; +import { IndexJob, TOperation, Schema, SchemaTypes } from '../../../../../shared/types'; import { AppLogic } from '../../../../app_logic'; +import { OptionValue } from '../../../../types'; import { SourceLogic } from '../../source_logic'; import { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_added.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_added.test.tsx index d3256a86baebc..ddf89159b2675 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_added.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_added.test.tsx @@ -10,10 +10,10 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockActions } from '../../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; - import { useLocation } from 'react-router-dom'; +import { shallow } from 'enzyme'; + import { Loading } from '../../../../shared/loading'; import { SourceAdded } from './source_added'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_added.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_added.tsx index 5901c06b3f66c..5f1d2ed0c81c3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_added.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_added.tsx @@ -6,10 +6,10 @@ */ import React, { useEffect } from 'react'; +import { useLocation } from 'react-router-dom'; import { Location } from 'history'; import { useActions } from 'kea'; -import { useLocation } from 'react-router-dom'; import { Loading } from '../../../../shared/loading'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.test.tsx index 6a773b81909a3..12399d4822a13 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.test.tsx @@ -8,8 +8,11 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../__mocks__'; +import { fullContentSources, contentItems } from '../../../__mocks__/content_sources.mock'; +import { meta } from '../../../__mocks__/meta.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { @@ -21,12 +24,9 @@ import { EuiLink, } from '@elastic/eui'; -import { meta } from '../../../__mocks__/meta.mock'; -import { fullContentSources, contentItems } from '../../../__mocks__/content_sources.mock'; - import { DEFAULT_META } from '../../../../shared/constants'; +import { Loading } from '../../../../shared/loading'; import { ComponentLoader } from '../../../components/shared/component_loader'; -import { Loading } from '../../../../../applications/shared/loading'; import { TablePaginationBar } from '../../../components/shared/table_pagination_bar'; import { SourceContent } from './source_content'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.tsx index 61676279ada03..3dd8ad1dc7899 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.tsx @@ -11,9 +11,6 @@ import { useActions, useValues } from 'kea'; import { startCase } from 'lodash'; import moment from 'moment'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - import { EuiButton, EuiButtonEmpty, @@ -31,20 +28,17 @@ import { EuiTableRowCell, EuiLink, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; -import { CUSTOM_SOURCE_DOCS_URL } from '../../../routes'; -import { SourceContentItem } from '../../../types'; - +import { Loading } from '../../../../shared/loading'; import { TruncatedContent } from '../../../../shared/truncate'; - -const MAX_LENGTH = 28; - import { ComponentLoader } from '../../../components/shared/component_loader'; -import { Loading } from '../../../../../applications/shared/loading'; import { TablePaginationBar } from '../../../components/shared/table_pagination_bar'; import { ViewContentHeader } from '../../../components/shared/view_content_header'; - import { CUSTOM_SERVICE_TYPE } from '../../../constants'; +import { CUSTOM_SOURCE_DOCS_URL } from '../../../routes'; +import { SourceContentItem } from '../../../types'; import { NO_CONTENT_MESSAGE, CUSTOM_DOCUMENTATION_LINK, @@ -55,9 +49,10 @@ import { SOURCE_CONTENT_TITLE, CONTENT_LOADING_TEXT, } from '../constants'; - import { SourceLogic } from '../source_logic'; +const MAX_LENGTH = 28; + export const SourceContent: React.FC = () => { const [searchTerm, setSearchTerm] = useState(''); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_info_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_info_card.test.tsx index 7a8a932f391e1..7c4c02cdc9819 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_info_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_info_card.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { EuiBadge, EuiHealth, EuiText, EuiTitle } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_info_card.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_info_card.tsx index 8334c34d6c615..765836191ff00 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_info_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_info_card.tsx @@ -18,7 +18,6 @@ import { } from '@elastic/eui'; import { SourceIcon } from '../../../components/shared/source_icon'; - import { REMOTE_SOURCE_LABEL, CREATED_LABEL, STATUS_LABEL, READY_TEXT } from '../constants'; interface SourceInfoCardProps { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.test.tsx index d73da79375ffe..f13189afe8252 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.test.tsx @@ -8,14 +8,14 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../__mocks__'; +import { fullContentSources, sourceConfigData } from '../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiConfirmModal } from '@elastic/eui'; -import { fullContentSources, sourceConfigData } from '../../../__mocks__/content_sources.mock'; - import { SourceConfigFields } from '../../../components/shared/source_config_fields'; import { SourceSettings } from './source_settings'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.tsx index 2fa00c7f029f1..75a1779a1fda8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.tsx @@ -6,12 +6,10 @@ */ import React, { useEffect, useState, ChangeEvent, FormEvent } from 'react'; +import { Link } from 'react-router-dom'; import { useActions, useValues } from 'kea'; import { isEmpty } from 'lodash'; -import { Link } from 'react-router-dom'; - -import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButton, @@ -23,7 +21,12 @@ import { EuiFlexItem, EuiFormRow, } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { AppLogic } from '../../../app_logic'; +import { ContentSection } from '../../../components/shared/content_section'; +import { SourceConfigFields } from '../../../components/shared/source_config_fields'; +import { ViewContentHeader } from '../../../components/shared/view_content_header'; import { CANCEL_BUTTON, OK_BUTTON, @@ -31,6 +34,8 @@ import { SAVE_CHANGES_BUTTON, REMOVE_BUTTON, } from '../../../constants'; +import { SourceDataItem } from '../../../types'; +import { AddSourceLogic } from '../components/add_source/add_source_logic'; import { SOURCE_SETTINGS_TITLE, SOURCE_SETTINGS_DESCRIPTION, @@ -41,16 +46,7 @@ import { SOURCE_REMOVE_TITLE, SOURCE_REMOVE_DESCRIPTION, } from '../constants'; - -import { ContentSection } from '../../../components/shared/content_section'; -import { SourceConfigFields } from '../../../components/shared/source_config_fields'; -import { ViewContentHeader } from '../../../components/shared/view_content_header'; - -import { SourceDataItem } from '../../../types'; -import { AppLogic } from '../../../app_logic'; -import { AddSourceLogic } from '../components/add_source/add_source_logic'; import { staticSourceData } from '../source_data'; - import { SourceLogic } from '../source_logic'; export const SourceSettings: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx index fe5545668e4ce..59f3bfb0a5611 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx @@ -8,12 +8,13 @@ import { setMockValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; +import { SideNavLink } from '../../../../shared/layout'; import { CUSTOM_SERVICE_TYPE } from '../../../constants'; -import { SourceSubNav } from './source_sub_nav'; -import { SideNavLink } from '../../../../shared/layout'; +import { SourceSubNav } from './source_sub_nav'; describe('SourceSubNav', () => { it('renders empty when no group id present', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.tsx index 739b9ec138f29..99cebd5ded585 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.tsx @@ -6,15 +6,12 @@ */ import React from 'react'; + import { useValues } from 'kea'; +import { SideNavLink } from '../../../../shared/layout'; import { AppLogic } from '../../../app_logic'; import { NAV, CUSTOM_SERVICE_TYPE } from '../../../constants'; - -import { SourceLogic } from '../source_logic'; - -import { SideNavLink } from '../../../../shared/layout'; - import { getContentSourcePath, SOURCE_DETAILS_PATH, @@ -23,6 +20,7 @@ import { SOURCE_DISPLAY_SETTINGS_PATH, SOURCE_SETTINGS_PATH, } from '../../../routes'; +import { SourceLogic } from '../source_logic'; export const SourceSubNav: React.FC = () => { const { isOrganization } = useValues(AppLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/organization_sources.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/organization_sources.test.tsx index 68addbacc5a23..b986658f19fb3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/organization_sources.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/organization_sources.test.tsx @@ -8,18 +8,16 @@ import '../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../__mocks__'; - -import { shallow } from 'enzyme'; +import { contentSources } from '../../__mocks__/content_sources.mock'; import React from 'react'; import { Redirect } from 'react-router-dom'; -import { contentSources } from '../../__mocks__/content_sources.mock'; +import { shallow } from 'enzyme'; import { Loading } from '../../../shared/loading'; import { SourcesTable } from '../../components/shared/sources_table'; import { ViewContentHeader } from '../../components/shared/view_content_header'; - import { ADD_SOURCE_PATH, getSourcesPath } from '../../routes'; import { OrganizationSources } from './organization_sources'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/organization_sources.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/organization_sources.tsx index 24c1f130da50d..4559003b4597f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/organization_sources.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/organization_sources.tsx @@ -6,11 +6,16 @@ */ import React, { useEffect } from 'react'; +import { Link, Redirect } from 'react-router-dom'; import { useActions, useValues } from 'kea'; -import { Link, Redirect } from 'react-router-dom'; import { EuiButton } from '@elastic/eui'; + +import { Loading } from '../../../shared/loading'; +import { ContentSection } from '../../components/shared/content_section'; +import { SourcesTable } from '../../components/shared/sources_table'; +import { ViewContentHeader } from '../../components/shared/view_content_header'; import { ADD_SOURCE_PATH, getSourcesPath } from '../../routes'; import { @@ -18,14 +23,7 @@ import { ORG_SOURCES_HEADER_TITLE, ORG_SOURCES_HEADER_DESCRIPTION, } from './constants'; - -import { Loading } from '../../../shared/loading'; -import { ContentSection } from '../../components/shared/content_section'; -import { SourcesTable } from '../../components/shared/sources_table'; -import { ViewContentHeader } from '../../components/shared/view_content_header'; - import { SourcesLogic } from './sources_logic'; - import { SourcesView } from './sources_view'; export const OrganizationSources: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx index d68b451ffa6f5..087681fa89603 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx @@ -12,11 +12,15 @@ import { useActions, useValues } from 'kea'; import { EuiCallOut, EuiEmptyPrompt, EuiSpacer, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { LicensingLogic } from '../../../../applications/shared/licensing'; - -import { ADD_SOURCE_PATH, getSourcesPath } from '../../routes'; - +import { LicensingLogic } from '../../../shared/licensing'; +import { Loading } from '../../../shared/loading'; +import { EuiButtonTo } from '../../../shared/react_router_helpers'; +import { AppLogic } from '../../app_logic'; import noSharedSourcesIcon from '../../assets/share_circle.svg'; +import { ContentSection } from '../../components/shared/content_section'; +import { SourcesTable } from '../../components/shared/sources_table'; +import { ViewContentHeader } from '../../components/shared/view_content_header'; +import { ADD_SOURCE_PATH, getSourcesPath } from '../../routes'; import { AND, @@ -34,16 +38,8 @@ import { LICENSE_CALLOUT_TITLE, LICENSE_CALLOUT_DESCRIPTION, } from './constants'; - -import { Loading } from '../../../shared/loading'; -import { EuiButtonTo } from '../../../shared/react_router_helpers'; -import { ContentSection } from '../../components/shared/content_section'; -import { SourcesTable } from '../../components/shared/sources_table'; -import { ViewContentHeader } from '../../components/shared/view_content_header'; - -import { AppLogic } from '../../app_logic'; -import { SourcesView } from './sources_view'; import { SourcesLogic } from './sources_logic'; +import { SourcesView } from './sources_view'; // TODO: Remove this after links in Kibana sidenav interface SidebarLink { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx index 5b34603bca68f..cdad8e07a88be 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; +import { SOURCE_NAMES, SOURCE_OBJ_TYPES, GITHUB_LINK_TITLE } from '../../constants'; import { ADD_BOX_PATH, ADD_CONFLUENCE_PATH, @@ -62,11 +63,8 @@ import { ZENDESK_DOCS_URL, CUSTOM_SOURCE_DOCS_URL, } from '../../routes'; - import { FeatureIds, SourceDataItem } from '../../types'; -import { SOURCE_NAMES, SOURCE_OBJ_TYPES, GITHUB_LINK_TITLE } from '../../constants'; - const connectStepDescription = { attachments: i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.sources.connectStepDescription.attachments', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts index 15df7ddc99395..d20d0576d11ce 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts @@ -12,16 +12,16 @@ import { mockKibanaValues, expectedAsyncError, } from '../../../__mocks__'; +import { fullContentSources, contentItems } from '../../__mocks__/content_sources.mock'; +import { meta } from '../../__mocks__/meta.mock'; + +import { DEFAULT_META } from '../../../shared/constants'; -import { AppLogic } from '../../app_logic'; jest.mock('../../app_logic', () => ({ AppLogic: { values: { isOrganization: true } }, })); +import { AppLogic } from '../../app_logic'; -import { fullContentSources, contentItems } from '../../__mocks__/content_sources.mock'; -import { meta } from '../../__mocks__/meta.mock'; - -import { DEFAULT_META } from '../../../shared/constants'; import { NOT_FOUND_PATH } from '../../routes'; import { SourceLogic } from './source_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts index c1f5d6033543f..72700ce42c75d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts @@ -9,17 +9,15 @@ import { kea, MakeLogicType } from 'kea'; import { i18n } from '@kbn/i18n'; -import { HttpLogic } from '../../../shared/http'; -import { KibanaLogic } from '../../../shared/kibana'; - +import { DEFAULT_META } from '../../../shared/constants'; import { flashAPIErrors, setSuccessMessage, setQueuedSuccessMessage, clearFlashMessages, } from '../../../shared/flash_messages'; - -import { DEFAULT_META } from '../../../shared/constants'; +import { HttpLogic } from '../../../shared/http'; +import { KibanaLogic } from '../../../shared/kibana'; import { AppLogic } from '../../app_logic'; import { NOT_FOUND_PATH, SOURCES_PATH, getSourcesPath } from '../../routes'; import { ContentSourceFullData, Meta, DocumentSummaryItem, SourceContentItem } from '../../types'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx index cf3c075d0c1e9..004f7e5e45bfa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx @@ -8,20 +8,17 @@ import '../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../__mocks__'; +import { contentSources } from '../../__mocks__/content_sources.mock'; import React from 'react'; -import { shallow } from 'enzyme'; import { useParams } from 'react-router-dom'; - import { Route, Switch } from 'react-router-dom'; -import { contentSources } from '../../__mocks__/content_sources.mock'; +import { shallow } from 'enzyme'; import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; - -import { NAV } from '../../constants'; - import { Loading } from '../../../shared/loading'; +import { NAV } from '../../constants'; import { DisplaySettingsRouter } from './components/display_settings'; import { Overview } from './components/overview'; @@ -29,7 +26,6 @@ import { Schema } from './components/schema'; import { SchemaChangeErrors } from './components/schema/schema_change_errors'; import { SourceContent } from './components/source_content'; import { SourceSettings } from './components/source_settings'; - import { SourceRouter } from './source_router'; describe('SourceRouter', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx index ac450441f8783..ef9788efbdaf2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx @@ -6,24 +6,19 @@ */ import React, { useEffect } from 'react'; +import { Route, Switch, useParams } from 'react-router-dom'; import { useActions, useValues } from 'kea'; import moment from 'moment'; -import { Route, Switch, useParams } from 'react-router-dom'; import { EuiButton, EuiCallOut, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { Loading } from '../../../shared/loading'; import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; - +import { AppLogic } from '../../app_logic'; import { NAV } from '../../constants'; - -import { - SOURCE_DISABLED_CALLOUT_TITLE, - SOURCE_DISABLED_CALLOUT_DESCRIPTION, - SOURCE_DISABLED_CALLOUT_BUTTON, -} from './constants'; - +import { CUSTOM_SERVICE_TYPE } from '../../constants'; import { ENT_SEARCH_LICENSE_MANAGEMENT, REINDEX_JOB_PATH, @@ -36,13 +31,6 @@ import { getSourcesPath, } from '../../routes'; -import { AppLogic } from '../../app_logic'; - -import { Loading } from '../../../shared/loading'; - -import { CUSTOM_SERVICE_TYPE } from '../../constants'; -import { SourceLogic } from './source_logic'; - import { DisplaySettingsRouter } from './components/display_settings'; import { Overview } from './components/overview'; import { Schema } from './components/schema'; @@ -50,6 +38,12 @@ import { SchemaChangeErrors } from './components/schema/schema_change_errors'; import { SourceContent } from './components/source_content'; import { SourceInfoCard } from './components/source_info_card'; import { SourceSettings } from './components/source_settings'; +import { + SOURCE_DISABLED_CALLOUT_TITLE, + SOURCE_DISABLED_CALLOUT_DESCRIPTION, + SOURCE_DISABLED_CALLOUT_BUTTON, +} from './constants'; +import { SourceLogic } from './source_logic'; export const SourceRouter: React.FC = () => { const { sourceId } = useParams() as { sourceId: string }; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.test.ts index b7db569eb704c..13844f51b2319 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.test.ts @@ -11,13 +11,12 @@ import { mockHttpValues, expectedAsyncError, } from '../../../__mocks__'; +import { configuredSources, contentSources } from '../../__mocks__/content_sources.mock'; -import { AppLogic } from '../../app_logic'; jest.mock('../../app_logic', () => ({ AppLogic: { values: { isOrganization: true } }, })); - -import { configuredSources, contentSources } from '../../__mocks__/content_sources.mock'; +import { AppLogic } from '../../app_logic'; import { SourcesLogic, fetchSourceStatuses, POLLING_INTERVAL } from './sources_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts index 5108ed45501f7..9de2b447619a6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts @@ -5,22 +5,18 @@ * 2.0. */ -import { cloneDeep, findIndex } from 'lodash'; - import { kea, MakeLogicType } from 'kea'; +import { cloneDeep, findIndex } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { HttpLogic } from '../../../shared/http'; - import { flashAPIErrors, setQueuedSuccessMessage } from '../../../shared/flash_messages'; - +import { HttpLogic } from '../../../shared/http'; +import { AppLogic } from '../../app_logic'; import { Connector, ContentSourceDetails, ContentSourceStatus, SourceDataItem } from '../../types'; import { staticSourceData } from './source_data'; -import { AppLogic } from '../../app_logic'; - interface ServerStatuses { [key: string]: string; } diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_router.test.tsx index b1a6ea128ac8c..2438061c67759 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_router.test.tsx @@ -10,10 +10,10 @@ import '../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; - import { Route, Switch, Redirect } from 'react-router-dom'; +import { shallow } from 'enzyme'; + import { ADD_SOURCE_PATH, PERSONAL_SOURCES_PATH, SOURCES_PATH, getSourcesPath } from '../../routes'; import { SourcesRouter } from './sources_router'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_router.tsx index 28ad2fe3a3965..b7857cf4612a2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_router.tsx @@ -6,16 +6,16 @@ */ import React, { useEffect } from 'react'; +import { Redirect, Route, Switch, useLocation } from 'react-router-dom'; import { Location } from 'history'; import { useActions, useValues } from 'kea'; -import { Redirect, Route, Switch, useLocation } from 'react-router-dom'; +import { FlashMessages } from '../../../shared/flash_messages'; import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { LicensingLogic } from '../../../shared/licensing'; import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; - -import { LicensingLogic } from '../../../../applications/shared/licensing'; - +import { AppLogic } from '../../app_logic'; import { NAV } from '../../constants'; import { ADD_SOURCE_PATH, @@ -26,17 +26,13 @@ import { getSourcesPath, } from '../../routes'; -import { FlashMessages } from '../../../shared/flash_messages'; - -import { AppLogic } from '../../app_logic'; -import { staticSourceData } from './source_data'; -import { SourcesLogic } from './sources_logic'; - import { AddSource, AddSourceList } from './components/add_source'; import { SourceAdded } from './components/source_added'; import { OrganizationSources } from './organization_sources'; import { PrivateSources } from './private_sources'; +import { staticSourceData } from './source_data'; import { SourceRouter } from './source_router'; +import { SourcesLogic } from './sources_logic'; import './sources.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_view.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_view.test.tsx index 742d19ebbd156..06d7ecff50299 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_view.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_view.test.tsx @@ -9,10 +9,10 @@ import '../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../__mocks__'; -import { shallow } from 'enzyme'; - import React from 'react'; +import { shallow } from 'enzyme'; + import { EuiModal } from '@elastic/eui'; import { Loading } from '../../../shared/loading'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_view.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_view.tsx index ac70d74cc3d78..c62f0b00258d6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_view.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_view.tsx @@ -9,9 +9,6 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - import { EuiButton, EuiLink, @@ -25,10 +22,11 @@ import { EuiOverlayMask, EuiText, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { Loading } from '../../../shared/loading'; import { SourceIcon } from '../../components/shared/source_icon'; - import { EXTERNAL_IDENTITIES_DOCS_URL, DOCUMENT_PERMISSIONS_DOCS_URL } from '../../routes'; import { @@ -36,7 +34,6 @@ import { DOCUMENT_PERMISSIONS_LINK, UNDERSTAND_BUTTON, } from './constants'; - import { SourcesLogic } from './sources_logic'; interface SourcesViewProps { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/error_state/error_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/error_state/error_state.test.tsx index 0408bbf3e7e84..a8fcdfd7cb257 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/error_state/error_state.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/error_state/error_state.test.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { ErrorStatePrompt } from '../../../shared/error_state'; + import { ErrorState } from './'; describe('ErrorState', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/error_state/error_state.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/error_state/error_state.tsx index 74e52912b551b..8116d55542820 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/error_state/error_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/error_state/error_state.tsx @@ -8,6 +8,7 @@ // TODO: Remove EuiPage & EuiPageBody before exposing full app import React from 'react'; + import { EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui'; import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/__mocks__/groups_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/__mocks__/groups_logic.mock.ts index 3df7fbb5a0596..0e072210d2489 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/__mocks__/groups_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/__mocks__/groups_logic.mock.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { ContentSource, User, Group } from '../../../types'; - import { DEFAULT_META } from '../../../../shared/constants'; +import { ContentSource, User, Group } from '../../../types'; export const mockGroupsValues = { groups: [] as Group[], diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.test.tsx index 1065c2c2df4c3..26ac5e484f0d7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.test.tsx @@ -8,12 +8,13 @@ import { setMockValues, setMockActions } from '../../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; -import { AddGroupModal } from './add_group_modal'; +import { shallow } from 'enzyme'; import { EuiModal, EuiOverlayMask } from '@elastic/eui'; +import { AddGroupModal } from './add_group_modal'; + describe('AddGroupModal', () => { const closeNewGroupModal = jest.fn(); const saveNewGroup = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.tsx index f49c978d06e90..fb82e9393f2a2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.tsx @@ -8,7 +8,6 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiButton, @@ -22,9 +21,9 @@ import { EuiModalHeaderTitle, EuiOverlayMask, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { CANCEL_BUTTON } from '../../../constants'; - import { GroupsLogic } from '../groups_logic'; const ADD_GROUP_HEADER = i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.test.tsx index 2dffe89f38569..9118bc5e7adf3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.test.tsx @@ -8,12 +8,13 @@ import { setMockActions } from '../../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; -import { ClearFiltersLink } from './clear_filters_link'; +import { shallow } from 'enzyme'; import { EuiLink } from '@elastic/eui'; +import { ClearFiltersLink } from './clear_filters_link'; + describe('ClearFiltersLink', () => { const resetGroupsFilters = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.tsx index 3734148ea3afa..6aeb2241bca61 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.tsx @@ -8,9 +8,9 @@ import React from 'react'; import { useActions } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiLink } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { GroupsLogic } from '../groups_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.test.tsx index 965a4887f4359..a460070772d1f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.test.tsx @@ -8,14 +8,15 @@ import { users } from '../../../__mocks__/users.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiFieldSearch, EuiFilterSelectItem, EuiCard, EuiPopoverTitle } from '@elastic/eui'; -import { FilterableUsersList } from './filterable_users_list'; - import { User } from '../../../types'; +import { FilterableUsersList } from './filterable_users_list'; + const mockSetState = jest.fn(); const useStateMock: any = (initState: any) => [initState, mockSetState]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.tsx index ef222e934260b..8a7875b5e8310 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.tsx @@ -7,8 +7,6 @@ import React, { useState } from 'react'; -import { i18n } from '@kbn/i18n'; - import { EuiCard, EuiFieldSearch, @@ -17,6 +15,7 @@ import { EuiPopoverTitle, EuiSpacer, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { User } from '../../../types'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.test.tsx index 36a99425c9793..1813b766b9875 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.test.tsx @@ -9,13 +9,14 @@ import { setMockActions } from '../../../../__mocks__'; import { users } from '../../../__mocks__/users.mock'; import React from 'react'; -import { shallow } from 'enzyme'; -import { FilterableUsersPopover } from './filterable_users_popover'; -import { FilterableUsersList } from './filterable_users_list'; +import { shallow } from 'enzyme'; import { EuiFilterGroup, EuiPopover } from '@elastic/eui'; +import { FilterableUsersList } from './filterable_users_list'; +import { FilterableUsersPopover } from './filterable_users_popover'; + const closePopover = jest.fn(); const addFilteredUser = jest.fn(); const removeFilteredUser = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.tsx index b47232197c47f..3cf4d97c781d9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.tsx @@ -12,8 +12,8 @@ import { useActions } from 'kea'; import { EuiFilterGroup, EuiPopover } from '@elastic/eui'; import { User } from '../../../types'; - import { GroupsLogic } from '../groups_logic'; + import { FilterableUsersList } from './filterable_users_list'; interface FilterableUsersPopoverProps { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.test.tsx index 8ee14b7c82cc4..949ae9d502e73 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.test.tsx @@ -6,16 +6,17 @@ */ import { setMockValues } from '../../../../__mocks__'; -import { groups } from '../../../__mocks__/groups.mock'; import { contentSources } from '../../../__mocks__/content_sources.mock'; +import { groups } from '../../../__mocks__/groups.mock'; import React from 'react'; -import { shallow } from 'enzyme'; -import { GroupManagerModal } from './group_manager_modal'; +import { shallow } from 'enzyme'; import { EuiOverlayMask, EuiModal, EuiEmptyPrompt } from '@elastic/eui'; +import { GroupManagerModal } from './group_manager_modal'; + const hideModal = jest.fn(); const selectAll = jest.fn(); const saveItems = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.tsx index ae5c042fc27dc..b4317ed9bd417 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.tsx @@ -9,8 +9,6 @@ import React from 'react'; import { useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { EuiButton, EuiButtonEmpty, @@ -26,15 +24,13 @@ import { EuiOverlayMask, EuiSpacer, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { EuiButtonTo } from '../../../../shared/react_router_helpers'; - -import { Group } from '../../../types'; +import noSharedSourcesIcon from '../../../assets/share_circle.svg'; import { CANCEL_BUTTON } from '../../../constants'; import { SOURCES_PATH } from '../../../routes'; - -import noSharedSourcesIcon from '../../../assets/share_circle.svg'; - +import { Group } from '../../../types'; import { GroupLogic } from '../group_logic'; import { GroupsLogic } from '../groups_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.test.tsx index ea49ae09f3a25..e39d72a861b6f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.test.tsx @@ -9,21 +9,22 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; import React from 'react'; + import { shallow } from 'enzyme'; +import { EuiFieldText } from '@elastic/eui'; + +import { Loading } from '../../../../shared/loading'; +import { ContentSection } from '../../../components/shared/content_section'; +import { SourcesTable } from '../../../components/shared/sources_table'; +import { ViewContentHeader } from '../../../components/shared/view_content_header'; + import { GroupOverview, EMPTY_SOURCES_DESCRIPTION, EMPTY_USERS_DESCRIPTION, } from './group_overview'; -import { ContentSection } from '../../../components/shared/content_section'; -import { ViewContentHeader } from '../../../components/shared/view_content_header'; -import { SourcesTable } from '../../../components/shared/sources_table'; -import { Loading } from '../../../../shared/loading'; - -import { EuiFieldText } from '@elastic/eui'; - const deleteGroup = jest.fn(); const showSharedSourcesModal = jest.fn(); const showManageUsersModal = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.tsx index ca67c2aac98ad..df9c0b5db9b7d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.tsx @@ -9,8 +9,6 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { EuiButton, EuiConfirmModal, @@ -22,20 +20,19 @@ import { EuiSpacer, EuiHorizontalRule, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; -import { CANCEL_BUTTON } from '../../../constants'; - -import { AppLogic } from '../../../app_logic'; +import { Loading } from '../../../../shared/loading'; import { TruncatedContent } from '../../../../shared/truncate'; +import { AppLogic } from '../../../app_logic'; import { ContentSection } from '../../../components/shared/content_section'; -import { ViewContentHeader } from '../../../components/shared/view_content_header'; -import { Loading } from '../../../../shared/loading'; import { SourcesTable } from '../../../components/shared/sources_table'; +import { ViewContentHeader } from '../../../components/shared/view_content_header'; +import { CANCEL_BUTTON } from '../../../constants'; +import { GroupLogic, MAX_NAME_LENGTH } from '../group_logic'; import { GroupUsersTable } from './group_users_table'; -import { GroupLogic, MAX_NAME_LENGTH } from '../group_logic'; - export const EMPTY_SOURCES_DESCRIPTION = i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.groups.overview.emptySourcesDescription', { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.test.tsx index 19898172fb4e7..205eafd69cd10 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.test.tsx @@ -9,14 +9,15 @@ import { setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import moment from 'moment'; +import { EuiTableRow } from '@elastic/eui'; + import { GroupRow, NO_USERS_MESSAGE, NO_SOURCES_MESSAGE } from './group_row'; import { GroupUsers } from './group_users'; -import { EuiTableRow } from '@elastic/eui'; - describe('GroupRow', () => { beforeEach(() => { setMockValues({ isFederatedAuth: true }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.tsx index 1a085aea93cc6..5e89d4491d597 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.tsx @@ -6,21 +6,20 @@ */ import React from 'react'; -import moment from 'moment'; -import { useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; +import { useValues } from 'kea'; +import moment from 'moment'; import { EuiTableRow, EuiTableRowCell, EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; -import { TruncatedContent } from '../../../../shared/truncate'; import { EuiLinkTo } from '../../../../shared/react_router_helpers'; - -import { Group } from '../../../types'; - +import { TruncatedContent } from '../../../../shared/truncate'; import { AppLogic } from '../../../app_logic'; import { getGroupPath } from '../../../routes'; +import { Group } from '../../../types'; import { MAX_NAME_LENGTH } from '../group_logic'; + import { GroupSources } from './group_sources'; import { GroupUsers } from './group_users'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.test.tsx index e4c626a28c1a6..23c00d0fa209e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.test.tsx @@ -8,13 +8,14 @@ import { contentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; +import { EuiFilterGroup } from '@elastic/eui'; + import { GroupRowSourcesDropdown } from './group_row_sources_dropdown'; import { SourceOptionItem } from './source_option_item'; -import { EuiFilterGroup } from '@elastic/eui'; - const onButtonClick = jest.fn(); const closePopover = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.tsx index a8f8c18cc6f38..77d7de91caf7c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.tsx @@ -7,9 +7,8 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; - import { EuiFilterGroup, EuiPopover, EuiPopoverTitle, EuiButtonEmpty } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { ContentSource } from '../../../types'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.test.tsx index 7dae74155d0d6..e75b325a4eae9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.test.tsx @@ -9,12 +9,13 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import { users } from '../../../__mocks__/users.mock'; import React from 'react'; + import { shallow, mount } from 'enzyme'; import { EuiLoadingContent, EuiButtonEmpty } from '@elastic/eui'; -import { GroupRowUsersDropdown } from './group_row_users_dropdown'; import { FilterableUsersPopover } from './filterable_users_popover'; +import { GroupRowUsersDropdown } from './group_row_users_dropdown'; const fetchGroupUsers = jest.fn(); const onButtonClick = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.tsx index 9ca9c8339ba6a..aaf715fc71615 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.tsx @@ -12,6 +12,7 @@ import { useActions, useValues } from 'kea'; import { EuiLoadingContent, EuiButtonEmpty } from '@elastic/eui'; import { GroupsLogic } from '../groups_logic'; + import { FilterableUsersPopover } from './filterable_users_popover'; interface GroupRowUsersDropdownProps { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.test.tsx index 49305ec33d228..4a9244486bf30 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.test.tsx @@ -9,14 +9,15 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; import React from 'react'; + import { shallow } from 'enzyme'; +import { EuiTable, EuiEmptyPrompt, EuiRange } from '@elastic/eui'; + import { Loading } from '../../../../shared/loading'; import { GroupSourcePrioritization } from './group_source_prioritization'; -import { EuiTable, EuiEmptyPrompt, EuiRange } from '@elastic/eui'; - const updatePriority = jest.fn(); const saveGroupSourcePrioritization = jest.fn(); const showSharedSourcesModal = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.tsx index 6907618e40b46..9b131e730b937 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.tsx @@ -9,8 +9,6 @@ import React, { ChangeEvent, MouseEvent } from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { EuiButton, EuiEmptyPrompt, @@ -26,14 +24,13 @@ import { EuiTableRow, EuiTableRowCell, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { Loading } from '../../../../shared/loading'; -import { ViewContentHeader } from '../../../components/shared/view_content_header'; import { SourceIcon } from '../../../components/shared/source_icon'; - -import { GroupLogic } from '../group_logic'; - +import { ViewContentHeader } from '../../../components/shared/view_content_header'; import { ContentSource } from '../../../types'; +import { GroupLogic } from '../group_logic'; const HEADER_TITLE = i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.groups.sourceProioritization.headerTitle', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.test.tsx index fd2a5e2bc6d9a..a245f0a768b0e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.test.tsx @@ -8,15 +8,15 @@ import { contentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; -import { shallow } from 'enzyme'; -import { GroupSources } from './group_sources'; -import { GroupRowSourcesDropdown } from './group_row_sources_dropdown'; +import { shallow } from 'enzyme'; import { SourceIcon } from '../../../components/shared/source_icon'; - import { ContentSourceDetails } from '../../../types'; +import { GroupRowSourcesDropdown } from './group_row_sources_dropdown'; +import { GroupSources } from './group_sources'; + describe('GroupSources', () => { it('renders', () => { const wrapper = shallow(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.tsx index ae3b5000941b1..97739e46caba4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.tsx @@ -9,7 +9,6 @@ import React, { useState } from 'react'; import { SourceIcon } from '../../../components/shared/source_icon'; import { MAX_TABLE_ROW_ICONS } from '../../../constants'; - import { ContentSource } from '../../../types'; import { GroupRowSourcesDropdown } from './group_row_sources_dropdown'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.test.tsx index ead4af451ee7a..e4dde81949bfa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.test.tsx @@ -8,12 +8,13 @@ import { setMockValues } from '../../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; -import { GroupSubNav } from './group_sub_nav'; +import { shallow } from 'enzyme'; import { SideNavLink } from '../../../../shared/layout'; +import { GroupSubNav } from './group_sub_nav'; + describe('GroupSubNav', () => { it('renders empty when no group id present', () => { setMockValues({ group: {} }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.tsx index e2bd6e8ae91f2..c5fc0717d1105 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.tsx @@ -6,14 +6,13 @@ */ import React from 'react'; -import { useValues } from 'kea'; -import { GroupLogic } from '../group_logic'; -import { NAV } from '../../../constants'; +import { useValues } from 'kea'; import { SideNavLink } from '../../../../shared/layout'; - +import { NAV } from '../../../constants'; import { getGroupPath, getGroupSourcePrioritizationPath } from '../../../routes'; +import { GroupLogic } from '../group_logic'; export const GroupSubNav: React.FC = () => { const { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.test.tsx index f1bc063e1a223..eba79ea70177d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.test.tsx @@ -8,14 +8,14 @@ import { users } from '../../../__mocks__/users.mock'; import React from 'react'; + import { shallow } from 'enzyme'; +import { UserIcon } from '../../../components/shared/user_icon'; import { User } from '../../../types'; -import { GroupUsers } from './group_users'; import { GroupRowUsersDropdown } from './group_row_users_dropdown'; - -import { UserIcon } from '../../../components/shared/user_icon'; +import { GroupUsers } from './group_users'; const props = { groupUsers: users, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.tsx index 850910428c4b2..6e60df15ed30a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.tsx @@ -9,7 +9,6 @@ import React, { useState } from 'react'; import { UserIcon } from '../../../components/shared/user_icon'; import { MAX_TABLE_ROW_ICONS } from '../../../constants'; - import { User } from '../../../types'; import { GroupRowUsersDropdown } from './group_row_users_dropdown'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx index 83e945547438f..a6376d7653627 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx @@ -9,14 +9,15 @@ import { setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; import React from 'react'; + import { shallow } from 'enzyme'; -import { User } from '../../../types'; +import { EuiTable, EuiTablePagination } from '@elastic/eui'; -import { GroupUsersTable } from './group_users_table'; import { TableHeader } from '../../../../shared/table_header'; +import { User } from '../../../types'; -import { EuiTable, EuiTablePagination } from '@elastic/eui'; +import { GroupUsersTable } from './group_users_table'; const group = groups[0]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.tsx index 4b337fda9143d..5d070b1a21b7d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.tsx @@ -9,17 +9,14 @@ import React, { useState } from 'react'; import { useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { EuiTable, EuiTableBody, EuiTablePagination } from '@elastic/eui'; import { Pager } from '@elastic/eui'; - -import { User } from '../../../types'; +import { i18n } from '@kbn/i18n'; import { TableHeader } from '../../../../shared/table_header'; -import { UserRow } from '../../../components/shared/user_row'; - import { AppLogic } from '../../../app_logic'; +import { UserRow } from '../../../components/shared/user_row'; +import { User } from '../../../types'; import { GroupLogic } from '../group_logic'; const USERS_PER_PAGE = 10; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx index d6724499490cf..f60a13ec296d5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx @@ -8,18 +8,18 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; -import { DEFAULT_META } from '../../../../shared/constants'; - import React from 'react'; + import { shallow } from 'enzyme'; +import { EuiTable, EuiTableHeaderCell } from '@elastic/eui'; + +import { DEFAULT_META } from '../../../../shared/constants'; import { TablePaginationBar } from '../../../components/shared/table_pagination_bar'; -import { GroupsTable } from './groups_table'; -import { GroupRow } from './group_row'; import { ClearFiltersLink } from './clear_filters_link'; - -import { EuiTable, EuiTableHeaderCell } from '@elastic/eui'; +import { GroupRow } from './group_row'; +import { GroupsTable } from './groups_table'; const setActivePage = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.tsx index 31f549c3e2065..95292116cba05 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.tsx @@ -9,8 +9,6 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { EuiSpacer, EuiTable, @@ -18,14 +16,14 @@ import { EuiTableHeader, EuiTableHeaderCell, } from '@elastic/eui'; - -import { TablePaginationBar } from '../../../components/shared/table_pagination_bar'; +import { i18n } from '@kbn/i18n'; import { AppLogic } from '../../../app_logic'; +import { TablePaginationBar } from '../../../components/shared/table_pagination_bar'; import { GroupsLogic } from '../groups_logic'; -import { GroupRow } from './group_row'; import { ClearFiltersLink } from './clear_filters_link'; +import { GroupRow } from './group_row'; const GROUP_TABLE_HEADER = i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.groups.groupsTable.groupTableHeader', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/manage_users_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/manage_users_modal.test.tsx index 059dff969aee3..49d51dfc7254c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/manage_users_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/manage_users_modal.test.tsx @@ -9,11 +9,12 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import { users } from '../../../__mocks__/users.mock'; import React from 'react'; + import { shallow } from 'enzyme'; -import { ManageUsersModal } from './manage_users_modal'; import { FilterableUsersList } from './filterable_users_list'; import { GroupManagerModal } from './group_manager_modal'; +import { ManageUsersModal } from './manage_users_modal'; const addGroupUser = jest.fn(); const removeGroupUser = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/shared_sources_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/shared_sources_modal.test.tsx index f937ded7d4918..dd72850a06ad9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/shared_sources_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/shared_sources_modal.test.tsx @@ -9,10 +9,11 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; import React from 'react'; + import { shallow } from 'enzyme'; -import { SharedSourcesModal } from './shared_sources_modal'; import { GroupManagerModal } from './group_manager_modal'; +import { SharedSourcesModal } from './shared_sources_modal'; import { SourcesList } from './sources_list'; const group = groups[0]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.test.tsx index d037a49875a7e..bad60e15ed2d0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.test.tsx @@ -8,14 +8,14 @@ import { contentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; -import { shallow } from 'enzyme'; -import { SourceOptionItem } from './source_option_item'; +import { shallow } from 'enzyme'; import { TruncatedContent } from '../../../../shared/truncate'; - import { SourceIcon } from '../../../components/shared/source_icon'; +import { SourceOptionItem } from './source_option_item'; + describe('SourceOptionItem', () => { it('renders', () => { const wrapper = shallow(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.tsx index a87980415bd1f..e2da597a83598 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { TruncatedContent } from '../../../../shared/truncate'; - import { SourceIcon } from '../../../components/shared/source_icon'; import { ContentSource } from '../../../types'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/sources_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/sources_list.test.tsx index 56e700c10e04c..05fe2c92f9f72 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/sources_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/sources_list.test.tsx @@ -8,12 +8,13 @@ import { contentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; -import { shallow } from 'enzyme'; -import { SourcesList } from './sources_list'; +import { shallow } from 'enzyme'; import { EuiFilterSelectItem } from '@elastic/eui'; +import { SourcesList } from './sources_list'; + const addFilteredSource = jest.fn(); const removeFilteredSource = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.test.tsx index b7efe84df180c..1e2a57da9ad2e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.test.tsx @@ -9,11 +9,11 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import { contentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; -import { shallow } from 'enzyme'; -import { TableFilterSourcesDropdown } from './table_filter_sources_dropdown'; +import { shallow } from 'enzyme'; import { SourcesList } from './sources_list'; +import { TableFilterSourcesDropdown } from './table_filter_sources_dropdown'; const addFilteredSource = jest.fn(); const removeFilteredSource = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.tsx index b38d5fc55b6f8..5f75340d562ef 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.tsx @@ -9,11 +9,11 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { EuiFilterButton, EuiFilterGroup, EuiPopover } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { GroupsLogic } from '../groups_logic'; + import { SourcesList } from './sources_list'; const FILTER_SOURCES_BUTTON_TEXT = i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.test.tsx index 9eaaa64b1c4e4..e472563862015 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.test.tsx @@ -9,10 +9,11 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import { users } from '../../../__mocks__/users.mock'; import React from 'react'; + import { shallow } from 'enzyme'; -import { TableFilterUsersDropdown } from './table_filter_users_dropdown'; import { FilterableUsersPopover } from './filterable_users_popover'; +import { TableFilterUsersDropdown } from './table_filter_users_dropdown'; const closeFilterUsersDropdown = jest.fn(); const toggleFilterUsersDropdown = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.tsx index 9ddb955767c14..c09e1e3cf87cc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.tsx @@ -9,11 +9,11 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { EuiFilterButton } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { GroupsLogic } from '../groups_logic'; + import { FilterableUsersPopover } from './filterable_users_popover'; const FILTER_USERS_BUTTON_TEXT = i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx index 0fdaf74376494..bcc58c394b516 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx @@ -8,13 +8,14 @@ import { setMockActions, setMockValues } from '../../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; -import { TableFilters } from './table_filters'; +import { shallow } from 'enzyme'; import { EuiFieldSearch } from '@elastic/eui'; + import { TableFilterSourcesDropdown } from './table_filter_sources_dropdown'; import { TableFilterUsersDropdown } from './table_filter_users_dropdown'; +import { TableFilters } from './table_filters'; const setFilterValue = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.tsx index cfd40e1a0df4e..e9ea6a7c6b4aa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.tsx @@ -9,9 +9,8 @@ import React, { ChangeEvent } from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { EuiFieldSearch, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { AppLogic } from '../../../app_logic'; import { GroupsLogic } from '../groups_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/user_option_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/user_option_item.test.tsx index 01f67cc910afd..6c8dbbde2e69f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/user_option_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/user_option_item.test.tsx @@ -8,12 +8,14 @@ import { users } from '../../../__mocks__/users.mock'; import React from 'react'; + import { shallow } from 'enzyme'; -import { UserOptionItem } from './user_option_item'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; + import { UserIcon } from '../../../components/shared/user_icon'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { UserOptionItem } from './user_option_item'; const user = users[0]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts index d8d41b5e2888a..836efa82995fc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts @@ -11,15 +11,15 @@ import { mockFlashMessageHelpers, mockHttpValues, } from '../../../__mocks__'; +import { groups } from '../../__mocks__/groups.mock'; import { nextTick } from '@kbn/test/jest'; -import { groups } from '../../__mocks__/groups.mock'; +import { GROUPS_PATH } from '../../routes'; + import { mockGroupValues } from './__mocks__/group_logic.mock'; import { GroupLogic } from './group_logic'; -import { GROUPS_PATH } from '../../routes'; - describe('GroupLogic', () => { const { mount } = new LogicMounter(GroupLogic); const { http } = mockHttpValues; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts index 7e7ce838434f5..f23b182b98649 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts @@ -7,10 +7,9 @@ import { kea, MakeLogicType } from 'kea'; import { isEqual } from 'lodash'; + import { i18n } from '@kbn/i18n'; -import { HttpLogic } from '../../../shared/http'; -import { KibanaLogic } from '../../../shared/kibana'; import { clearFlashMessages, flashAPIErrors, @@ -18,9 +17,9 @@ import { setQueuedSuccessMessage, setQueuedErrorMessage, } from '../../../shared/flash_messages'; - +import { HttpLogic } from '../../../shared/http'; +import { KibanaLogic } from '../../../shared/kibana'; import { GROUPS_PATH } from '../../routes'; - import { ContentSourceDetails, GroupDetails, User, SourcePriority } from '../../types'; export const MAX_NAME_LENGTH = 40; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.test.tsx index a04fc4c744790..0b218f2496154 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.test.tsx @@ -7,25 +7,21 @@ import '../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../__mocks__'; +import { groups } from '../../__mocks__/groups.mock'; import React from 'react'; -import { shallow } from 'enzyme'; - import { Route, Switch } from 'react-router-dom'; -import { groups } from '../../__mocks__/groups.mock'; +import { shallow } from 'enzyme'; +import { FlashMessages } from '../../../shared/flash_messages'; import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { GroupOverview } from './components/group_overview'; import { GroupSourcePrioritization } from './components/group_source_prioritization'; - -import { GroupRouter } from './group_router'; - -import { FlashMessages } from '../../../shared/flash_messages'; - import { ManageUsersModal } from './components/manage_users_modal'; import { SharedSourcesModal } from './components/shared_sources_modal'; +import { GroupRouter } from './group_router'; describe('GroupRouter', () => { const initializeGroup = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.tsx index 82eb7931dfcdc..a5b8bd138d0c8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.tsx @@ -6,23 +6,21 @@ */ import React, { useEffect } from 'react'; +import { Route, Switch, useParams } from 'react-router-dom'; import { useActions, useValues } from 'kea'; -import { Route, Switch, useParams } from 'react-router-dom'; import { FlashMessages } from '../../../shared/flash_messages'; import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; - -import { GROUP_SOURCE_PRIORITIZATION_PATH, GROUP_PATH } from '../../routes'; import { NAV } from '../../constants'; -import { GroupLogic } from './group_logic'; - -import { ManageUsersModal } from './components/manage_users_modal'; -import { SharedSourcesModal } from './components/shared_sources_modal'; +import { GROUP_SOURCE_PRIORITIZATION_PATH, GROUP_PATH } from '../../routes'; import { GroupOverview } from './components/group_overview'; import { GroupSourcePrioritization } from './components/group_source_prioritization'; +import { ManageUsersModal } from './components/manage_users_modal'; +import { SharedSourcesModal } from './components/shared_sources_modal'; +import { GroupLogic } from './group_logic'; export const GroupRouter: React.FC = () => { const { groupId } = useParams() as { groupId: string }; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx index d67dd5857561e..8470c5d3e0f66 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx @@ -11,23 +11,22 @@ import { groups } from '../../__mocks__/groups.mock'; import { meta } from '../../__mocks__/meta.mock'; import React from 'react'; + import { shallow } from 'enzyme'; -import { Groups } from './groups'; +import { EuiFieldSearch, EuiLoadingSpinner } from '@elastic/eui'; -import { ViewContentHeader } from '../../components/shared/view_content_header'; -import { Loading } from '../../../shared/loading'; +import { DEFAULT_META } from '../../../shared/constants'; import { FlashMessages } from '../../../shared/flash_messages'; +import { Loading } from '../../../shared/loading'; +import { EuiButtonTo } from '../../../shared/react_router_helpers'; +import { ViewContentHeader } from '../../components/shared/view_content_header'; import { AddGroupModal } from './components/add_group_modal'; import { ClearFiltersLink } from './components/clear_filters_link'; import { GroupsTable } from './components/groups_table'; import { TableFilters } from './components/table_filters'; - -import { DEFAULT_META } from '../../../shared/constants'; - -import { EuiFieldSearch, EuiLoadingSpinner } from '@elastic/eui'; -import { EuiButtonTo } from '../../../shared/react_router_helpers'; +import { Groups } from './groups'; const getSearchResults = jest.fn(); const openNewGroupModal = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.tsx index 7a8b9343691f9..b2bf0364b2d1f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.tsx @@ -8,26 +8,22 @@ import React, { useEffect } from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiSpacer } from '@elastic/eui'; -import { EuiButtonTo } from '../../../shared/react_router_helpers'; - -import { AppLogic } from '../../app_logic'; +import { i18n } from '@kbn/i18n'; +import { FlashMessages, FlashMessagesLogic } from '../../../shared/flash_messages'; import { Loading } from '../../../shared/loading'; +import { EuiButtonTo } from '../../../shared/react_router_helpers'; +import { AppLogic } from '../../app_logic'; import { ViewContentHeader } from '../../components/shared/view_content_header'; - import { getGroupPath, USERS_PATH } from '../../routes'; -import { FlashMessages, FlashMessagesLogic } from '../../../shared/flash_messages'; - -import { GroupsLogic } from './groups_logic'; - import { AddGroupModal } from './components/add_group_modal'; import { ClearFiltersLink } from './components/clear_filters_link'; import { GroupsTable } from './components/groups_table'; import { TableFilters } from './components/table_filters'; +import { GroupsLogic } from './groups_logic'; export const Groups: React.FC = () => { const { messages } = useValues(FlashMessagesLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts index 26d7f9784cc6e..806c6e1c69f84 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts @@ -6,15 +6,15 @@ */ import { LogicMounter, mockFlashMessageHelpers, mockHttpValues } from '../../../__mocks__'; +import { contentSources } from '../../__mocks__/content_sources.mock'; +import { groups } from '../../__mocks__/groups.mock'; +import { users } from '../../__mocks__/users.mock'; import { nextTick } from '@kbn/test/jest'; -import { DEFAULT_META } from '../../../shared/constants'; import { JSON_HEADER as headers } from '../../../../../common/constants'; +import { DEFAULT_META } from '../../../shared/constants'; -import { groups } from '../../__mocks__/groups.mock'; -import { contentSources } from '../../__mocks__/content_sources.mock'; -import { users } from '../../__mocks__/users.mock'; import { mockGroupsValues } from './__mocks__/groups_logic.mock'; import { GroupsLogic } from './groups_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts index 68a6eb7bdf344..a036cdda3d68e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts @@ -6,22 +6,20 @@ */ import { kea, MakeLogicType } from 'kea'; -import { i18n } from '@kbn/i18n'; -import { HttpLogic } from '../../../shared/http'; +import { i18n } from '@kbn/i18n'; +import { JSON_HEADER as headers } from '../../../../../common/constants'; +import { Meta } from '../../../../../common/types'; +import { DEFAULT_META } from '../../../shared/constants'; import { clearFlashMessages, flashAPIErrors, setSuccessMessage, } from '../../../shared/flash_messages'; - +import { HttpLogic } from '../../../shared/http'; import { ContentSource, Group, User } from '../../types'; -import { JSON_HEADER as headers } from '../../../../../common/constants'; -import { DEFAULT_META } from '../../../shared/constants'; -import { Meta } from '../../../../../common/types'; - export const MAX_NAME_LENGTH = 40; interface GroupsServerData { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.test.tsx index 43c31038a45c6..0295605eddd4d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.test.tsx @@ -9,14 +9,13 @@ import '../../../__mocks__/shallow_useeffect.mock'; import { setMockActions } from '../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; - import { Route, Switch } from 'react-router-dom'; -import { GroupsRouter } from './groups_router'; +import { shallow } from 'enzyme'; import { GroupRouter } from './group_router'; import { Groups } from './groups'; +import { GroupsRouter } from './groups_router'; describe('GroupsRouter', () => { const initializeGroups = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.tsx index e835a2668f3d3..d8c4f4801ba24 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.tsx @@ -6,21 +6,18 @@ */ import React, { useEffect } from 'react'; +import { Route, Switch } from 'react-router-dom'; import { useActions } from 'kea'; -import { Route, Switch } from 'react-router-dom'; - import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; - -import { GROUP_PATH, GROUPS_PATH } from '../../routes'; import { NAV } from '../../constants'; - -import { GroupsLogic } from './groups_logic'; +import { GROUP_PATH, GROUPS_PATH } from '../../routes'; import { GroupRouter } from './group_router'; import { Groups } from './groups'; +import { GroupsLogic } from './groups_logic'; import './groups.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/__mocks__/overview_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/__mocks__/overview_logic.mock.ts index f03dcfe98ddd0..787354974cb31 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/__mocks__/overview_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/__mocks__/overview_logic.mock.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { setMockValues as setMockKeaValues, setMockActions } from '../../../../__mocks__/kea.mock'; import { DEFAULT_INITIAL_APP_DATA } from '../../../../../../common/__mocks__'; +import { setMockValues as setMockKeaValues, setMockActions } from '../../../../__mocks__/kea.mock'; const { workplaceSearch: mockAppValues } = DEFAULT_INITIAL_APP_DATA; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.test.tsx index 8f962ec4cf665..68dece976a09c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.test.tsx @@ -10,6 +10,7 @@ import '../../../__mocks__/enterprise_search_url.mock'; import { mockTelemetryActions } from '../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiEmptyPrompt, EuiButton, EuiButtonEmpty } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.tsx index 68a4c4dc10f4f..2f8d06b71fc27 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { useActions } from 'kea'; import { @@ -20,8 +21,8 @@ import { EuiLinkProps, } from '@elastic/eui'; -import { TelemetryLogic } from '../../../shared/telemetry'; import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; +import { TelemetryLogic } from '../../../shared/telemetry'; interface OnboardingCardProps { title: React.ReactNode; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx index 7f676ce2faac2..7a368e7d384ea 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx @@ -6,16 +6,18 @@ */ import { mockTelemetryActions } from '../../../__mocks__'; + import './__mocks__/overview_logic.mock'; -import { setMockValues } from './__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { SOURCES_PATH, USERS_PATH } from '../../routes'; -import { OnboardingSteps, OrgNameOnboarding } from './onboarding_steps'; +import { setMockValues } from './__mocks__'; import { OnboardingCard } from './onboarding_card'; +import { OnboardingSteps, OrgNameOnboarding } from './onboarding_steps'; const account = { id: '1', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx index ae30a52c1541c..fc3998fcdfeec 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx @@ -6,8 +6,7 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; + import { useValues, useActions } from 'kea'; import { @@ -22,17 +21,18 @@ import { EuiButtonEmptyProps, EuiLinkProps, } from '@elastic/eui'; -import sharedSourcesIcon from '../../components/shared/assets/source_icons/share_circle.svg'; -import { TelemetryLogic } from '../../../shared/telemetry'; -import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; -import { SOURCES_PATH, USERS_PATH, ORG_SETTINGS_PATH } from '../../routes'; - -import { ContentSection } from '../../components/shared/content_section'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; +import { TelemetryLogic } from '../../../shared/telemetry'; import { AppLogic } from '../../app_logic'; -import { OverviewLogic } from './overview_logic'; +import sharedSourcesIcon from '../../components/shared/assets/source_icons/share_circle.svg'; +import { ContentSection } from '../../components/shared/content_section'; +import { SOURCES_PATH, USERS_PATH, ORG_SETTINGS_PATH } from '../../routes'; import { OnboardingCard } from './onboarding_card'; +import { OverviewLogic } from './overview_logic'; const SOURCES_TITLE = i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.overviewOnboardingSourcesCard.title', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.test.tsx index cf4f96f6b788b..412977f18fadf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.test.tsx @@ -6,12 +6,14 @@ */ import './__mocks__/overview_logic.mock'; -import { setMockValues } from './__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiFlexGrid } from '@elastic/eui'; +import { setMockValues } from './__mocks__'; import { OrganizationStats } from './organization_stats'; import { StatisticCard } from './statistic_card'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.tsx index 52c370caac989..525035030b8cc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.tsx @@ -6,18 +6,18 @@ */ import React from 'react'; -import { EuiFlexGrid } from '@elastic/eui'; + import { useValues } from 'kea'; -import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiFlexGrid } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { AppLogic } from '../../app_logic'; import { ContentSection } from '../../components/shared/content_section'; import { SOURCES_PATH, USERS_PATH } from '../../routes'; -import { AppLogic } from '../../app_logic'; import { OverviewLogic } from './overview_logic'; - import { StatisticCard } from './statistic_card'; export const OrganizationStats: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview.test.tsx index fc70a07e339e4..2ec2d949ff491 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview.test.tsx @@ -7,18 +7,19 @@ import '../../../__mocks__/react_router_history.mock'; import './__mocks__/overview_logic.mock'; -import { mockActions, setMockValues } from './__mocks__'; import React from 'react'; + import { shallow, mount } from 'enzyme'; import { Loading } from '../../../shared/loading'; import { ViewContentHeader } from '../../components/shared/view_content_header'; +import { mockActions, setMockValues } from './__mocks__'; import { OnboardingSteps } from './onboarding_steps'; import { OrganizationStats } from './organization_stats'; -import { RecentActivity } from './recent_activity'; import { Overview } from './overview'; +import { RecentActivity } from './recent_activity'; describe('Overview', () => { describe('non-happy-path states', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview.tsx index 07bc999922661..6bf84b585da80 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview.tsx @@ -8,22 +8,22 @@ // TODO: Remove EuiPage & EuiPageBody before exposing full app import React, { useEffect } from 'react'; + +import { useActions, useValues } from 'kea'; + import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { useActions, useValues } from 'kea'; import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { Loading } from '../../../shared/loading'; import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; - import { AppLogic } from '../../app_logic'; -import { OverviewLogic } from './overview_logic'; - -import { Loading } from '../../../shared/loading'; import { ProductButton } from '../../components/shared/product_button'; import { ViewContentHeader } from '../../components/shared/view_content_header'; import { OnboardingSteps } from './onboarding_steps'; import { OrganizationStats } from './organization_stats'; +import { OverviewLogic } from './overview_logic'; import { RecentActivity } from './recent_activity'; const ONBOARDING_HEADER_TITLE = i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.ts index 6d0beb638cd52..75513cfba3a09 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.ts @@ -6,6 +6,7 @@ */ import { kea, MakeLogicType } from 'kea'; + import { HttpLogic } from '../../../shared/http'; import { FeedActivity } from './recent_activity'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.test.tsx index 9c571bd8bc169..0b62207afc520 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.test.tsx @@ -6,15 +6,17 @@ */ import { mockTelemetryActions } from '../../../__mocks__'; + import './__mocks__/overview_logic.mock'; -import { setMockValues } from './__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiEmptyPrompt, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { setMockValues } from './__mocks__'; import { RecentActivity, RecentActivityItem } from './recent_activity'; const organization = { name: 'foo', defaultOrgName: 'bar' }; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.tsx index 1dcec989a94c7..43d3f880feef4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.tsx @@ -7,19 +7,19 @@ import React from 'react'; -import moment from 'moment'; import { useValues, useActions } from 'kea'; +import moment from 'moment'; import { EuiEmptyPrompt, EuiLink, EuiPanel, EuiSpacer, EuiLinkProps } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ContentSection } from '../../components/shared/content_section'; -import { TelemetryLogic } from '../../../shared/telemetry'; import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; -import { SOURCE_DETAILS_PATH, getContentSourcePath } from '../../routes'; +import { TelemetryLogic } from '../../../shared/telemetry'; +import { AppLogic } from '../../app_logic'; +import { ContentSection } from '../../components/shared/content_section'; import { RECENT_ACTIVITY_TITLE } from '../../constants'; +import { SOURCE_DETAILS_PATH, getContentSourcePath } from '../../routes'; -import { AppLogic } from '../../app_logic'; import { OverviewLogic } from './overview_logic'; import './recent_activity.scss'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.test.tsx index 2893c3630393e..ff1d69e406830 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.test.tsx @@ -8,6 +8,7 @@ import '../../../__mocks__/enterprise_search_url.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiCard } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.tsx index 83e6c2012a046..346debb1c5251 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { EuiCard, EuiFlexItem, EuiTitle, EuiTextColor } from '@elastic/eui'; import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/components/private_sources_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/components/private_sources_table.test.tsx index fb28fba9b3aea..4f7160ba631f1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/components/private_sources_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/components/private_sources_table.test.tsx @@ -8,7 +8,9 @@ import { setMockValues } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiSwitch } from '@elastic/eui'; import { PrivateSourcesTable } from './private_sources_table'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/components/private_sources_table.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/components/private_sources_table.tsx index 8ba29e5986e04..559b2fe3edbd1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/components/private_sources_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/components/private_sources_table.tsx @@ -24,11 +24,10 @@ import { EuiTableRowCell, EuiSpacer, } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { LicensingLogic } from '../../../../shared/licensing'; -import { SecurityLogic, PrivateSourceSection } from '../security_logic'; import { REMOTE_SOURCES_TOGGLE_TEXT, REMOTE_SOURCES_TABLE_DESCRIPTION, @@ -38,6 +37,7 @@ import { STANDARD_SOURCES_EMPTY_TABLE_TITLE, SOURCE, } from '../../../constants'; +import { SecurityLogic, PrivateSourceSection } from '../security_logic'; interface PrivateSourcesTableProps { sourceType: 'remote' | 'standard'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security.test.tsx index 24e6e5808355a..4eed6a6fefe68 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security.test.tsx @@ -9,11 +9,14 @@ import { setMockValues, setMockActions } from '../../../__mocks__'; import { unmountHandler } from '../../../__mocks__/shallow_useeffect.mock'; import React from 'react'; + import { shallow } from 'enzyme'; + import { EuiSwitch, EuiConfirmModal } from '@elastic/eui'; -import { Loading } from '../../../shared/loading'; +import { Loading } from '../../../shared/loading'; import { ViewContentHeader } from '../../components/shared/view_content_header'; + import { Security } from './security'; describe('Security', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security.tsx index 818dd34447c73..ba1ffb66f4691 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security.tsx @@ -23,15 +23,11 @@ import { EuiOverlayMask, } from '@elastic/eui'; -import { LicensingLogic } from '../../../shared/licensing'; import { FlashMessages } from '../../../shared/flash_messages'; -import { LicenseCallout } from '../../components/shared/license_callout'; +import { LicensingLogic } from '../../../shared/licensing'; import { Loading } from '../../../shared/loading'; +import { LicenseCallout } from '../../components/shared/license_callout'; import { ViewContentHeader } from '../../components/shared/view_content_header'; -import { SecurityLogic } from './security_logic'; - -import { PrivateSourcesTable } from './components/private_sources_table'; - import { SECURITY_UNSAVED_CHANGES_MESSAGE, RESET_BUTTON, @@ -46,6 +42,9 @@ import { PRIVATE_SOURCES_UPDATE_CONFIRMATION_TEXT, } from '../../constants'; +import { PrivateSourcesTable } from './components/private_sources_table'; +import { SecurityLogic } from './security_logic'; + export const Security: React.FC = () => { const [confirmModalVisible, setConfirmModalVisibility] = useState(false); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.test.ts index c2bd1be390592..02d8fdd3c30e4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.test.ts @@ -5,11 +5,13 @@ * 2.0. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; import { mockHttpValues, mockFlashMessageHelpers } from '../../../__mocks__'; -import { SecurityLogic } from './security_logic'; +import { LogicMounter } from '../../../__mocks__/kea.mock'; + import { nextTick } from '@kbn/test/jest'; +import { SecurityLogic } from './security_logic'; + describe('SecurityLogic', () => { const { http } = mockHttpValues; const { flashAPIErrors } = mockFlashMessageHelpers; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.ts index 8689cec037848..07ebec41366b2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.ts @@ -5,11 +5,10 @@ * 2.0. */ +import { kea, MakeLogicType } from 'kea'; import { cloneDeep } from 'lodash'; import { isEqual } from 'lodash'; -import { kea, MakeLogicType } from 'kea'; - import { clearFlashMessages, setSuccessMessage, @@ -17,7 +16,6 @@ import { } from '../../../shared/flash_messages'; import { HttpLogic } from '../../../shared/http'; import { AppLogic } from '../../app_logic'; - import { SOURCE_RESTRICTIONS_SUCCESS_MESSAGE } from '../../constants'; export interface PrivateSource { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/connectors.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/connectors.test.tsx index d1dd9e64c4d2d..13ef86a21a208 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/connectors.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/connectors.test.tsx @@ -8,10 +8,10 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../__mocks__'; - import { configuredSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { Loading } from '../../../../shared/loading'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/connectors.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/connectors.tsx index 5b74f6d1d2806..9387cd4602255 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/connectors.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/connectors.tsx @@ -19,12 +19,11 @@ import { EuiSpacer, } from '@elastic/eui'; -import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; import { Loading } from '../../../../shared/loading'; -import { SourceIcon } from '../../../components/shared/source_icon'; +import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; import { LicenseCallout } from '../../../components/shared/license_callout'; +import { SourceIcon } from '../../../components/shared/source_icon'; import { ViewContentHeader } from '../../../components/shared/view_content_header'; - import { CONFIGURE_BUTTON, CONNECTORS_HEADER_TITLE, @@ -36,9 +35,7 @@ import { } from '../../../constants'; import { getSourcesPath } from '../../../routes'; import { SourceDataItem } from '../../../types'; - import { staticSourceData } from '../../content_sources/source_data'; - import { SettingsLogic } from '../settings_logic'; export const Connectors: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/customize.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/customize.test.tsx index 8f77c229ad6f8..ed05829d9e082 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/customize.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/customize.test.tsx @@ -10,6 +10,7 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../__mocks__'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiFieldText } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/customize.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/customize.tsx index d57621bd397db..37f9e288f7f3d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/customize.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/customize.tsx @@ -11,16 +11,14 @@ import { useActions, useValues } from 'kea'; import { EuiButton, EuiFieldText, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui'; +import { ContentSection } from '../../../components/shared/content_section'; +import { ViewContentHeader } from '../../../components/shared/view_content_header'; import { CUSTOMIZE_HEADER_TITLE, CUSTOMIZE_HEADER_DESCRIPTION, CUSTOMIZE_NAME_LABEL, CUSTOMIZE_NAME_BUTTON, } from '../../../constants'; - -import { ContentSection } from '../../../components/shared/content_section'; -import { ViewContentHeader } from '../../../components/shared/view_content_header'; - import { SettingsLogic } from '../settings_logic'; export const Customize: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.test.tsx index 6fc9d51f42a86..55a58610e0ed6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.test.tsx @@ -8,17 +8,18 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../__mocks__'; +import { oauthApplication } from '../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiModal, EuiForm } from '@elastic/eui'; -import { oauthApplication } from '../../../__mocks__/content_sources.mock'; -import { OAUTH_DESCRIPTION, REDIRECT_INSECURE_ERROR_TEXT } from '../../../constants'; - import { CredentialItem } from '../../../components/shared/credential_item'; import { ViewContentHeader } from '../../../components/shared/view_content_header'; +import { OAUTH_DESCRIPTION, REDIRECT_INSECURE_ERROR_TEXT } from '../../../constants'; + import { OauthApplication } from './oauth_application'; describe('OauthApplication', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.tsx index 04759e4f5fdd0..28e7e2a33eaa1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.tsx @@ -26,7 +26,11 @@ import { EuiText, } from '@elastic/eui'; -import { ENT_SEARCH_LICENSE_MANAGEMENT } from '../../../routes'; +import { LicensingLogic } from '../../../../shared/licensing'; +import { ContentSection } from '../../../components/shared/content_section'; +import { CredentialItem } from '../../../components/shared/credential_item'; +import { LicenseBadge } from '../../../components/shared/license_badge'; +import { ViewContentHeader } from '../../../components/shared/view_content_header'; import { CLIENT_ID_LABEL, CLIENT_SECRET_LABEL, @@ -48,12 +52,7 @@ import { LICENSE_MODAL_DESCRIPTION, LICENSE_MODAL_LINK, } from '../../../constants'; - -import { LicensingLogic } from '../../../../shared/licensing'; -import { ContentSection } from '../../../components/shared/content_section'; -import { LicenseBadge } from '../../../components/shared/license_badge'; -import { ViewContentHeader } from '../../../components/shared/view_content_header'; -import { CredentialItem } from '../../../components/shared/credential_item'; +import { ENT_SEARCH_LICENSE_MANAGEMENT } from '../../../routes'; import { SettingsLogic } from '../settings_logic'; export const OauthApplication: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/settings_sub_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/settings_sub_nav.test.tsx index f00bb7d897e25..5cd8a3fc1cf03 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/settings_sub_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/settings_sub_nav.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { SideNavLink } from '../../../../shared/layout'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/settings_sub_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/settings_sub_nav.tsx index 20a6e349c1272..3f68997a17b8b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/settings_sub_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/settings_sub_nav.tsx @@ -7,10 +7,8 @@ import React from 'react'; -import { NAV } from '../../../constants'; - import { SideNavLink } from '../../../../shared/layout'; - +import { NAV } from '../../../constants'; import { ORG_SETTINGS_CUSTOMIZE_PATH, ORG_SETTINGS_CONNECTORS_PATH, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/source_config.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/source_config.test.tsx index 73ea92117c6df..ed9f715fd6916 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/source_config.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/source_config.test.tsx @@ -8,16 +8,17 @@ import '../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions } from '../../../../__mocks__'; +import { sourceConfigData } from '../../../__mocks__/content_sources.mock'; import React from 'react'; + import { shallow } from 'enzyme'; import { EuiConfirmModal } from '@elastic/eui'; -import { sourceConfigData } from '../../../__mocks__/content_sources.mock'; - import { Loading } from '../../../../shared/loading'; import { SaveConfig } from '../../content_sources/components/add_source/save_config'; + import { SourceConfig } from './source_config'; describe('SourceConfig', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/source_config.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/source_config.tsx index 4b59e0f3401c5..4ed223931d6a4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/source_config.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/source_config.tsx @@ -8,18 +8,16 @@ import React, { useEffect, useState } from 'react'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; import { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { Loading } from '../../../../shared/loading'; import { SourceDataItem } from '../../../types'; -import { staticSourceData } from '../../content_sources/source_data'; -import { AddSourceLogic } from '../../content_sources/components/add_source/add_source_logic'; - import { AddSourceHeader } from '../../content_sources/components/add_source/add_source_header'; +import { AddSourceLogic } from '../../content_sources/components/add_source/add_source_logic'; import { SaveConfig } from '../../content_sources/components/add_source/save_config'; - +import { staticSourceData } from '../../content_sources/source_data'; import { SettingsLogic } from '../settings_logic'; interface SourceConfigProps { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.test.ts index b8b08b8658372..a57c2c1f9ad44 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.test.ts @@ -5,15 +5,14 @@ * 2.0. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; - import { mockFlashMessageHelpers, mockHttpValues, mockKibanaValues } from '../../../__mocks__'; +import { LogicMounter } from '../../../__mocks__/kea.mock'; +import { configuredSources, oauthApplication } from '../../__mocks__/content_sources.mock'; import { nextTick } from '@kbn/test/jest'; -import { configuredSources, oauthApplication } from '../../__mocks__/content_sources.mock'; - import { ORG_UPDATED_MESSAGE, OAUTH_APP_UPDATED_MESSAGE } from '../../constants'; + import { SettingsLogic } from './settings_logic'; describe('SettingsLogic', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.ts index 5a4f366c737d5..ad552ff8f5a41 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.ts @@ -6,6 +6,7 @@ */ import { kea, MakeLogicType } from 'kea'; + import { i18n } from '@kbn/i18n'; import { @@ -14,13 +15,11 @@ import { setSuccessMessage, flashAPIErrors, } from '../../../shared/flash_messages'; -import { KibanaLogic } from '../../../shared/kibana'; import { HttpLogic } from '../../../shared/http'; - -import { Connector } from '../../types'; +import { KibanaLogic } from '../../../shared/kibana'; import { ORG_UPDATED_MESSAGE, OAUTH_APP_UPDATED_MESSAGE } from '../../constants'; - import { ORG_SETTINGS_CONNECTORS_PATH } from '../../routes'; +import { Connector } from '../../types'; interface IOauthApplication { name: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.test.tsx index 7f3ba0a8f34b3..411414fb33eaf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.test.tsx @@ -10,19 +10,17 @@ import '../../../__mocks__/shallow_useeffect.mock'; import { setMockActions } from '../../../__mocks__'; import React from 'react'; -import { shallow } from 'enzyme'; - import { Route, Redirect, Switch } from 'react-router-dom'; -import { staticSourceData } from '../content_sources/source_data'; +import { shallow } from 'enzyme'; import { FlashMessages } from '../../../shared/flash_messages'; +import { staticSourceData } from '../content_sources/source_data'; import { Connectors } from './components/connectors'; import { Customize } from './components/customize'; import { OauthApplication } from './components/oauth_application'; import { SourceConfig } from './components/source_config'; - import { SettingsRouter } from './settings_router'; describe('SettingsRouter', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.tsx index ee9122b015eff..34dcc48621a2e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.tsx @@ -6,26 +6,23 @@ */ import React, { useEffect } from 'react'; +import { Redirect, Route, Switch } from 'react-router-dom'; import { useActions } from 'kea'; -import { Redirect, Route, Switch } from 'react-router-dom'; +import { FlashMessages } from '../../../shared/flash_messages'; import { ORG_SETTINGS_PATH, ORG_SETTINGS_CUSTOMIZE_PATH, ORG_SETTINGS_CONNECTORS_PATH, ORG_SETTINGS_OAUTH_APPLICATION_PATH, } from '../../routes'; - -import { FlashMessages } from '../../../shared/flash_messages'; +import { staticSourceData } from '../content_sources/source_data'; import { Connectors } from './components/connectors'; import { Customize } from './components/customize'; import { OauthApplication } from './components/oauth_application'; import { SourceConfig } from './components/source_config'; - -import { staticSourceData } from '../content_sources/source_data'; - import { SettingsLogic } from './settings_logic'; export const SettingsRouter: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.test.tsx index 8bec56603cd80..6b03e86080402 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.test.tsx @@ -6,10 +6,12 @@ */ import React from 'react'; + import { shallow } from 'enzyme'; import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SetupGuideLayout } from '../../../shared/setup_guide'; + import { SetupGuide } from './'; describe('SetupGuide', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx index 810125fc931a6..13191f42bc566 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx @@ -6,18 +6,19 @@ */ import React from 'react'; + import { EuiSpacer, EuiTitle, EuiText, EuiButton, EuiLink } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; -import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide'; import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide'; import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; +import { DOCS_PREFIX } from '../../routes'; import GettingStarted from './assets/getting_started.png'; -import { DOCS_PREFIX } from '../../routes'; const GETTING_STARTED_LINK_URL = `${DOCS_PREFIX}/workplace-search-getting-started.html`; export const SetupGuide: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/index.ts b/x-pack/plugins/enterprise_search/public/index.ts index da343728b7d41..b7131e70fec07 100644 --- a/x-pack/plugins/enterprise_search/public/index.ts +++ b/x-pack/plugins/enterprise_search/public/index.ts @@ -6,6 +6,7 @@ */ import { PluginInitializerContext } from 'src/core/public'; + import { EnterpriseSearchPlugin } from './plugin'; export const plugin = (initializerContext: PluginInitializerContext) => { diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index c10eb74f47720..f00e81a5accf7 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -12,15 +12,15 @@ import { HttpSetup, Plugin, PluginInitializerContext, -} from 'src/core/public'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; + DEFAULT_APP_CATEGORIES, +} from '../../../../src/core/public'; +import { ChartsPluginStart } from '../../../../src/plugins/charts/public'; import { FeatureCatalogueCategory, HomePublicPluginSetup, } from '../../../../src/plugins/home/public'; import { CloudSetup } from '../../cloud/public'; import { LicensingPluginStart } from '../../licensing/public'; -import { ChartsPluginStart } from '../../../../src/plugins/charts/public'; import { APP_SEARCH_PLUGIN, diff --git a/x-pack/plugins/enterprise_search/server/__mocks__/router.mock.ts b/x-pack/plugins/enterprise_search/server/__mocks__/router.mock.ts index 88cf30bb2a549..5c19ca7062b65 100644 --- a/x-pack/plugins/enterprise_search/server/__mocks__/router.mock.ts +++ b/x-pack/plugins/enterprise_search/server/__mocks__/router.mock.ts @@ -5,13 +5,13 @@ * 2.0. */ -import { httpServiceMock, httpServerMock } from 'src/core/server/mocks'; import { IRouter, KibanaRequest, RequestHandlerContext, RouteValidatorConfig, } from 'src/core/server'; +import { httpServiceMock, httpServerMock } from 'src/core/server/mocks'; /** * Test helper that mocks Kibana's router and DRYs out various helper (callRoute, schema validation) diff --git a/x-pack/plugins/enterprise_search/server/__mocks__/routerDependencies.mock.ts b/x-pack/plugins/enterprise_search/server/__mocks__/routerDependencies.mock.ts index c84254660a728..50ff082858fc8 100644 --- a/x-pack/plugins/enterprise_search/server/__mocks__/routerDependencies.mock.ts +++ b/x-pack/plugins/enterprise_search/server/__mocks__/routerDependencies.mock.ts @@ -6,6 +6,7 @@ */ import { loggingSystemMock } from 'src/core/server/mocks'; + import { ConfigType } from '../'; export const mockLogger = loggingSystemMock.createLogger().get(); diff --git a/x-pack/plugins/enterprise_search/server/collectors/app_search/telemetry.ts b/x-pack/plugins/enterprise_search/server/collectors/app_search/telemetry.ts index 537e1b77f3e84..36ba2976f929a 100644 --- a/x-pack/plugins/enterprise_search/server/collectors/app_search/telemetry.ts +++ b/x-pack/plugins/enterprise_search/server/collectors/app_search/telemetry.ts @@ -6,6 +6,7 @@ */ import { get } from 'lodash'; + import { SavedObjectsServiceStart, Logger } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; diff --git a/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.ts b/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.ts index 732dfbd02c10b..f71c8a5444c9c 100644 --- a/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.ts +++ b/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.ts @@ -6,6 +6,7 @@ */ import { get } from 'lodash'; + import { SavedObjectsServiceStart, Logger } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; diff --git a/x-pack/plugins/enterprise_search/server/collectors/workplace_search/telemetry.ts b/x-pack/plugins/enterprise_search/server/collectors/workplace_search/telemetry.ts index 01210eba95368..e36ce94066789 100644 --- a/x-pack/plugins/enterprise_search/server/collectors/workplace_search/telemetry.ts +++ b/x-pack/plugins/enterprise_search/server/collectors/workplace_search/telemetry.ts @@ -6,6 +6,7 @@ */ import { get } from 'lodash'; + import { SavedObjectsServiceStart, Logger } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; diff --git a/x-pack/plugins/enterprise_search/server/index.ts b/x-pack/plugins/enterprise_search/server/index.ts index ac012077fdf84..c4552b9134eae 100644 --- a/x-pack/plugins/enterprise_search/server/index.ts +++ b/x-pack/plugins/enterprise_search/server/index.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { PluginInitializerContext, PluginConfigDescriptor } from 'src/core/server'; import { schema, TypeOf } from '@kbn/config-schema'; +import { PluginInitializerContext, PluginConfigDescriptor } from 'src/core/server'; + import { EnterpriseSearchPlugin } from './plugin'; export const plugin = (initializerContext: PluginInitializerContext) => { diff --git a/x-pack/plugins/enterprise_search/server/lib/check_access.test.ts b/x-pack/plugins/enterprise_search/server/lib/check_access.test.ts index 4a978c66b16d6..3c5d33fa74d3b 100644 --- a/x-pack/plugins/enterprise_search/server/lib/check_access.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/check_access.test.ts @@ -5,14 +5,15 @@ * 2.0. */ +import { spacesMock } from '../../../spaces/server/mocks'; + +import { checkAccess } from './check_access'; + jest.mock('./enterprise_search_config_api', () => ({ callEnterpriseSearchConfigAPI: jest.fn(), })); import { callEnterpriseSearchConfigAPI } from './enterprise_search_config_api'; -import { checkAccess } from './check_access'; -import { spacesMock } from '../../../spaces/server/mocks'; - const enabledSpace = { id: 'space', name: 'space', diff --git a/x-pack/plugins/enterprise_search/server/lib/check_access.ts b/x-pack/plugins/enterprise_search/server/lib/check_access.ts index 25c92d62c1203..0a5e0c9e2b832 100644 --- a/x-pack/plugins/enterprise_search/server/lib/check_access.ts +++ b/x-pack/plugins/enterprise_search/server/lib/check_access.ts @@ -6,9 +6,10 @@ */ import { KibanaRequest, Logger } from 'src/core/server'; -import { SpacesPluginStart } from '../../../spaces/server'; + import { SecurityPluginSetup } from '../../../security/server'; -import { ConfigType } from '../'; +import { SpacesPluginStart } from '../../../spaces/server'; +import { ConfigType } from '../index'; import { callEnterpriseSearchConfigAPI } from './enterprise_search_config_api'; diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts index 61aeffd99db00..6c6744ef3e32b 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts @@ -5,14 +5,15 @@ * 2.0. */ +import { DEFAULT_INITIAL_APP_DATA } from '../../common/__mocks__'; + jest.mock('node-fetch'); -// eslint-disable-next-line @typescript-eslint/no-var-requires -const fetchMock = require('node-fetch') as jest.Mock; +import fetch from 'node-fetch'; + const { Response } = jest.requireActual('node-fetch'); import { loggingSystemMock } from 'src/core/server/mocks'; -import { DEFAULT_INITIAL_APP_DATA } from '../../common/__mocks__'; import { callEnterpriseSearchConfigAPI } from './enterprise_search_config_api'; describe('callEnterpriseSearchConfigAPI', () => { @@ -101,7 +102,7 @@ describe('callEnterpriseSearchConfigAPI', () => { }); it('calls the config API endpoint', async () => { - fetchMock.mockImplementationOnce((url: string) => { + ((fetch as unknown) as jest.Mock).mockImplementationOnce((url: string) => { expect(url).toEqual('http://localhost:3002/api/ent/v2/internal/client_config'); return Promise.resolve(new Response(JSON.stringify(mockResponse))); }); @@ -117,7 +118,7 @@ describe('callEnterpriseSearchConfigAPI', () => { }); it('falls back without error when data is unavailable', async () => { - fetchMock.mockImplementationOnce((url: string) => Promise.resolve(new Response('{}'))); + ((fetch as unknown) as jest.Mock).mockReturnValueOnce(Promise.resolve(new Response('{}'))); expect(await callEnterpriseSearchConfigAPI(mockDependencies)).toEqual({ access: { @@ -180,21 +181,17 @@ describe('callEnterpriseSearchConfigAPI', () => { const config = { host: '' }; expect(await callEnterpriseSearchConfigAPI({ ...mockDependencies, config })).toEqual({}); - expect(fetchMock).not.toHaveBeenCalled(); + expect(fetch).not.toHaveBeenCalled(); }); it('handles server errors', async () => { - fetchMock.mockImplementationOnce(() => { - return Promise.reject('500'); - }); + ((fetch as unknown) as jest.Mock).mockReturnValueOnce(Promise.reject('500')); expect(await callEnterpriseSearchConfigAPI(mockDependencies)).toEqual({}); expect(mockDependencies.log.error).toHaveBeenCalledWith( 'Could not perform access check to Enterprise Search: 500' ); - fetchMock.mockImplementationOnce(() => { - return Promise.resolve('Bad Data'); - }); + ((fetch as unknown) as jest.Mock).mockReturnValueOnce(Promise.resolve('Bad Data')); expect(await callEnterpriseSearchConfigAPI(mockDependencies)).toEqual({}); expect(mockDependencies.log.error).toHaveBeenCalledWith( 'Could not perform access check to Enterprise Search: TypeError: response.json is not a function' @@ -212,7 +209,7 @@ describe('callEnterpriseSearchConfigAPI', () => { ); // Timeout - fetchMock.mockImplementationOnce(async () => { + ((fetch as unknown) as jest.Mock).mockImplementationOnce(async () => { jest.advanceTimersByTime(250); return Promise.reject({ name: 'AbortError' }); }); diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts index 9f207361cef91..0ed4ad257f30b 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts @@ -9,11 +9,12 @@ import AbortController from 'abort-controller'; import fetch from 'node-fetch'; import { KibanaRequest, Logger } from 'src/core/server'; -import { ConfigType } from '../'; -import { Access } from './check_access'; -import { InitialAppData } from '../../common/types'; import { stripTrailingSlash } from '../../common/strip_slashes'; +import { InitialAppData } from '../../common/types'; +import { ConfigType } from '../index'; + +import { Access } from './check_access'; interface Params { request: KibanaRequest; diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts index 8d47ba0ec77ba..7199067a2c8f4 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts @@ -6,6 +6,7 @@ */ import { mockConfig, mockLogger } from '../__mocks__'; + import { JSON_HEADER, READ_ONLY_MODE_HEADER } from '../../common/constants'; import { EnterpriseSearchRequestHandler } from './enterprise_search_request_handler'; @@ -13,6 +14,7 @@ import { EnterpriseSearchRequestHandler } from './enterprise_search_request_hand jest.mock('node-fetch'); // eslint-disable-next-line @typescript-eslint/no-var-requires const fetchMock = require('node-fetch') as jest.Mock; + const { Response } = jest.requireActual('node-fetch'); const responseMock = { diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts index 39590b310fc26..f47df58c4eca1 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts @@ -7,6 +7,7 @@ import fetch, { Response } from 'node-fetch'; import querystring from 'querystring'; + import { RequestHandler, RequestHandlerContext, @@ -14,8 +15,9 @@ import { KibanaResponseFactory, Logger, } from 'src/core/server'; -import { ConfigType } from '../index'; + import { JSON_HEADER, READ_ONLY_MODE_HEADER } from '../../common/constants'; +import { ConfigType } from '../index'; interface ConstructorDependencies { config: ConfigType; diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts index 569479f921cdd..1b9659899097d 100644 --- a/x-pack/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/plugins/enterprise_search/server/plugin.ts @@ -13,37 +13,39 @@ import { SavedObjectsServiceStart, IRouter, KibanaRequest, -} from 'src/core/server'; -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { SpacesPluginStart } from '../../spaces/server'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; -import { SecurityPluginSetup } from '../../security/server'; + DEFAULT_APP_CATEGORIES, +} from '../../../../src/core/server'; +import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; +import { SecurityPluginSetup } from '../../security/server'; +import { SpacesPluginStart } from '../../spaces/server'; import { ENTERPRISE_SEARCH_PLUGIN, APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN, } from '../common/constants'; -import { ConfigType } from './'; + +import { registerTelemetryUsageCollector as registerASTelemetryUsageCollector } from './collectors/app_search/telemetry'; +import { registerTelemetryUsageCollector as registerESTelemetryUsageCollector } from './collectors/enterprise_search/telemetry'; +import { registerTelemetryUsageCollector as registerWSTelemetryUsageCollector } from './collectors/workplace_search/telemetry'; + import { checkAccess } from './lib/check_access'; import { EnterpriseSearchRequestHandler, IEnterpriseSearchRequestHandler, } from './lib/enterprise_search_request_handler'; -import { enterpriseSearchTelemetryType } from './saved_objects/enterprise_search/telemetry'; -import { registerTelemetryUsageCollector as registerESTelemetryUsageCollector } from './collectors/enterprise_search/telemetry'; -import { registerTelemetryRoute } from './routes/enterprise_search/telemetry'; +import { registerAppSearchRoutes } from './routes/app_search'; import { registerConfigDataRoute } from './routes/enterprise_search/config_data'; +import { registerTelemetryRoute } from './routes/enterprise_search/telemetry'; +import { registerWorkplaceSearchRoutes } from './routes/workplace_search'; import { appSearchTelemetryType } from './saved_objects/app_search/telemetry'; -import { registerTelemetryUsageCollector as registerASTelemetryUsageCollector } from './collectors/app_search/telemetry'; -import { registerAppSearchRoutes } from './routes/app_search'; - +import { enterpriseSearchTelemetryType } from './saved_objects/enterprise_search/telemetry'; import { workplaceSearchTelemetryType } from './saved_objects/workplace_search/telemetry'; -import { registerTelemetryUsageCollector as registerWSTelemetryUsageCollector } from './collectors/workplace_search/telemetry'; -import { registerWorkplaceSearchRoutes } from './routes/workplace_search'; + +import { ConfigType } from './'; interface PluginsSetup { usageCollection?: UsageCollectionSetup; diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/engines.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/engines.ts index 49ff0353bef03..0070680985a34 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/engines.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/engines.ts @@ -7,8 +7,8 @@ import { schema } from '@kbn/config-schema'; -import { RouteDependencies } from '../../plugin'; import { ENGINES_PAGE_SIZE } from '../../../common/constants'; +import { RouteDependencies } from '../../plugin'; interface EnginesResponse { results: object[]; diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts index 233e728a3010a..92fdcb689db1d 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts @@ -7,12 +7,12 @@ import { RouteDependencies } from '../../plugin'; -import { registerEnginesRoutes } from './engines'; -import { registerCredentialsRoutes } from './credentials'; -import { registerSettingsRoutes } from './settings'; import { registerAnalyticsRoutes } from './analytics'; +import { registerCredentialsRoutes } from './credentials'; import { registerDocumentsRoutes, registerDocumentRoutes } from './documents'; +import { registerEnginesRoutes } from './engines'; import { registerSearchSettingsRoutes } from './search_settings'; +import { registerSettingsRoutes } from './settings'; export const registerAppSearchRoutes = (dependencies: RouteDependencies) => { registerEnginesRoutes(dependencies); diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.ts index f9c65eedbb13a..e2cbd409bd396 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { RouteDependencies } from '../../plugin'; import { callEnterpriseSearchConfigAPI } from '../../lib/enterprise_search_config_api'; +import { RouteDependencies } from '../../plugin'; export function registerConfigDataRoute({ router, config, log }: RouteDependencies) { router.get( diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/telemetry.test.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/telemetry.test.ts index 08c398ba3eb0d..62f68748fcea1 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/telemetry.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/telemetry.test.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { loggingSystemMock, savedObjectsServiceMock } from 'src/core/server/mocks'; import { MockRouter, mockLogger, mockDependencies } from '../../__mocks__'; +import { loggingSystemMock, savedObjectsServiceMock } from 'src/core/server/mocks'; + jest.mock('../../collectors/lib/telemetry', () => ({ incrementUICounter: jest.fn(), })); diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/telemetry.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/telemetry.ts index c8750bdff5d38..90afba414c044 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/telemetry.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/telemetry.ts @@ -7,12 +7,13 @@ import { schema } from '@kbn/config-schema'; -import { RouteDependencies } from '../../plugin'; -import { incrementUICounter } from '../../collectors/lib/telemetry'; - -import { ES_TELEMETRY_NAME } from '../../collectors/enterprise_search/telemetry'; import { AS_TELEMETRY_NAME } from '../../collectors/app_search/telemetry'; +import { ES_TELEMETRY_NAME } from '../../collectors/enterprise_search/telemetry'; +import { incrementUICounter } from '../../collectors/lib/telemetry'; import { WS_TELEMETRY_NAME } from '../../collectors/workplace_search/telemetry'; + +import { RouteDependencies } from '../../plugin'; + const productToTelemetryMap = { enterprise_search: ES_TELEMETRY_NAME, app_search: AS_TELEMETRY_NAME, diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts index c4819c3579adc..cc6226e340653 100644 --- a/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts @@ -7,11 +7,11 @@ import { RouteDependencies } from '../../plugin'; -import { registerOverviewRoute } from './overview'; import { registerGroupsRoutes } from './groups'; -import { registerSourcesRoutes } from './sources'; -import { registerSettingsRoutes } from './settings'; +import { registerOverviewRoute } from './overview'; import { registerSecurityRoutes } from './security'; +import { registerSettingsRoutes } from './settings'; +import { registerSourcesRoutes } from './sources'; export const registerWorkplaceSearchRoutes = (dependencies: RouteDependencies) => { registerOverviewRoute(dependencies); diff --git a/x-pack/plugins/enterprise_search/server/saved_objects/app_search/telemetry.ts b/x-pack/plugins/enterprise_search/server/saved_objects/app_search/telemetry.ts index 29b1ce8182f52..ab873b6678885 100644 --- a/x-pack/plugins/enterprise_search/server/saved_objects/app_search/telemetry.ts +++ b/x-pack/plugins/enterprise_search/server/saved_objects/app_search/telemetry.ts @@ -8,6 +8,7 @@ /* istanbul ignore file */ import { SavedObjectsType } from 'src/core/server'; + import { AS_TELEMETRY_NAME } from '../../collectors/app_search/telemetry'; export const appSearchTelemetryType: SavedObjectsType = { diff --git a/x-pack/plugins/enterprise_search/server/saved_objects/enterprise_search/telemetry.ts b/x-pack/plugins/enterprise_search/server/saved_objects/enterprise_search/telemetry.ts index 07659299ef87f..e2edff1b6a213 100644 --- a/x-pack/plugins/enterprise_search/server/saved_objects/enterprise_search/telemetry.ts +++ b/x-pack/plugins/enterprise_search/server/saved_objects/enterprise_search/telemetry.ts @@ -8,6 +8,7 @@ /* istanbul ignore file */ import { SavedObjectsType } from 'src/core/server'; + import { ES_TELEMETRY_NAME } from '../../collectors/enterprise_search/telemetry'; export const enterpriseSearchTelemetryType: SavedObjectsType = { diff --git a/x-pack/plugins/enterprise_search/server/saved_objects/workplace_search/telemetry.ts b/x-pack/plugins/enterprise_search/server/saved_objects/workplace_search/telemetry.ts index a466d69cf8343..af4d5908dec67 100644 --- a/x-pack/plugins/enterprise_search/server/saved_objects/workplace_search/telemetry.ts +++ b/x-pack/plugins/enterprise_search/server/saved_objects/workplace_search/telemetry.ts @@ -8,6 +8,7 @@ /* istanbul ignore file */ import { SavedObjectsType } from 'src/core/server'; + import { WS_TELEMETRY_NAME } from '../../collectors/workplace_search/telemetry'; export const workplaceSearchTelemetryType: SavedObjectsType = { diff --git a/x-pack/plugins/file_upload/kibana.json b/x-pack/plugins/file_upload/kibana.json index 7ca024174ec6a..7676a01d0b0f9 100644 --- a/x-pack/plugins/file_upload/kibana.json +++ b/x-pack/plugins/file_upload/kibana.json @@ -3,6 +3,6 @@ "version": "8.0.0", "kibanaVersion": "kibana", "server": true, - "ui": false, - "requiredPlugins": ["usageCollection"] + "ui": true, + "requiredPlugins": ["data", "usageCollection"] } diff --git a/x-pack/plugins/maps_file_upload/public/components/index_settings.js b/x-pack/plugins/file_upload/public/components/index_settings.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/components/index_settings.js rename to x-pack/plugins/file_upload/public/components/index_settings.js diff --git a/x-pack/plugins/maps_file_upload/public/components/json_import_progress.js b/x-pack/plugins/file_upload/public/components/json_import_progress.js similarity index 96% rename from x-pack/plugins/maps_file_upload/public/components/json_import_progress.js rename to x-pack/plugins/file_upload/public/components/json_import_progress.js index 535142bc3500e..1f9293e77d33c 100644 --- a/x-pack/plugins/maps_file_upload/public/components/json_import_progress.js +++ b/x-pack/plugins/file_upload/public/components/json_import_progress.js @@ -118,9 +118,7 @@ export class JsonImportProgress extends Component { {i18n.translate('xpack.fileUpload.jsonImport.indexMgmtLink', { defaultMessage: 'Index Management', diff --git a/x-pack/plugins/maps_file_upload/public/components/json_index_file_picker.js b/x-pack/plugins/file_upload/public/components/json_index_file_picker.js similarity index 99% rename from x-pack/plugins/maps_file_upload/public/components/json_index_file_picker.js rename to x-pack/plugins/file_upload/public/components/json_index_file_picker.js index 8721b5b60f039..a92412ae9d697 100644 --- a/x-pack/plugins/maps_file_upload/public/components/json_index_file_picker.js +++ b/x-pack/plugins/file_upload/public/components/json_index_file_picker.js @@ -10,8 +10,8 @@ import { EuiFilePicker, EuiFormRow, EuiProgress } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { parseFile } from '../util/file_parser'; -import { MAX_FILE_SIZE } from '../../common/constants/file_import'; +const MAX_FILE_SIZE = 52428800; const ACCEPTABLE_FILETYPES = ['json', 'geojson']; const acceptedFileTypeString = ACCEPTABLE_FILETYPES.map((type) => `.${type}`).join(','); const acceptedFileTypeStringMessage = ACCEPTABLE_FILETYPES.map((type) => `.${type}`).join(', '); diff --git a/x-pack/plugins/maps_file_upload/public/components/json_upload_and_parse.js b/x-pack/plugins/file_upload/public/components/json_upload_and_parse.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/components/json_upload_and_parse.js rename to x-pack/plugins/file_upload/public/components/json_upload_and_parse.js diff --git a/x-pack/plugins/maps_file_upload/public/get_file_upload_component.ts b/x-pack/plugins/file_upload/public/get_file_upload_component.ts similarity index 100% rename from x-pack/plugins/maps_file_upload/public/get_file_upload_component.ts rename to x-pack/plugins/file_upload/public/get_file_upload_component.ts diff --git a/x-pack/plugins/maps_file_upload/public/index.ts b/x-pack/plugins/file_upload/public/index.ts similarity index 94% rename from x-pack/plugins/maps_file_upload/public/index.ts rename to x-pack/plugins/file_upload/public/index.ts index 95553685cbbdd..efabc984e0220 100644 --- a/x-pack/plugins/maps_file_upload/public/index.ts +++ b/x-pack/plugins/file_upload/public/index.ts @@ -11,5 +11,7 @@ export function plugin() { return new FileUploadPlugin(); } +export * from '../common'; + export { StartContract } from './plugin'; export { FileUploadComponentProps } from './get_file_upload_component'; diff --git a/x-pack/plugins/maps_file_upload/public/kibana_services.js b/x-pack/plugins/file_upload/public/kibana_services.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/kibana_services.js rename to x-pack/plugins/file_upload/public/kibana_services.js diff --git a/x-pack/plugins/maps_file_upload/public/plugin.ts b/x-pack/plugins/file_upload/public/plugin.ts similarity index 100% rename from x-pack/plugins/maps_file_upload/public/plugin.ts rename to x-pack/plugins/file_upload/public/plugin.ts diff --git a/x-pack/plugins/maps_file_upload/public/util/file_parser.js b/x-pack/plugins/file_upload/public/util/file_parser.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/util/file_parser.js rename to x-pack/plugins/file_upload/public/util/file_parser.js diff --git a/x-pack/plugins/maps_file_upload/public/util/file_parser.test.js b/x-pack/plugins/file_upload/public/util/file_parser.test.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/util/file_parser.test.js rename to x-pack/plugins/file_upload/public/util/file_parser.test.js diff --git a/x-pack/plugins/maps_file_upload/public/util/geo_json_clean_and_validate.js b/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/util/geo_json_clean_and_validate.js rename to x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.js diff --git a/x-pack/plugins/maps_file_upload/public/util/geo_json_clean_and_validate.test.js b/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.test.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/util/geo_json_clean_and_validate.test.js rename to x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.test.js diff --git a/x-pack/plugins/maps_file_upload/public/util/geo_processing.js b/x-pack/plugins/file_upload/public/util/geo_processing.js similarity index 76% rename from x-pack/plugins/maps_file_upload/public/util/geo_processing.js rename to x-pack/plugins/file_upload/public/util/geo_processing.js index d6f9651496aca..c90c55c2b49ac 100644 --- a/x-pack/plugins/maps_file_upload/public/util/geo_processing.js +++ b/x-pack/plugins/file_upload/public/util/geo_processing.js @@ -6,26 +6,12 @@ */ import _ from 'lodash'; -import { ES_GEO_FIELD_TYPE } from '../../common/constants/file_import'; -const DEFAULT_SETTINGS = { - number_of_shards: 1, +export const ES_GEO_FIELD_TYPE = { + GEO_POINT: 'geo_point', + GEO_SHAPE: 'geo_shape', }; -const DEFAULT_GEO_SHAPE_MAPPINGS = { - coordinates: { - type: ES_GEO_FIELD_TYPE.GEO_SHAPE, - }, -}; - -const DEFAULT_GEO_POINT_MAPPINGS = { - coordinates: { - type: ES_GEO_FIELD_TYPE.GEO_POINT, - }, -}; - -const DEFAULT_INGEST_PIPELINE = {}; - export function getGeoIndexTypesForFeatures(featureTypes) { const hasNoFeatureType = !featureTypes || !featureTypes.length; if (hasNoFeatureType) { @@ -77,11 +63,16 @@ export function geoJsonToEs(parsedGeojson, datatype) { export function getGeoJsonIndexingDetails(parsedGeojson, dataType) { return { data: geoJsonToEs(parsedGeojson, dataType), - ingestPipeline: DEFAULT_INGEST_PIPELINE, - mappings: - dataType === ES_GEO_FIELD_TYPE.GEO_POINT - ? DEFAULT_GEO_POINT_MAPPINGS - : DEFAULT_GEO_SHAPE_MAPPINGS, - settings: DEFAULT_SETTINGS, + ingestPipeline: {}, + mappings: { + properties: { + coordinates: { + type: dataType, + }, + }, + }, + settings: { + number_of_shards: 1, + }, }; } diff --git a/x-pack/plugins/maps_file_upload/public/util/geo_processing.test.js b/x-pack/plugins/file_upload/public/util/geo_processing.test.js similarity index 97% rename from x-pack/plugins/maps_file_upload/public/util/geo_processing.test.js rename to x-pack/plugins/file_upload/public/util/geo_processing.test.js index 75da5bae015af..37b665c0a3e16 100644 --- a/x-pack/plugins/maps_file_upload/public/util/geo_processing.test.js +++ b/x-pack/plugins/file_upload/public/util/geo_processing.test.js @@ -5,8 +5,7 @@ * 2.0. */ -import { geoJsonToEs } from './geo_processing'; -import { ES_GEO_FIELD_TYPE } from '../../common/constants/file_import'; +import { ES_GEO_FIELD_TYPE, geoJsonToEs } from './geo_processing'; describe('geo_processing', () => { describe('getGeoJsonToEs', () => { diff --git a/x-pack/plugins/maps_file_upload/public/util/http_service.js b/x-pack/plugins/file_upload/public/util/http_service.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/util/http_service.js rename to x-pack/plugins/file_upload/public/util/http_service.js diff --git a/x-pack/plugins/maps_file_upload/public/util/indexing_service.js b/x-pack/plugins/file_upload/public/util/indexing_service.js similarity index 96% rename from x-pack/plugins/maps_file_upload/public/util/indexing_service.js rename to x-pack/plugins/file_upload/public/util/indexing_service.js index c29e9685162bc..253681dad6a7d 100644 --- a/x-pack/plugins/maps_file_upload/public/util/indexing_service.js +++ b/x-pack/plugins/file_upload/public/util/indexing_service.js @@ -11,8 +11,6 @@ import { getGeoJsonIndexingDetails } from './geo_processing'; import { sizeLimitedChunking } from './size_limited_chunking'; import { i18n } from '@kbn/i18n'; -const fileType = 'json'; - export async function indexData(parsedFile, transformDetails, indexName, dataType, appName) { if (!parsedFile) { throw i18n.translate('xpack.fileUpload.indexingService.noFileImported', { @@ -117,10 +115,10 @@ function transformDataByFormatForIndexing(transform, parsedFile, dataType) { async function writeToIndex(indexingDetails) { const query = indexingDetails.id ? { id: indexingDetails.id } : null; - const { appName, index, data, settings, mappings, ingestPipeline } = indexingDetails; + const { index, data, settings, mappings, ingestPipeline } = indexingDetails; return await httpService({ - url: `/api/maps/fileupload/import`, + url: `/api/file_upload/import`, method: 'POST', ...(query ? { query } : {}), data: { @@ -129,8 +127,6 @@ async function writeToIndex(indexingDetails) { settings, mappings, ingestPipeline, - fileType, - ...(appName ? { app: appName } : {}), }, }); } diff --git a/x-pack/plugins/maps_file_upload/public/util/indexing_service.test.js b/x-pack/plugins/file_upload/public/util/indexing_service.test.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/util/indexing_service.test.js rename to x-pack/plugins/file_upload/public/util/indexing_service.test.js diff --git a/x-pack/plugins/maps_file_upload/public/util/size_limited_chunking.js b/x-pack/plugins/file_upload/public/util/size_limited_chunking.js similarity index 95% rename from x-pack/plugins/maps_file_upload/public/util/size_limited_chunking.js rename to x-pack/plugins/file_upload/public/util/size_limited_chunking.js index e42e11d0f27f0..09d4e8ca8e3a2 100644 --- a/x-pack/plugins/maps_file_upload/public/util/size_limited_chunking.js +++ b/x-pack/plugins/file_upload/public/util/size_limited_chunking.js @@ -5,7 +5,7 @@ * 2.0. */ -import { MAX_BYTES } from '../../common/constants/file_import'; +const MAX_BYTES = 31457280; // MAX_BYTES is a good guideline for splitting up posts, but this logic // occasionally sizes chunks so closely to the limit, that the remaining content diff --git a/x-pack/plugins/maps_file_upload/public/util/size_limited_chunking.test.js b/x-pack/plugins/file_upload/public/util/size_limited_chunking.test.js similarity index 100% rename from x-pack/plugins/maps_file_upload/public/util/size_limited_chunking.test.js rename to x-pack/plugins/file_upload/public/util/size_limited_chunking.test.js diff --git a/x-pack/plugins/file_upload/server/routes.ts b/x-pack/plugins/file_upload/server/routes.ts index 425e5551f2147..d7b7b8f99edd9 100644 --- a/x-pack/plugins/file_upload/server/routes.ts +++ b/x-pack/plugins/file_upload/server/routes.ts @@ -52,7 +52,7 @@ export function fileUploadRoutes(router: IRouter) { accepts: ['application/json'], maxBytes: MAX_FILE_SIZE_BYTES, }, - tags: ['access:ml:canFindFileStructure'], + tags: ['access:fileUpload:import'], }, }, async (context, request, response) => { diff --git a/x-pack/plugins/file_upload/tsconfig.json b/x-pack/plugins/file_upload/tsconfig.json index f985a4599d5fe..bebb08e6dd5e3 100644 --- a/x-pack/plugins/file_upload/tsconfig.json +++ b/x-pack/plugins/file_upload/tsconfig.json @@ -10,6 +10,7 @@ "include": ["common/**/*", "public/**/*", "server/**/*"], "references": [ { "path": "../../../src/core/tsconfig.json" }, + { "path": "../../../src/plugins/data/tsconfig.json" }, { "path": "../../../src/plugins/usage_collection/tsconfig.json" } ] } diff --git a/x-pack/plugins/fleet/kibana.json b/x-pack/plugins/fleet/kibana.json index aa0761c8a39bd..4a4019e3e9e47 100644 --- a/x-pack/plugins/fleet/kibana.json +++ b/x-pack/plugins/fleet/kibana.json @@ -4,14 +4,13 @@ "server": true, "ui": true, "configPath": ["xpack", "fleet"], - "requiredPlugins": ["licensing", "data"], + "requiredPlugins": ["licensing", "data", "encryptedSavedObjects"], "optionalPlugins": [ "security", "features", "cloud", "usageCollection", - "home", - "encryptedSavedObjects" + "home" ], "extraPublicDirs": ["common"], "requiredBundles": ["kibanaReact", "esUiShared", "home", "infra", "kibanaUtils"] diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/alpha_flyout.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/alpha_flyout.tsx index 82b2d20005225..c91d80124dd35 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/alpha_flyout.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/components/alpha_flyout.tsx @@ -61,7 +61,7 @@ export const AlphaFlyout: React.FunctionComponent = ({ onClose }) => { ), forumLink: ( - + = ({ { const branch = appContextService.getKibanaBranch(); if (branch === 'master') { return SNAPSHOT_REGISTRY_URL_CDN; + } else if (appContextService.getKibanaVersion().includes('-SNAPSHOT')) { + return STAGING_REGISTRY_URL_CDN; } else { return PRODUCTION_REGISTRY_URL_CDN; } diff --git a/x-pack/plugins/index_lifecycle_management/tsconfig.json b/x-pack/plugins/index_lifecycle_management/tsconfig.json new file mode 100644 index 0000000000000..73dcc62132cbf --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/tsconfig.json @@ -0,0 +1,32 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "__jest__/**/*", + "common/**/*", + "public/**/*", + "server/**/*", + "../../typings/**/*", + ], + "references": [ + { "path": "../../../src/core/tsconfig.json" }, + // required plugins + { "path": "../licensing/tsconfig.json" }, + { "path": "../../../src/plugins/management/tsconfig.json" }, + { "path": "../features/tsconfig.json" }, + { "path": "../../../src/plugins/share/tsconfig.json" }, + // optional plugins + { "path": "../cloud/tsconfig.json" }, + { "path": "../../../src/plugins/usage_collection/tsconfig.json" }, + { "path": "../index_management/tsconfig.json" }, + { "path": "../../../src/plugins/home/tsconfig.json" }, + // required bundles + { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, + ] +} diff --git a/x-pack/plugins/infra/common/alerting/metrics/index.ts b/x-pack/plugins/infra/common/alerting/metrics/index.ts index 5151a40c7e8b1..2c66638711cd0 100644 --- a/x-pack/plugins/infra/common/alerting/metrics/index.ts +++ b/x-pack/plugins/infra/common/alerting/metrics/index.ts @@ -10,8 +10,8 @@ export const INFRA_ALERT_PREVIEW_PATH = '/api/infra/alerting/preview'; export const TOO_MANY_BUCKETS_PREVIEW_EXCEPTION = 'TOO_MANY_BUCKETS_PREVIEW_EXCEPTION'; export interface TooManyBucketsPreviewExceptionMetadata { - TOO_MANY_BUCKETS_PREVIEW_EXCEPTION: any; - maxBuckets: number; + TOO_MANY_BUCKETS_PREVIEW_EXCEPTION: boolean; + maxBuckets: any; } export const isTooManyBucketsPreviewException = ( value: any diff --git a/x-pack/plugins/infra/common/alerting/metrics/types.ts b/x-pack/plugins/infra/common/alerting/metrics/types.ts index 47a5202cc7275..7a4edb8f49189 100644 --- a/x-pack/plugins/infra/common/alerting/metrics/types.ts +++ b/x-pack/plugins/infra/common/alerting/metrics/types.ts @@ -4,14 +4,15 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import * as rt from 'io-ts'; +import { ANOMALY_THRESHOLD } from '../../infra_ml'; import { ItemTypeRT } from '../../inventory_models/types'; // TODO: Have threshold and inventory alerts import these types from this file instead of from their // local directories export const METRIC_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.threshold'; export const METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.inventory.threshold'; +export const METRIC_ANOMALY_ALERT_TYPE_ID = 'metrics.alert.anomaly'; export enum Comparator { GT = '>', @@ -34,6 +35,26 @@ export enum Aggregators { P99 = 'p99', } +const metricAnomalyNodeTypeRT = rt.union([rt.literal('hosts'), rt.literal('k8s')]); +const metricAnomalyMetricRT = rt.union([ + rt.literal('memory_usage'), + rt.literal('network_in'), + rt.literal('network_out'), +]); +const metricAnomalyInfluencerFilterRT = rt.type({ + fieldName: rt.string, + fieldValue: rt.string, +}); + +export interface MetricAnomalyParams { + nodeType: rt.TypeOf; + metric: rt.TypeOf; + alertInterval?: string; + sourceId?: string; + threshold: Exclude; + influencerFilter: rt.TypeOf | undefined; +} + // Alert Preview API const baseAlertRequestParamsRT = rt.intersection([ rt.partial({ @@ -51,7 +72,6 @@ const baseAlertRequestParamsRT = rt.intersection([ rt.literal('M'), rt.literal('y'), ]), - criteria: rt.array(rt.any), alertInterval: rt.string, alertThrottle: rt.string, alertOnNoData: rt.boolean, @@ -65,6 +85,7 @@ const metricThresholdAlertPreviewRequestParamsRT = rt.intersection([ }), rt.type({ alertType: rt.literal(METRIC_THRESHOLD_ALERT_TYPE_ID), + criteria: rt.array(rt.any), }), ]); export type MetricThresholdAlertPreviewRequestParams = rt.TypeOf< @@ -76,26 +97,49 @@ const inventoryAlertPreviewRequestParamsRT = rt.intersection([ rt.type({ nodeType: ItemTypeRT, alertType: rt.literal(METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID), + criteria: rt.array(rt.any), }), ]); export type InventoryAlertPreviewRequestParams = rt.TypeOf< typeof inventoryAlertPreviewRequestParamsRT >; +const metricAnomalyAlertPreviewRequestParamsRT = rt.intersection([ + baseAlertRequestParamsRT, + rt.type({ + nodeType: metricAnomalyNodeTypeRT, + metric: metricAnomalyMetricRT, + threshold: rt.number, + alertType: rt.literal(METRIC_ANOMALY_ALERT_TYPE_ID), + }), + rt.partial({ + influencerFilter: metricAnomalyInfluencerFilterRT, + }), +]); +export type MetricAnomalyAlertPreviewRequestParams = rt.TypeOf< + typeof metricAnomalyAlertPreviewRequestParamsRT +>; + export const alertPreviewRequestParamsRT = rt.union([ metricThresholdAlertPreviewRequestParamsRT, inventoryAlertPreviewRequestParamsRT, + metricAnomalyAlertPreviewRequestParamsRT, ]); export type AlertPreviewRequestParams = rt.TypeOf; export const alertPreviewSuccessResponsePayloadRT = rt.type({ numberOfGroups: rt.number, - resultTotals: rt.type({ - fired: rt.number, - noData: rt.number, - error: rt.number, - notifications: rt.number, - }), + resultTotals: rt.intersection([ + rt.type({ + fired: rt.number, + noData: rt.number, + error: rt.number, + notifications: rt.number, + }), + rt.partial({ + warning: rt.number, + }), + ]), }); export type AlertPreviewSuccessResponsePayload = rt.TypeOf< typeof alertPreviewSuccessResponsePayloadRT diff --git a/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_hosts_anomalies.ts b/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_hosts_anomalies.ts index 27574d01be898..0b70b65b7069e 100644 --- a/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_hosts_anomalies.ts +++ b/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_hosts_anomalies.ts @@ -62,6 +62,7 @@ export const getMetricsHostsAnomaliesRequestPayloadRT = rt.type({ rt.type({ // the ID of the source configuration sourceId: rt.string, + anomalyThreshold: rt.number, // the time range to fetch the log entry anomalies from timeRange: timeRangeRT, }), diff --git a/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_k8s_anomalies.ts b/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_k8s_anomalies.ts index 3c2615a447b07..3ee6189dcbf9a 100644 --- a/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_k8s_anomalies.ts +++ b/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_k8s_anomalies.ts @@ -62,6 +62,7 @@ export const getMetricsK8sAnomaliesRequestPayloadRT = rt.type({ rt.type({ // the ID of the source configuration sourceId: rt.string, + anomalyThreshold: rt.number, // the time range to fetch the log entry anomalies from timeRange: timeRangeRT, }), diff --git a/x-pack/plugins/infra/common/http_api/source_api.ts b/x-pack/plugins/infra/common/http_api/source_api.ts index 257383be859aa..f14151531ba35 100644 --- a/x-pack/plugins/infra/common/http_api/source_api.ts +++ b/x-pack/plugins/infra/common/http_api/source_api.ts @@ -90,6 +90,7 @@ export const SavedSourceConfigurationRuntimeType = rt.partial({ metricsExplorerDefaultView: rt.string, fields: SavedSourceConfigurationFieldsRuntimeType, logColumns: rt.array(SavedSourceConfigurationColumnRuntimeType), + anomalyThreshold: rt.number, }); export interface InfraSavedSourceConfiguration @@ -107,6 +108,7 @@ export const pickSavedSourceConfiguration = ( inventoryDefaultView, metricsExplorerDefaultView, logColumns, + anomalyThreshold, } = value; const { container, host, pod, tiebreaker, timestamp } = fields; @@ -119,6 +121,7 @@ export const pickSavedSourceConfiguration = ( metricsExplorerDefaultView, fields: { container, host, pod, tiebreaker, timestamp }, logColumns, + anomalyThreshold, }; }; @@ -140,6 +143,7 @@ export const StaticSourceConfigurationRuntimeType = rt.partial({ metricsExplorerDefaultView: rt.string, fields: StaticSourceConfigurationFieldsRuntimeType, logColumns: rt.array(SavedSourceConfigurationColumnRuntimeType), + anomalyThreshold: rt.number, }); export interface InfraStaticSourceConfiguration diff --git a/x-pack/plugins/infra/common/infra_ml/anomaly_results.ts b/x-pack/plugins/infra/common/infra_ml/anomaly_results.ts index 589e57a1388b5..81e46d85ba220 100644 --- a/x-pack/plugins/infra/common/infra_ml/anomaly_results.ts +++ b/x-pack/plugins/infra/common/infra_ml/anomaly_results.ts @@ -5,36 +5,44 @@ * 2.0. */ -export const ML_SEVERITY_SCORES = { - warning: 3, - minor: 25, - major: 50, - critical: 75, -}; +export enum ANOMALY_SEVERITY { + CRITICAL = 'critical', + MAJOR = 'major', + MINOR = 'minor', + WARNING = 'warning', + LOW = 'low', + UNKNOWN = 'unknown', +} -export type MLSeverityScoreCategories = keyof typeof ML_SEVERITY_SCORES; +export enum ANOMALY_THRESHOLD { + CRITICAL = 75, + MAJOR = 50, + MINOR = 25, + WARNING = 3, + LOW = 0, +} -export const ML_SEVERITY_COLORS = { - critical: 'rgb(228, 72, 72)', - major: 'rgb(229, 113, 0)', - minor: 'rgb(255, 221, 0)', - warning: 'rgb(125, 180, 226)', +export const SEVERITY_COLORS = { + CRITICAL: '#fe5050', + MAJOR: '#fba740', + MINOR: '#fdec25', + WARNING: '#8bc8fb', + LOW: '#d2e9f7', + BLANK: '#ffffff', }; -export const getSeverityCategoryForScore = ( - score: number -): MLSeverityScoreCategories | undefined => { - if (score >= ML_SEVERITY_SCORES.critical) { - return 'critical'; - } else if (score >= ML_SEVERITY_SCORES.major) { - return 'major'; - } else if (score >= ML_SEVERITY_SCORES.minor) { - return 'minor'; - } else if (score >= ML_SEVERITY_SCORES.warning) { - return 'warning'; +export const getSeverityCategoryForScore = (score: number): ANOMALY_SEVERITY | undefined => { + if (score >= ANOMALY_THRESHOLD.CRITICAL) { + return ANOMALY_SEVERITY.CRITICAL; + } else if (score >= ANOMALY_THRESHOLD.MAJOR) { + return ANOMALY_SEVERITY.MAJOR; + } else if (score >= ANOMALY_THRESHOLD.MINOR) { + return ANOMALY_SEVERITY.MINOR; + } else if (score >= ANOMALY_THRESHOLD.WARNING) { + return ANOMALY_SEVERITY.WARNING; } else { // Category is too low to include - return undefined; + return ANOMALY_SEVERITY.LOW; } }; diff --git a/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx b/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx index cfe1579b5f408..57c6f695453ef 100644 --- a/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx +++ b/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx @@ -37,7 +37,7 @@ interface Props { alertInterval: string; alertThrottle: string; alertType: PreviewableAlertTypes; - alertParams: { criteria: any[]; sourceId: string } & Record; + alertParams: { criteria?: any[]; sourceId: string } & Record; validate: (params: any) => ValidationResult; showNoDataResults?: boolean; groupByDisplayName?: string; @@ -109,6 +109,7 @@ export const AlertPreview: React.FC = (props) => { }, [previewLookbackInterval, alertInterval]); const isPreviewDisabled = useMemo(() => { + if (!alertParams.criteria) return false; const validationResult = validate({ criteria: alertParams.criteria } as any); const hasValidationErrors = Object.values(validationResult.errors).some((result) => Object.values(result).some((arr) => Array.isArray(arr) && arr.length) @@ -123,6 +124,11 @@ export const AlertPreview: React.FC = (props) => { return unthrottledNotifications > notifications; }, [previewResult, showNoDataResults]); + const hasWarningThreshold = useMemo( + () => alertParams.criteria?.some((c) => Reflect.has(c, 'warningThreshold')) ?? false, + [alertParams] + ); + return ( = (props) => { - - - - ), - }} - />{' '} - {previewResult.groupByDisplayName ? ( - <> - {' '} - - - {' '} - - ) : null} - e.value === previewResult.previewLookbackInterval - )?.shortText, - }} - /> - + } > {showNoDataResults && previewResult.resultTotals.noData ? ( + ), boldedResultsNumber: ( {i18n.translate( 'xpack.infra.metrics.alertFlyout.alertPreviewNoDataResultNumber', { - defaultMessage: - '{noData, plural, one {was # result} other {were # results}}', + defaultMessage: '{noData, plural, one {# result} other {# results}}', values: { noData: previewResult.resultTotals.noData, }, @@ -361,6 +333,145 @@ export const AlertPreview: React.FC = (props) => { ); }; +const PreviewTextString = ({ + previewResult, + hasWarningThreshold, +}: { + previewResult: AlertPreviewSuccessResponsePayload & Record; + hasWarningThreshold: boolean; +}) => { + const instanceCount = hasWarningThreshold ? ( + + ), + criticalInstances: ( + + + + ), + warningInstances: ( + + + + ), + boldCritical: ( + + + + ), + boldWarning: ( + + + + ), + }} + /> + ) : ( + + ), + firedTimes: ( + + + + ), + }} + /> + ); + + const groupByText = previewResult.groupByDisplayName ? ( + <> + + + + ), + }} + />{' '} + + ) : ( + <> + ); + + const lookbackText = ( + e.value === previewResult.previewLookbackInterval) + ?.shortText, + }} + /> + ); + + return ( + + ); +}; + const previewOptions = [ { value: 'h', diff --git a/x-pack/plugins/infra/public/alerting/common/components/get_alert_preview.ts b/x-pack/plugins/infra/public/alerting/common/components/get_alert_preview.ts index a1cee1361a18f..2bb98e83cbe70 100644 --- a/x-pack/plugins/infra/public/alerting/common/components/get_alert_preview.ts +++ b/x-pack/plugins/infra/public/alerting/common/components/get_alert_preview.ts @@ -10,13 +10,15 @@ import { INFRA_ALERT_PREVIEW_PATH, METRIC_THRESHOLD_ALERT_TYPE_ID, METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, + METRIC_ANOMALY_ALERT_TYPE_ID, AlertPreviewRequestParams, AlertPreviewSuccessResponsePayload, } from '../../../../common/alerting/metrics'; export type PreviewableAlertTypes = | typeof METRIC_THRESHOLD_ALERT_TYPE_ID - | typeof METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID; + | typeof METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID + | typeof METRIC_ANOMALY_ALERT_TYPE_ID; export async function getAlertPreview({ fetch, diff --git a/x-pack/plugins/infra/public/alerting/common/components/metrics_alert_dropdown.tsx b/x-pack/plugins/infra/public/alerting/common/components/metrics_alert_dropdown.tsx new file mode 100644 index 0000000000000..f1236c4fc2c2b --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/common/components/metrics_alert_dropdown.tsx @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import React, { useState, useCallback, useMemo } from 'react'; +import { + EuiPopover, + EuiButtonEmpty, + EuiContextMenu, + EuiContextMenuPanelDescriptor, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { useInfraMLCapabilities } from '../../../containers/ml/infra_ml_capabilities'; +import { PrefilledInventoryAlertFlyout } from '../../inventory/components/alert_flyout'; +import { PrefilledThresholdAlertFlyout } from '../../metric_threshold/components/alert_flyout'; +import { PrefilledAnomalyAlertFlyout } from '../../metric_anomaly/components/alert_flyout'; +import { useLinkProps } from '../../../hooks/use_link_props'; + +type VisibleFlyoutType = 'inventory' | 'threshold' | 'anomaly' | null; + +export const MetricsAlertDropdown = () => { + const [popoverOpen, setPopoverOpen] = useState(false); + const [visibleFlyoutType, setVisibleFlyoutType] = useState(null); + const { hasInfraMLCapabilities } = useInfraMLCapabilities(); + + const closeFlyout = useCallback(() => setVisibleFlyoutType(null), [setVisibleFlyoutType]); + + const manageAlertsLinkProps = useLinkProps({ + app: 'management', + pathname: '/insightsAndAlerting/triggersActions/alerts', + }); + + const panels: EuiContextMenuPanelDescriptor[] = useMemo( + () => [ + { + id: 0, + title: i18n.translate('xpack.infra.alerting.alertDropdownTitle', { + defaultMessage: 'Alerts', + }), + items: [ + { + name: i18n.translate('xpack.infra.alerting.infrastructureDropdownMenu', { + defaultMessage: 'Infrastructure', + }), + panel: 1, + }, + { + name: i18n.translate('xpack.infra.alerting.metricsDropdownMenu', { + defaultMessage: 'Metrics', + }), + panel: 2, + }, + { + name: i18n.translate('xpack.infra.alerting.manageAlerts', { + defaultMessage: 'Manage alerts', + }), + icon: 'tableOfContents', + onClick: manageAlertsLinkProps.onClick, + }, + ], + }, + { + id: 1, + title: i18n.translate('xpack.infra.alerting.infrastructureDropdownTitle', { + defaultMessage: 'Infrastructure alerts', + }), + items: [ + { + name: i18n.translate('xpack.infra.alerting.createInventoryAlertButton', { + defaultMessage: 'Create inventory alert', + }), + onClick: () => setVisibleFlyoutType('inventory'), + }, + ].concat( + hasInfraMLCapabilities + ? { + name: i18n.translate('xpack.infra.alerting.createAnomalyAlertButton', { + defaultMessage: 'Create anomaly alert', + }), + onClick: () => setVisibleFlyoutType('anomaly'), + } + : [] + ), + }, + { + id: 2, + title: i18n.translate('xpack.infra.alerting.metricsDropdownTitle', { + defaultMessage: 'Metrics alerts', + }), + items: [ + { + name: i18n.translate('xpack.infra.alerting.createThresholdAlertButton', { + defaultMessage: 'Create threshold alert', + }), + onClick: () => setVisibleFlyoutType('threshold'), + }, + ], + }, + ], + [manageAlertsLinkProps, setVisibleFlyoutType, hasInfraMLCapabilities] + ); + + const closePopover = useCallback(() => { + setPopoverOpen(false); + }, [setPopoverOpen]); + + const openPopover = useCallback(() => { + setPopoverOpen(true); + }, [setPopoverOpen]); + + return ( + <> + + + + } + isOpen={popoverOpen} + closePopover={closePopover} + > + + + + + ); +}; + +interface AlertFlyoutProps { + visibleFlyoutType: VisibleFlyoutType; + onClose(): void; +} + +const AlertFlyout = ({ visibleFlyoutType, onClose }: AlertFlyoutProps) => { + switch (visibleFlyoutType) { + case 'inventory': + return ; + case 'threshold': + return ; + case 'anomaly': + return ; + default: + return null; + } +}; diff --git a/x-pack/plugins/infra/public/alerting/inventory/components/alert_dropdown.tsx b/x-pack/plugins/infra/public/alerting/inventory/components/alert_dropdown.tsx deleted file mode 100644 index a7b6c9fb7104c..0000000000000 --- a/x-pack/plugins/infra/public/alerting/inventory/components/alert_dropdown.tsx +++ /dev/null @@ -1,59 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useState, useCallback } from 'react'; -import { EuiPopover, EuiButtonEmpty, EuiContextMenuItem, EuiContextMenuPanel } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { useAlertPrefillContext } from '../../../alerting/use_alert_prefill'; -import { AlertFlyout } from './alert_flyout'; -import { ManageAlertsContextMenuItem } from './manage_alerts_context_menu_item'; - -export const InventoryAlertDropdown = () => { - const [popoverOpen, setPopoverOpen] = useState(false); - const [flyoutVisible, setFlyoutVisible] = useState(false); - - const { inventoryPrefill } = useAlertPrefillContext(); - const { nodeType, metric, filterQuery } = inventoryPrefill; - - const closePopover = useCallback(() => { - setPopoverOpen(false); - }, [setPopoverOpen]); - - const openPopover = useCallback(() => { - setPopoverOpen(true); - }, [setPopoverOpen]); - - const menuItems = [ - setFlyoutVisible(true)}> - - , - , - ]; - - return ( - <> - - - - } - isOpen={popoverOpen} - closePopover={closePopover} - > - - - - - ); -}; diff --git a/x-pack/plugins/infra/public/alerting/inventory/components/alert_flyout.tsx b/x-pack/plugins/infra/public/alerting/inventory/components/alert_flyout.tsx index 815e1f2be33f2..33fe3c7af30c7 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/components/alert_flyout.tsx +++ b/x-pack/plugins/infra/public/alerting/inventory/components/alert_flyout.tsx @@ -8,8 +8,7 @@ import React, { useCallback, useContext, useMemo } from 'react'; import { TriggerActionsContext } from '../../../utils/triggers_actions_context'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID } from '../../../../server/lib/alerting/inventory_metric_threshold/types'; +import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID } from '../../../../common/alerting/metrics'; import { InfraWaffleMapOptions } from '../../../lib/lib'; import { InventoryItemType } from '../../../../common/inventory_models/types'; import { useAlertPrefillContext } from '../../../alerting/use_alert_prefill'; @@ -49,3 +48,18 @@ export const AlertFlyout = ({ options, nodeType, filter, visible, setVisible }: return <>{visible && AddAlertFlyout}; }; + +export const PrefilledInventoryAlertFlyout = ({ onClose }: { onClose(): void }) => { + const { inventoryPrefill } = useAlertPrefillContext(); + const { nodeType, metric, filterQuery } = inventoryPrefill; + + return ( + + ); +}; diff --git a/x-pack/plugins/infra/public/alerting/inventory/components/expression.tsx b/x-pack/plugins/infra/public/alerting/inventory/components/expression.tsx index d403c254f2bd0..4a05521e9fc87 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/components/expression.tsx +++ b/x-pack/plugins/infra/public/alerting/inventory/components/expression.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { debounce, pick } from 'lodash'; +import { debounce, pick, omit } from 'lodash'; import { Unit } from '@elastic/datemath'; import React, { useCallback, useMemo, useEffect, useState, ChangeEvent } from 'react'; import { IFieldType } from 'src/plugins/data/public'; @@ -21,6 +21,7 @@ import { EuiCheckbox, EuiToolTip, EuiIcon, + EuiHealth, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; @@ -423,9 +424,24 @@ const StyledExpression = euiStyled.div` padding: 0 4px; `; +const StyledHealth = euiStyled(EuiHealth)` + margin-left: 4px; +`; + export const ExpressionRow: React.FC = (props) => { const { setAlertParams, expression, errors, expressionId, remove, canDelete, fields } = props; - const { metric, comparator = Comparator.GT, threshold = [], customMetric } = expression; + const { + metric, + comparator = Comparator.GT, + threshold = [], + customMetric, + warningThreshold = [], + warningComparator, + } = expression; + + const [displayWarningThreshold, setDisplayWarningThreshold] = useState( + Boolean(warningThreshold?.length) + ); const updateMetric = useCallback( (m?: SnapshotMetricType | string) => { @@ -452,6 +468,13 @@ export const ExpressionRow: React.FC = (props) => { [expressionId, expression, setAlertParams] ); + const updateWarningComparator = useCallback( + (c?: string) => { + setAlertParams(expressionId, { ...expression, warningComparator: c as Comparator }); + }, + [expressionId, expression, setAlertParams] + ); + const updateThreshold = useCallback( (t) => { if (t.join() !== expression.threshold.join()) { @@ -461,6 +484,58 @@ export const ExpressionRow: React.FC = (props) => { [expressionId, expression, setAlertParams] ); + const updateWarningThreshold = useCallback( + (t) => { + if (t.join() !== expression.warningThreshold?.join()) { + setAlertParams(expressionId, { ...expression, warningThreshold: t }); + } + }, + [expressionId, expression, setAlertParams] + ); + + const toggleWarningThreshold = useCallback(() => { + if (!displayWarningThreshold) { + setDisplayWarningThreshold(true); + setAlertParams(expressionId, { + ...expression, + warningComparator: comparator, + warningThreshold: [], + }); + } else { + setDisplayWarningThreshold(false); + setAlertParams(expressionId, omit(expression, 'warningComparator', 'warningThreshold')); + } + }, [ + displayWarningThreshold, + setDisplayWarningThreshold, + setAlertParams, + comparator, + expression, + expressionId, + ]); + + const criticalThresholdExpression = ( + + ); + + const warningThresholdExpression = displayWarningThreshold && ( + + ); + const ofFields = useMemo(() => { let myMetrics = hostMetricTypes; @@ -515,25 +590,62 @@ export const ExpressionRow: React.FC = (props) => { fields={fields} /> - - - - {metric && ( -
- {metricUnit[metric]?.label || ''} -
- )} + {!displayWarningThreshold && criticalThresholdExpression} + {displayWarningThreshold && ( + <> + + {criticalThresholdExpression} + + + + + + {warningThresholdExpression} + + + + + + + )} + {!displayWarningThreshold && ( + <> + {' '} + + + + + + + + )}
{canDelete && ( @@ -553,6 +665,38 @@ export const ExpressionRow: React.FC = (props) => { ); }; +const ThresholdElement: React.FC<{ + updateComparator: (c?: string) => void; + updateThreshold: (t?: number[]) => void; + threshold: InventoryMetricConditions['threshold']; + comparator: InventoryMetricConditions['comparator']; + errors: IErrorObject; + metric?: SnapshotMetricType; +}> = ({ updateComparator, updateThreshold, threshold, metric, comparator, errors }) => { + return ( + <> + + + + {metric && ( +
+ {metricUnit[metric]?.label || ''} +
+ )} + + ); +}; + const getDisplayNameForType = (type: InventoryItemType) => { const inventoryModel = findInventoryModel(type); return inventoryModel.displayName; diff --git a/x-pack/plugins/infra/public/alerting/inventory/components/node_type.tsx b/x-pack/plugins/infra/public/alerting/inventory/components/node_type.tsx index f02f98c49f01a..bd7812acac678 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/components/node_type.tsx +++ b/x-pack/plugins/infra/public/alerting/inventory/components/node_type.tsx @@ -68,7 +68,7 @@ export const NodeTypeExpression = ({ setAggTypePopoverOpen(false)}> { - if (!isNumber(v)) { - const key = i === 0 ? 'threshold0' : 'threshold1'; - errors[id][key].push( - i18n.translate('xpack.infra.metrics.alertFlyout.error.thresholdTypeRequired', { - defaultMessage: 'Thresholds must contain a valid number.', - }) - ); - } - }); - } - - if (c.comparator === 'between' && (!c.threshold || c.threshold.length < 2)) { - errors[id].threshold1.push( + if (c.warningThreshold && !c.warningThreshold.length) { + errors[id].warning.threshold0.push( i18n.translate('xpack.infra.metrics.alertFlyout.error.thresholdRequired', { defaultMessage: 'Threshold is required.', }) ); } + for (const props of [ + { comparator: c.comparator, threshold: c.threshold, type: 'critical' }, + { comparator: c.warningComparator, threshold: c.warningThreshold, type: 'warning' }, + ]) { + // The Threshold component returns an empty array with a length ([empty]) because it's using delete newThreshold[i]. + // We need to use [...c.threshold] to convert it to an array with an undefined value ([undefined]) so we can test each element. + const { comparator, threshold, type } = props as { + comparator?: Comparator; + threshold?: number[]; + type: 'critical' | 'warning'; + }; + if (threshold && threshold.length && ![...threshold].every(isNumber)) { + [...threshold].forEach((v, i) => { + if (!isNumber(v)) { + const key = i === 0 ? 'threshold0' : 'threshold1'; + errors[id][type][key].push( + i18n.translate('xpack.infra.metrics.alertFlyout.error.thresholdTypeRequired', { + defaultMessage: 'Thresholds must contain a valid number.', + }) + ); + } + }); + } + + if (comparator === Comparator.BETWEEN && (!threshold || threshold.length < 2)) { + errors[id][type].threshold1.push( + i18n.translate('xpack.infra.metrics.alertFlyout.error.thresholdRequired', { + defaultMessage: 'Threshold is required.', + }) + ); + } + } if (!c.timeSize) { errors[id].timeWindowSize.push( diff --git a/x-pack/plugins/infra/public/alerting/metric_anomaly/components/alert_flyout.tsx b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/alert_flyout.tsx new file mode 100644 index 0000000000000..9d467e1df7e36 --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/alert_flyout.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useContext, useMemo } from 'react'; + +import { TriggerActionsContext } from '../../../utils/triggers_actions_context'; +import { METRIC_ANOMALY_ALERT_TYPE_ID } from '../../../../common/alerting/metrics'; +import { InfraWaffleMapOptions } from '../../../lib/lib'; +import { InventoryItemType } from '../../../../common/inventory_models/types'; +import { useAlertPrefillContext } from '../../../alerting/use_alert_prefill'; + +interface Props { + visible?: boolean; + metric?: InfraWaffleMapOptions['metric']; + nodeType?: InventoryItemType; + filter?: string; + setVisible(val: boolean): void; +} + +export const AlertFlyout = ({ metric, nodeType, visible, setVisible }: Props) => { + const { triggersActionsUI } = useContext(TriggerActionsContext); + + const onCloseFlyout = useCallback(() => setVisible(false), [setVisible]); + const AddAlertFlyout = useMemo( + () => + triggersActionsUI && + triggersActionsUI.getAddAlertFlyout({ + consumer: 'infrastructure', + onClose: onCloseFlyout, + canChangeTrigger: false, + alertTypeId: METRIC_ANOMALY_ALERT_TYPE_ID, + metadata: { + metric, + nodeType, + }, + }), + // eslint-disable-next-line react-hooks/exhaustive-deps + [triggersActionsUI, visible] + ); + + return <>{visible && AddAlertFlyout}; +}; + +export const PrefilledAnomalyAlertFlyout = ({ onClose }: { onClose(): void }) => { + const { inventoryPrefill } = useAlertPrefillContext(); + const { nodeType, metric } = inventoryPrefill; + + return ; +}; diff --git a/x-pack/plugins/infra/public/alerting/metric_anomaly/components/expression.test.tsx b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/expression.test.tsx new file mode 100644 index 0000000000000..ae2c6ed81badb --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/expression.test.tsx @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mountWithIntl, nextTick } from '@kbn/test/jest'; +// We are using this inside a `jest.mock` call. Jest requires dynamic dependencies to be prefixed with `mock` +import { coreMock as mockCoreMock } from 'src/core/public/mocks'; +import React from 'react'; +import { Expression, AlertContextMeta } from './expression'; +import { act } from 'react-dom/test-utils'; + +jest.mock('../../../containers/source/use_source_via_http', () => ({ + useSourceViaHttp: () => ({ + source: { id: 'default' }, + createDerivedIndexPattern: () => ({ fields: [], title: 'metricbeat-*' }), + }), +})); + +jest.mock('../../../hooks/use_kibana', () => ({ + useKibanaContextForPlugin: () => ({ + services: mockCoreMock.createStart(), + }), +})); + +jest.mock('../../../containers/ml/infra_ml_capabilities', () => ({ + useInfraMLCapabilities: () => ({ + isLoading: false, + hasInfraMLCapabilities: true, + }), +})); + +describe('Expression', () => { + async function setup(currentOptions: AlertContextMeta) { + const alertParams = { + metric: undefined, + nodeType: undefined, + threshold: 50, + }; + const wrapper = mountWithIntl( + Reflect.set(alertParams, key, value)} + setAlertProperty={() => {}} + metadata={currentOptions} + /> + ); + + const update = async () => + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + await update(); + + return { wrapper, update, alertParams }; + } + + it('should prefill the alert using the context metadata', async () => { + const currentOptions = { + nodeType: 'pod', + metric: { type: 'tx' }, + }; + const { alertParams } = await setup(currentOptions as AlertContextMeta); + expect(alertParams.nodeType).toBe('k8s'); + expect(alertParams.metric).toBe('network_out'); + }); +}); diff --git a/x-pack/plugins/infra/public/alerting/metric_anomaly/components/expression.tsx b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/expression.tsx new file mode 100644 index 0000000000000..5938c7119616f --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/expression.tsx @@ -0,0 +1,320 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { pick } from 'lodash'; +import React, { useCallback, useState, useMemo, useEffect } from 'react'; +import { EuiFlexGroup, EuiSpacer, EuiText, EuiLoadingContent } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { useInfraMLCapabilities } from '../../../containers/ml/infra_ml_capabilities'; +import { SubscriptionSplashContent } from '../../../components/subscription_splash_content'; +import { AlertPreview } from '../../common'; +import { + METRIC_ANOMALY_ALERT_TYPE_ID, + MetricAnomalyParams, +} from '../../../../common/alerting/metrics'; +import { euiStyled, EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common'; +import { + WhenExpression, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../../../triggers_actions_ui/public/common'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { IErrorObject } from '../../../../../triggers_actions_ui/public/types'; +import { useSourceViaHttp } from '../../../containers/source/use_source_via_http'; +import { findInventoryModel } from '../../../../common/inventory_models'; +import { InventoryItemType, SnapshotMetricType } from '../../../../common/inventory_models/types'; +import { NodeTypeExpression } from './node_type'; +import { SeverityThresholdExpression } from './severity_threshold'; +import { InfraWaffleMapOptions } from '../../../lib/lib'; +import { ANOMALY_THRESHOLD } from '../../../../common/infra_ml'; + +import { validateMetricAnomaly } from './validation'; +import { InfluencerFilter } from './influencer_filter'; +import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; + +export interface AlertContextMeta { + metric?: InfraWaffleMapOptions['metric']; + nodeType?: InventoryItemType; +} + +interface Props { + errors: IErrorObject[]; + alertParams: MetricAnomalyParams & { + sourceId: string; + }; + alertInterval: string; + alertThrottle: string; + setAlertParams(key: string, value: any): void; + setAlertProperty(key: string, value: any): void; + metadata: AlertContextMeta; +} + +export const defaultExpression = { + metric: 'memory_usage' as MetricAnomalyParams['metric'], + threshold: ANOMALY_THRESHOLD.MAJOR, + nodeType: 'hosts', + influencerFilter: undefined, +}; + +export const Expression: React.FC = (props) => { + const { hasInfraMLCapabilities, isLoading: isLoadingMLCapabilities } = useInfraMLCapabilities(); + const { http, notifications } = useKibanaContextForPlugin().services; + const { setAlertParams, alertParams, alertInterval, alertThrottle, metadata } = props; + const { source, createDerivedIndexPattern } = useSourceViaHttp({ + sourceId: 'default', + type: 'metrics', + fetch: http.fetch, + toastWarning: notifications.toasts.addWarning, + }); + + const derivedIndexPattern = useMemo(() => createDerivedIndexPattern('metrics'), [ + createDerivedIndexPattern, + ]); + + const [influencerFieldName, updateInfluencerFieldName] = useState( + alertParams.influencerFilter?.fieldName ?? 'host.name' + ); + + useEffect(() => { + setAlertParams('hasInfraMLCapabilities', hasInfraMLCapabilities); + }, [setAlertParams, hasInfraMLCapabilities]); + + useEffect(() => { + if (alertParams.influencerFilter) { + setAlertParams('influencerFilter', { + ...alertParams.influencerFilter, + fieldName: influencerFieldName, + }); + } + }, [influencerFieldName, alertParams, setAlertParams]); + const updateInfluencerFieldValue = useCallback( + (value: string) => { + if (value) { + setAlertParams('influencerFilter', { + ...alertParams.influencerFilter, + fieldValue: value, + }); + } else { + setAlertParams('influencerFilter', undefined); + } + }, + [setAlertParams, alertParams] + ); + + useEffect(() => { + setAlertParams('alertInterval', alertInterval); + }, [setAlertParams, alertInterval]); + + const updateNodeType = useCallback( + (nt: any) => { + setAlertParams('nodeType', nt); + }, + [setAlertParams] + ); + + const updateMetric = useCallback( + (metric: string) => { + setAlertParams('metric', metric); + }, + [setAlertParams] + ); + + const updateSeverityThreshold = useCallback( + (threshold: any) => { + setAlertParams('threshold', threshold); + }, + [setAlertParams] + ); + + const prefillNodeType = useCallback(() => { + const md = metadata; + if (md && md.nodeType) { + setAlertParams( + 'nodeType', + getMLNodeTypeFromInventoryNodeType(md.nodeType) ?? defaultExpression.nodeType + ); + } else { + setAlertParams('nodeType', defaultExpression.nodeType); + } + }, [metadata, setAlertParams]); + + const prefillMetric = useCallback(() => { + const md = metadata; + if (md && md.metric) { + setAlertParams( + 'metric', + getMLMetricFromInventoryMetric(md.metric.type) ?? defaultExpression.metric + ); + } else { + setAlertParams('metric', defaultExpression.metric); + } + }, [metadata, setAlertParams]); + + useEffect(() => { + if (!alertParams.nodeType) { + prefillNodeType(); + } + + if (!alertParams.threshold) { + setAlertParams('threshold', defaultExpression.threshold); + } + + if (!alertParams.metric) { + prefillMetric(); + } + + if (!alertParams.sourceId) { + setAlertParams('sourceId', source?.id || 'default'); + } + }, [metadata, derivedIndexPattern, defaultExpression, source]); // eslint-disable-line react-hooks/exhaustive-deps + + if (isLoadingMLCapabilities) return ; + if (!hasInfraMLCapabilities) return ; + + return ( + // https://github.com/elastic/kibana/issues/89506 + + +

+ +

+
+ + + + + + + + + + + + + + + + + + + +
+ ); +}; + +// required for dynamic import +// eslint-disable-next-line import/no-default-export +export default Expression; + +const StyledExpressionRow = euiStyled(EuiFlexGroup)` + display: flex; + flex-wrap: wrap; + margin: 0 -4px; +`; + +const StyledExpression = euiStyled.div` + padding: 0 4px; +`; + +const getDisplayNameForType = (type: InventoryItemType) => { + const inventoryModel = findInventoryModel(type); + return inventoryModel.displayName; +}; + +export const nodeTypes: { [key: string]: any } = { + hosts: { + text: getDisplayNameForType('host'), + value: 'hosts', + }, + k8s: { + text: getDisplayNameForType('pod'), + value: 'k8s', + }, +}; + +const getMLMetricFromInventoryMetric = (metric: SnapshotMetricType) => { + switch (metric) { + case 'memory': + return 'memory_usage'; + case 'tx': + return 'network_out'; + case 'rx': + return 'network_in'; + default: + return null; + } +}; + +const getMLNodeTypeFromInventoryNodeType = (nodeType: InventoryItemType) => { + switch (nodeType) { + case 'host': + return 'hosts'; + case 'pod': + return 'k8s'; + default: + return null; + } +}; diff --git a/x-pack/plugins/infra/public/alerting/metric_anomaly/components/influencer_filter.tsx b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/influencer_filter.tsx new file mode 100644 index 0000000000000..34a917a77dcf5 --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/influencer_filter.tsx @@ -0,0 +1,193 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { debounce } from 'lodash'; +import { i18n } from '@kbn/i18n'; +import React, { useState, useCallback, useEffect, useMemo } from 'react'; +import { first } from 'lodash'; +import { EuiFlexGroup, EuiFormRow, EuiCheckbox, EuiFlexItem, EuiSelect } from '@elastic/eui'; +import { + MetricsExplorerKueryBar, + CurryLoadSuggestionsType, +} from '../../../pages/metrics/metrics_explorer/components/kuery_bar'; +import { MetricAnomalyParams } from '../../../../common/alerting/metrics'; + +interface Props { + fieldName: string; + fieldValue: string; + nodeType: MetricAnomalyParams['nodeType']; + onChangeFieldName: (v: string) => void; + onChangeFieldValue: (v: string) => void; + derivedIndexPattern: Parameters[0]['derivedIndexPattern']; +} + +const FILTER_TYPING_DEBOUNCE_MS = 500; + +export const InfluencerFilter = ({ + fieldName, + fieldValue, + nodeType, + onChangeFieldName, + onChangeFieldValue, + derivedIndexPattern, +}: Props) => { + const fieldNameOptions = useMemo(() => (nodeType === 'k8s' ? k8sFieldNames : hostFieldNames), [ + nodeType, + ]); + + // If initial props contain a fieldValue, assume it was passed in from loaded alertParams, + // and enable the UI element + const [isEnabled, updateIsEnabled] = useState(fieldValue ? true : false); + const [storedFieldValue, updateStoredFieldValue] = useState(fieldValue); + + useEffect( + () => + nodeType === 'k8s' + ? onChangeFieldName(first(k8sFieldNames)!.value) + : onChangeFieldName(first(hostFieldNames)!.value), + [nodeType, onChangeFieldName] + ); + + const onSelectFieldName = useCallback((e) => onChangeFieldName(e.target.value), [ + onChangeFieldName, + ]); + const onUpdateFieldValue = useCallback( + (value) => { + updateStoredFieldValue(value); + onChangeFieldValue(value); + }, + [onChangeFieldValue] + ); + + const toggleEnabled = useCallback(() => { + const nextState = !isEnabled; + updateIsEnabled(nextState); + if (!nextState) { + onChangeFieldValue(''); + } else { + onChangeFieldValue(storedFieldValue); + } + }, [isEnabled, updateIsEnabled, onChangeFieldValue, storedFieldValue]); + + /* eslint-disable-next-line react-hooks/exhaustive-deps */ + const debouncedOnUpdateFieldValue = useCallback( + debounce(onUpdateFieldValue, FILTER_TYPING_DEBOUNCE_MS), + [onUpdateFieldValue] + ); + + const affixFieldNameToQuery: CurryLoadSuggestionsType = (fn) => ( + expression, + cursorPosition, + maxSuggestions + ) => { + // Add the field name to the front of the passed-in query + const prefix = `${fieldName}:`; + // Trim whitespace to prevent AND/OR suggestions + const modifiedExpression = `${prefix}${expression}`.trim(); + // Move the cursor position forward by the length of the field name + const modifiedPosition = cursorPosition + prefix.length; + return fn(modifiedExpression, modifiedPosition, maxSuggestions, (suggestions) => + suggestions + .map((s) => ({ + ...s, + // Remove quotes from suggestions + text: s.text.replace(/\"/g, '').trim(), + // Offset the returned suggestions' cursor positions so that they can be autocompleted accurately + start: s.start - prefix.length, + end: s.end - prefix.length, + })) + // Removing quotes can lead to an already-selected suggestion still coming up in the autocomplete list, + // so filter these out + .filter((s) => !expression.startsWith(s.text)) + ); + }; + + return ( + + } + helpText={ + isEnabled ? ( + <> + {i18n.translate('xpack.infra.metrics.alertFlyout.anomalyFilterHelpText', { + defaultMessage: + 'Limit the scope of your alert trigger to anomalies influenced by certain node(s).', + })} +
+ {i18n.translate('xpack.infra.metrics.alertFlyout.anomalyFilterHelpTextExample', { + defaultMessage: 'For example: "my-node-1" or "my-node-*"', + })} + + ) : null + } + fullWidth + display="rowCompressed" + > + {isEnabled ? ( + + + + + + + + + ) : ( + <> + )} +
+ ); +}; + +const hostFieldNames = [ + { + value: 'host.name', + text: 'host.name', + }, +]; + +const k8sFieldNames = [ + { + value: 'kubernetes.pod.uid', + text: 'kubernetes.pod.uid', + }, + { + value: 'kubernetes.node.name', + text: 'kubernetes.node.name', + }, + { + value: 'kubernetes.namespace', + text: 'kubernetes.namespace', + }, +]; + +const filterByNodeLabel = i18n.translate('xpack.infra.metrics.alertFlyout.filterByNodeLabel', { + defaultMessage: 'Filter by node', +}); diff --git a/x-pack/plugins/infra/public/alerting/metric_anomaly/components/node_type.tsx b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/node_type.tsx new file mode 100644 index 0000000000000..6ddcf8fd5cb65 --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/node_type.tsx @@ -0,0 +1,117 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiExpression, EuiPopover, EuiFlexGroup, EuiFlexItem, EuiSelect } from '@elastic/eui'; +import { EuiPopoverTitle, EuiButtonIcon } from '@elastic/eui'; +import { MetricAnomalyParams } from '../../../../common/alerting/metrics'; + +type Node = MetricAnomalyParams['nodeType']; + +interface WhenExpressionProps { + value: Node; + options: { [key: string]: { text: string; value: Node } }; + onChange: (value: Node) => void; + popupPosition?: + | 'upCenter' + | 'upLeft' + | 'upRight' + | 'downCenter' + | 'downLeft' + | 'downRight' + | 'leftCenter' + | 'leftUp' + | 'leftDown' + | 'rightCenter' + | 'rightUp' + | 'rightDown'; +} + +export const NodeTypeExpression = ({ + value, + options, + onChange, + popupPosition, +}: WhenExpressionProps) => { + const [aggTypePopoverOpen, setAggTypePopoverOpen] = useState(false); + + return ( + { + setAggTypePopoverOpen(true); + }} + /> + } + isOpen={aggTypePopoverOpen} + closePopover={() => { + setAggTypePopoverOpen(false); + }} + ownFocus + anchorPosition={popupPosition ?? 'downLeft'} + > +
+ setAggTypePopoverOpen(false)}> + + + { + onChange(e.target.value as Node); + setAggTypePopoverOpen(false); + }} + options={Object.values(options).map((o) => o)} + /> +
+
+ ); +}; + +interface ClosablePopoverTitleProps { + children: JSX.Element; + onClose: () => void; +} + +export const ClosablePopoverTitle = ({ children, onClose }: ClosablePopoverTitleProps) => { + return ( + + + {children} + + onClose()} + /> + + + + ); +}; diff --git a/x-pack/plugins/infra/public/alerting/metric_anomaly/components/severity_threshold.tsx b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/severity_threshold.tsx new file mode 100644 index 0000000000000..2dc561ff172b9 --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/severity_threshold.tsx @@ -0,0 +1,140 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiExpression, EuiPopover, EuiFlexGroup, EuiFlexItem, EuiSelect } from '@elastic/eui'; +import { EuiPopoverTitle, EuiButtonIcon } from '@elastic/eui'; +import { ANOMALY_THRESHOLD } from '../../../../common/infra_ml'; + +interface WhenExpressionProps { + value: Exclude; + onChange: (value: ANOMALY_THRESHOLD) => void; + popupPosition?: + | 'upCenter' + | 'upLeft' + | 'upRight' + | 'downCenter' + | 'downLeft' + | 'downRight' + | 'leftCenter' + | 'leftUp' + | 'leftDown' + | 'rightCenter' + | 'rightUp' + | 'rightDown'; +} + +const options = { + [ANOMALY_THRESHOLD.CRITICAL]: { + text: i18n.translate('xpack.infra.metrics.alertFlyout.expression.severityScore.criticalLabel', { + defaultMessage: 'Critical', + }), + value: ANOMALY_THRESHOLD.CRITICAL, + }, + [ANOMALY_THRESHOLD.MAJOR]: { + text: i18n.translate('xpack.infra.metrics.alertFlyout.expression.severityScore.majorLabel', { + defaultMessage: 'Major', + }), + value: ANOMALY_THRESHOLD.MAJOR, + }, + [ANOMALY_THRESHOLD.MINOR]: { + text: i18n.translate('xpack.infra.metrics.alertFlyout.expression.severityScore.minorLabel', { + defaultMessage: 'Minor', + }), + value: ANOMALY_THRESHOLD.MINOR, + }, + [ANOMALY_THRESHOLD.WARNING]: { + text: i18n.translate('xpack.infra.metrics.alertFlyout.expression.severityScore.warningLabel', { + defaultMessage: 'Warning', + }), + value: ANOMALY_THRESHOLD.WARNING, + }, +}; + +export const SeverityThresholdExpression = ({ + value, + onChange, + popupPosition, +}: WhenExpressionProps) => { + const [aggTypePopoverOpen, setAggTypePopoverOpen] = useState(false); + + return ( + { + setAggTypePopoverOpen(true); + }} + /> + } + isOpen={aggTypePopoverOpen} + closePopover={() => { + setAggTypePopoverOpen(false); + }} + ownFocus + anchorPosition={popupPosition ?? 'downLeft'} + > +
+ setAggTypePopoverOpen(false)}> + + + { + onChange(Number(e.target.value) as ANOMALY_THRESHOLD); + setAggTypePopoverOpen(false); + }} + options={Object.values(options).map((o) => o)} + /> +
+
+ ); +}; + +interface ClosablePopoverTitleProps { + children: JSX.Element; + onClose: () => void; +} + +export const ClosablePopoverTitle = ({ children, onClose }: ClosablePopoverTitleProps) => { + return ( + + + {children} + + onClose()} + /> + + + + ); +}; diff --git a/x-pack/plugins/infra/public/alerting/metric_anomaly/components/validation.tsx b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/validation.tsx new file mode 100644 index 0000000000000..8e254fb2b67a8 --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/metric_anomaly/components/validation.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ValidationResult } from '../../../../../triggers_actions_ui/public/types'; + +export function validateMetricAnomaly({ + hasInfraMLCapabilities, +}: { + hasInfraMLCapabilities: boolean; +}): ValidationResult { + const validationResult = { errors: {} }; + const errors: { + hasInfraMLCapabilities: string[]; + } = { + hasInfraMLCapabilities: [], + }; + + validationResult.errors = errors; + + if (!hasInfraMLCapabilities) { + errors.hasInfraMLCapabilities.push( + i18n.translate('xpack.infra.metrics.alertFlyout.error.mlCapabilitiesRequired', { + defaultMessage: 'Cannot create an anomaly alert when machine learning is disabled.', + }) + ); + } + + return validationResult; +} diff --git a/x-pack/plugins/infra/public/alerting/metric_anomaly/index.ts b/x-pack/plugins/infra/public/alerting/metric_anomaly/index.ts new file mode 100644 index 0000000000000..31fed514bdacc --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/metric_anomaly/index.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { METRIC_ANOMALY_ALERT_TYPE_ID } from '../../../common/alerting/metrics'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { AlertTypeModel } from '../../../../triggers_actions_ui/public/types'; +import { AlertTypeParams } from '../../../../alerts/common'; +import { validateMetricAnomaly } from './components/validation'; + +interface MetricAnomalyAlertTypeParams extends AlertTypeParams { + hasInfraMLCapabilities: boolean; +} + +export function createMetricAnomalyAlertType(): AlertTypeModel { + return { + id: METRIC_ANOMALY_ALERT_TYPE_ID, + description: i18n.translate('xpack.infra.metrics.anomaly.alertFlyout.alertDescription', { + defaultMessage: 'Alert when the anomaly score exceeds a defined threshold.', + }), + iconClass: 'bell', + documentationUrl(docLinks) { + return `${docLinks.ELASTIC_WEBSITE_URL}guide/en/observability/${docLinks.DOC_LINK_VERSION}/metric-anomaly-alert.html`; + }, + alertParamsExpression: React.lazy(() => import('./components/expression')), + validate: validateMetricAnomaly, + defaultActionMessage: i18n.translate( + 'xpack.infra.metrics.alerting.anomaly.defaultActionMessage', + { + defaultMessage: `\\{\\{alertName\\}\\} is in a state of \\{\\{context.alertState\\}\\} + +\\{\\{context.metric\\}\\} was \\{\\{context.summary\\}\\} than normal at \\{\\{context.timestamp\\}\\} + +Typical value: \\{\\{context.typical\\}\\} +Actual value: \\{\\{context.actual\\}\\} +`, + } + ), + requiresAppContext: false, + }; +} diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_dropdown.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_dropdown.tsx deleted file mode 100644 index 3bbe811225825..0000000000000 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_dropdown.tsx +++ /dev/null @@ -1,57 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useState, useCallback } from 'react'; -import { EuiPopover, EuiButtonEmpty, EuiContextMenuItem, EuiContextMenuPanel } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { useAlertPrefillContext } from '../../use_alert_prefill'; -import { AlertFlyout } from './alert_flyout'; -import { ManageAlertsContextMenuItem } from '../../inventory/components/manage_alerts_context_menu_item'; - -export const MetricsAlertDropdown = () => { - const [popoverOpen, setPopoverOpen] = useState(false); - const [flyoutVisible, setFlyoutVisible] = useState(false); - - const { metricThresholdPrefill } = useAlertPrefillContext(); - const { groupBy, filterQuery, metrics } = metricThresholdPrefill; - - const closePopover = useCallback(() => { - setPopoverOpen(false); - }, [setPopoverOpen]); - - const openPopover = useCallback(() => { - setPopoverOpen(true); - }, [setPopoverOpen]); - - const menuItems = [ - setFlyoutVisible(true)}> - - , - , - ]; - - return ( - <> - - - - } - isOpen={popoverOpen} - closePopover={closePopover} - > - - - - - ); -}; diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_flyout.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_flyout.tsx index 929654ecb4693..e7e4ade5257fc 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_flyout.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_flyout.tsx @@ -7,10 +7,10 @@ import React, { useCallback, useContext, useMemo } from 'react'; import { TriggerActionsContext } from '../../../utils/triggers_actions_context'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { METRIC_THRESHOLD_ALERT_TYPE_ID } from '../../../../server/lib/alerting/metric_threshold/types'; +import { METRIC_THRESHOLD_ALERT_TYPE_ID } from '../../../../common/alerting/metrics'; import { MetricsExplorerSeries } from '../../../../common/http_api/metrics_explorer'; import { MetricsExplorerOptions } from '../../../pages/metrics/metrics_explorer/hooks/use_metrics_explorer_options'; +import { useAlertPrefillContext } from '../../../alerting/use_alert_prefill'; interface Props { visible?: boolean; @@ -42,3 +42,10 @@ export const AlertFlyout = (props: Props) => { return <>{visible && AddAlertFlyout}; }; + +export const PrefilledThresholdAlertFlyout = ({ onClose }: { onClose(): void }) => { + const { metricThresholdPrefill } = useAlertPrefillContext(); + const { groupBy, filterQuery, metrics } = metricThresholdPrefill; + + return ; +}; diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx index 939834fa7c4a8..7e4209e4253d7 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx @@ -64,6 +64,7 @@ describe('ExpressionChart', () => { pod: 'kubernetes.pod.uid', tiebreaker: '_doc', }, + anomalyThreshold: 20, }, }; diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx index 65842089863f3..c98984b5475cd 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx @@ -111,7 +111,9 @@ export const ExpressionChart: React.FC = ({ ); } - const thresholds = expression.threshold.slice().sort(); + const criticalThresholds = expression.threshold.slice().sort(); + const warningThresholds = expression.warningThreshold?.slice().sort() ?? []; + const thresholds = [...criticalThresholds, ...warningThresholds].sort(); // Creating a custom series where the ID is changed to 0 // so that we can get a proper domian @@ -145,108 +147,70 @@ export const ExpressionChart: React.FC = ({ const dataDomain = calculateDomain(series, [metric], false); const domain = { max: Math.max(dataDomain.max, last(thresholds) || dataDomain.max) * 1.1, // add 10% headroom. - min: Math.min(dataDomain.min, first(thresholds) || dataDomain.min), + min: Math.min(dataDomain.min, first(thresholds) || dataDomain.min) * 0.9, // add 10% floor, }; if (domain.min === first(expression.threshold)) { domain.min = domain.min * 0.9; } - const isAbove = [Comparator.GT, Comparator.GT_OR_EQ].includes(expression.comparator); - const isBelow = [Comparator.LT, Comparator.LT_OR_EQ].includes(expression.comparator); const opacity = 0.3; const { timeSize, timeUnit } = expression; const timeLabel = TIME_LABELS[timeUnit as keyof typeof TIME_LABELS]; - return ( - <> - - - - ({ - dataValue: threshold, - }))} - style={{ - line: { - strokeWidth: 2, - stroke: colorTransformer(Color.color1), - opacity: 1, - }, - }} - /> - {thresholds.length === 2 && expression.comparator === Comparator.BETWEEN ? ( - <> - - - ) : null} - {thresholds.length === 2 && expression.comparator === Comparator.OUTSIDE_RANGE ? ( - <> - - & { sortedThresholds: number[]; color: Color; id: string }) => { + if (!comparator || !threshold) return null; + const isAbove = [Comparator.GT, Comparator.GT_OR_EQ].includes(comparator); + const isBelow = [Comparator.LT, Comparator.LT_OR_EQ].includes(comparator); + return ( + <> + ({ + dataValue: t, + }))} + style={{ + line: { + strokeWidth: 2, + stroke: colorTransformer(color), + opacity: 1, + }, + }} + /> + {sortedThresholds.length === 2 && comparator === Comparator.BETWEEN ? ( + <> + - - ) : null} - {isBelow && first(expression.threshold) != null ? ( + }, + ]} + /> + + ) : null} + {sortedThresholds.length === 2 && comparator === Comparator.OUTSIDE_RANGE ? ( + <> = ({ x0: firstTimestamp, x1: lastTimestamp, y0: domain.min, - y1: first(expression.threshold), + y1: first(threshold), }, }, ]} /> - ) : null} - {isAbove && first(expression.threshold) != null ? ( = ({ coordinates: { x0: firstTimestamp, x1: lastTimestamp, - y0: first(expression.threshold), + y0: last(threshold), y1: domain.max, }, }, ]} /> - ) : null} + + ) : null} + {isBelow && first(threshold) != null ? ( + + ) : null} + {isAbove && first(threshold) != null ? ( + + ) : null} + + ); + }; + + return ( + <> + + + + + {expression.warningComparator && expression.warningThreshold && ( + + )} = (props) => { const [isExpanded, setRowState] = useState(true); const toggleRowState = useCallback(() => setRowState(!isExpanded), [isExpanded]); @@ -85,9 +92,14 @@ export const ExpressionRow: React.FC = (props) => { metric, comparator = Comparator.GT, threshold = [], + warningThreshold = [], + warningComparator, } = expression; + const [displayWarningThreshold, setDisplayWarningThreshold] = useState( + Boolean(warningThreshold?.length) + ); - const isMetricPct = useMemo(() => metric && metric.endsWith('.pct'), [metric]); + const isMetricPct = useMemo(() => Boolean(metric && metric.endsWith('.pct')), [metric]); const updateAggType = useCallback( (at: string) => { @@ -114,22 +126,81 @@ export const ExpressionRow: React.FC = (props) => { [expressionId, expression, setAlertParams] ); + const updateWarningComparator = useCallback( + (c?: string) => { + setAlertParams(expressionId, { ...expression, warningComparator: c as Comparator }); + }, + [expressionId, expression, setAlertParams] + ); + + const convertThreshold = useCallback( + (enteredThreshold) => + isMetricPct ? enteredThreshold.map((v: number) => pctToDecimal(v)) : enteredThreshold, + [isMetricPct] + ); + const updateThreshold = useCallback( (enteredThreshold) => { - const t = isMetricPct - ? enteredThreshold.map((v: number) => pctToDecimal(v)) - : enteredThreshold; + const t = convertThreshold(enteredThreshold); if (t.join() !== expression.threshold.join()) { setAlertParams(expressionId, { ...expression, threshold: t }); } }, - [expressionId, expression, isMetricPct, setAlertParams] + [expressionId, expression, convertThreshold, setAlertParams] ); - const displayedThreshold = useMemo(() => { - if (isMetricPct) return threshold.map((v) => decimalToPct(v)); - return threshold; - }, [threshold, isMetricPct]); + const updateWarningThreshold = useCallback( + (enteredThreshold) => { + const t = convertThreshold(enteredThreshold); + if (t.join() !== expression.warningThreshold?.join()) { + setAlertParams(expressionId, { ...expression, warningThreshold: t }); + } + }, + [expressionId, expression, convertThreshold, setAlertParams] + ); + + const toggleWarningThreshold = useCallback(() => { + if (!displayWarningThreshold) { + setDisplayWarningThreshold(true); + setAlertParams(expressionId, { + ...expression, + warningComparator: comparator, + warningThreshold: [], + }); + } else { + setDisplayWarningThreshold(false); + setAlertParams(expressionId, omit(expression, 'warningComparator', 'warningThreshold')); + } + }, [ + displayWarningThreshold, + setDisplayWarningThreshold, + setAlertParams, + comparator, + expression, + expressionId, + ]); + + const criticalThresholdExpression = ( + + ); + + const warningThresholdExpression = displayWarningThreshold && ( + + ); return ( <> @@ -187,26 +258,62 @@ export const ExpressionRow: React.FC = (props) => { /> )} - - - - {isMetricPct && ( -
- % -
- )} + {!displayWarningThreshold && criticalThresholdExpression} + {displayWarningThreshold && ( + <> + + {criticalThresholdExpression} + + + + + + {warningThresholdExpression} + + + + + + + )} + {!displayWarningThreshold && ( + <> + {' '} + + + + + + + + )}
{canDelete && ( @@ -227,6 +334,44 @@ export const ExpressionRow: React.FC = (props) => { ); }; +const ThresholdElement: React.FC<{ + updateComparator: (c?: string) => void; + updateThreshold: (t?: number[]) => void; + threshold: MetricExpression['threshold']; + isMetricPct: boolean; + comparator: MetricExpression['comparator']; + errors: IErrorObject; +}> = ({ updateComparator, updateThreshold, threshold, isMetricPct, comparator, errors }) => { + const displayedThreshold = useMemo(() => { + if (isMetricPct) return threshold.map((v) => decimalToPct(v)); + return threshold; + }, [threshold, isMetricPct]); + + return ( + <> + + + + {isMetricPct && ( +
+ % +
+ )} + + ); +}; + export const aggregationType: { [key: string]: any } = { avg: { text: i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.avg', { diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx index bab396df9da0d..69b2f1d1bcc8f 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx @@ -25,8 +25,14 @@ export function validateMetricThreshold({ aggField: string[]; timeSizeUnit: string[]; timeWindowSize: string[]; - threshold0: string[]; - threshold1: string[]; + critical: { + threshold0: string[]; + threshold1: string[]; + }; + warning: { + threshold0: string[]; + threshold1: string[]; + }; metric: string[]; }; } = {}; @@ -44,8 +50,14 @@ export function validateMetricThreshold({ aggField: [], timeSizeUnit: [], timeWindowSize: [], - threshold0: [], - threshold1: [], + critical: { + threshold0: [], + threshold1: [], + }, + warning: { + threshold0: [], + threshold1: [], + }, metric: [], }; if (!c.aggType) { @@ -57,36 +69,54 @@ export function validateMetricThreshold({ } if (!c.threshold || !c.threshold.length) { - errors[id].threshold0.push( + errors[id].critical.threshold0.push( i18n.translate('xpack.infra.metrics.alertFlyout.error.thresholdRequired', { defaultMessage: 'Threshold is required.', }) ); } - // The Threshold component returns an empty array with a length ([empty]) because it's using delete newThreshold[i]. - // We need to use [...c.threshold] to convert it to an array with an undefined value ([undefined]) so we can test each element. - if (c.threshold && c.threshold.length && ![...c.threshold].every(isNumber)) { - [...c.threshold].forEach((v, i) => { - if (!isNumber(v)) { - const key = i === 0 ? 'threshold0' : 'threshold1'; - errors[id][key].push( - i18n.translate('xpack.infra.metrics.alertFlyout.error.thresholdTypeRequired', { - defaultMessage: 'Thresholds must contain a valid number.', - }) - ); - } - }); - } - - if (c.comparator === Comparator.BETWEEN && (!c.threshold || c.threshold.length < 2)) { - errors[id].threshold1.push( + if (c.warningThreshold && !c.warningThreshold.length) { + errors[id].warning.threshold0.push( i18n.translate('xpack.infra.metrics.alertFlyout.error.thresholdRequired', { defaultMessage: 'Threshold is required.', }) ); } + for (const props of [ + { comparator: c.comparator, threshold: c.threshold, type: 'critical' }, + { comparator: c.warningComparator, threshold: c.warningThreshold, type: 'warning' }, + ]) { + // The Threshold component returns an empty array with a length ([empty]) because it's using delete newThreshold[i]. + // We need to use [...c.threshold] to convert it to an array with an undefined value ([undefined]) so we can test each element. + const { comparator, threshold, type } = props as { + comparator?: Comparator; + threshold?: number[]; + type: 'critical' | 'warning'; + }; + if (threshold && threshold.length && ![...threshold].every(isNumber)) { + [...threshold].forEach((v, i) => { + if (!isNumber(v)) { + const key = i === 0 ? 'threshold0' : 'threshold1'; + errors[id][type][key].push( + i18n.translate('xpack.infra.metrics.alertFlyout.error.thresholdTypeRequired', { + defaultMessage: 'Thresholds must contain a valid number.', + }) + ); + } + }); + } + + if (comparator === Comparator.BETWEEN && (!threshold || threshold.length < 2)) { + errors[id][type].threshold1.push( + i18n.translate('xpack.infra.metrics.alertFlyout.error.thresholdRequired', { + defaultMessage: 'Threshold is required.', + }) + ); + } + } + if (!c.timeSize) { errors[id].timeWindowSize.push( i18n.translate('xpack.infra.metrics.alertFlyout.error.timeRequred', { diff --git a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/index.ts b/x-pack/plugins/infra/public/components/logging/log_analysis_setup/index.ts index 1bcc9e7157a51..db5a996c604fc 100644 --- a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/index.ts +++ b/x-pack/plugins/infra/public/components/logging/log_analysis_setup/index.ts @@ -14,4 +14,3 @@ export * from './missing_results_privileges_prompt'; export * from './missing_setup_privileges_prompt'; export * from './ml_unavailable_prompt'; export * from './setup_status_unknown_prompt'; -export * from './subscription_splash_content'; diff --git a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/subscription_splash_content.tsx b/x-pack/plugins/infra/public/components/logging/log_analysis_setup/subscription_splash_content.tsx deleted file mode 100644 index c91c1d82afe9b..0000000000000 --- a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/subscription_splash_content.tsx +++ /dev/null @@ -1,176 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useEffect } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - EuiPage, - EuiPageBody, - EuiPageContent, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiTitle, - EuiText, - EuiButton, - EuiButtonEmpty, - EuiImage, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { HttpStart } from 'src/core/public'; -import { LoadingPage } from '../../loading_page'; - -import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; -import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common'; -import { useTrialStatus } from '../../../hooks/use_trial_status'; - -export const SubscriptionSplashContent: React.FC = () => { - const { services } = useKibana<{ http: HttpStart }>(); - const { loadState, isTrialAvailable, checkTrialAvailability } = useTrialStatus(); - - useEffect(() => { - checkTrialAvailability(); - }, [checkTrialAvailability]); - - if (loadState === 'pending') { - return ( - - ); - } - - const canStartTrial = isTrialAvailable && loadState === 'resolved'; - - let title; - let description; - let cta; - - if (canStartTrial) { - title = ( - - ); - - description = ( - - ); - - cta = ( - - - - ); - } else { - title = ( - - ); - - description = ( - - ); - - cta = ( - - - - ); - } - - return ( - - - - - - -

{title}

-
- - -

{description}

-
- -
{cta}
-
- - - -
- - -

- -

-
- - - -
-
-
-
- ); -}; - -const SubscriptionPage = euiStyled(EuiPage)` - height: 100% -`; - -const SubscriptionPageContent = euiStyled(EuiPageContent)` - max-width: 768px !important; -`; - -const SubscriptionPageFooter = euiStyled.div` - background: ${(props) => props.theme.eui.euiColorLightestShade}; - margin: 0 -${(props) => props.theme.eui.paddingSizes.l} -${(props) => - props.theme.eui.paddingSizes.l}; - padding: ${(props) => props.theme.eui.paddingSizes.l}; -`; diff --git a/x-pack/plugins/infra/public/components/source_configuration/indices_configuration_form_state.ts b/x-pack/plugins/infra/public/components/source_configuration/indices_configuration_form_state.ts index 794048a8b3a3a..b4dede79d11f2 100644 --- a/x-pack/plugins/infra/public/components/source_configuration/indices_configuration_form_state.ts +++ b/x-pack/plugins/infra/public/components/source_configuration/indices_configuration_form_state.ts @@ -7,7 +7,11 @@ import { ReactNode, useCallback, useMemo, useState } from 'react'; -import { createInputFieldProps, validateInputFieldNotEmpty } from './input_fields'; +import { + createInputFieldProps, + createInputRangeFieldProps, + validateInputFieldNotEmpty, +} from './input_fields'; interface FormState { name: string; @@ -20,6 +24,7 @@ interface FormState { podField: string; tiebreakerField: string; timestampField: string; + anomalyThreshold: number; } type FormStateChanges = Partial; @@ -124,6 +129,17 @@ export const useIndicesConfigurationFormState = ({ }), [formState.timestampField] ); + const anomalyThresholdFieldProps = useMemo( + () => + createInputRangeFieldProps({ + errors: validateInputFieldNotEmpty(formState.anomalyThreshold), + name: 'anomalyThreshold', + onChange: (anomalyThreshold) => + setFormStateChanges((changes) => ({ ...changes, anomalyThreshold })), + value: formState.anomalyThreshold, + }), + [formState.anomalyThreshold] + ); const fieldProps = useMemo( () => ({ @@ -135,6 +151,7 @@ export const useIndicesConfigurationFormState = ({ podField: podFieldFieldProps, tiebreakerField: tiebreakerFieldFieldProps, timestampField: timestampFieldFieldProps, + anomalyThreshold: anomalyThresholdFieldProps, }), [ nameFieldProps, @@ -145,6 +162,7 @@ export const useIndicesConfigurationFormState = ({ podFieldFieldProps, tiebreakerFieldFieldProps, timestampFieldFieldProps, + anomalyThresholdFieldProps, ] ); @@ -183,4 +201,5 @@ const defaultFormState: FormState = { podField: '', tiebreakerField: '', timestampField: '', + anomalyThreshold: 0, }; diff --git a/x-pack/plugins/infra/public/components/source_configuration/input_fields.tsx b/x-pack/plugins/infra/public/components/source_configuration/input_fields.tsx index b8832d27a0a4d..a7a842417ebc2 100644 --- a/x-pack/plugins/infra/public/components/source_configuration/input_fields.tsx +++ b/x-pack/plugins/infra/public/components/source_configuration/input_fields.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { ReactText } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -43,7 +43,47 @@ export const createInputFieldProps = < value, }); -export const validateInputFieldNotEmpty = (value: string) => +export interface InputRangeFieldProps< + Value extends ReactText = ReactText, + FieldElement extends HTMLInputElement = HTMLInputElement, + ButtonElement extends HTMLButtonElement = HTMLButtonElement +> { + error: React.ReactNode[]; + isInvalid: boolean; + name: string; + onChange?: ( + evt: React.ChangeEvent | React.MouseEvent, + isValid: boolean + ) => void; + value: Value; +} + +export const createInputRangeFieldProps = < + Value extends ReactText = ReactText, + FieldElement extends HTMLInputElement = HTMLInputElement, + ButtonElement extends HTMLButtonElement = HTMLButtonElement +>({ + errors, + name, + onChange, + value, +}: { + errors: FieldErrorMessage[]; + name: string; + onChange: (newValue: number, isValid: boolean) => void; + value: Value; +}): InputRangeFieldProps => ({ + error: errors, + isInvalid: errors.length > 0, + name, + onChange: ( + evt: React.ChangeEvent | React.MouseEvent, + isValid: boolean + ) => onChange(+evt.currentTarget.value, isValid), + value, +}); + +export const validateInputFieldNotEmpty = (value: React.ReactText) => value === '' ? [ { + return ( + + +

+ +

+
+ + + + + } + description={ + + } + > + + } + > + + + +
+ ); +}; diff --git a/x-pack/plugins/infra/public/components/source_configuration/source_configuration_form_state.tsx b/x-pack/plugins/infra/public/components/source_configuration/source_configuration_form_state.tsx index 3f947bdb40677..c80235137eea6 100644 --- a/x-pack/plugins/infra/public/components/source_configuration/source_configuration_form_state.tsx +++ b/x-pack/plugins/infra/public/components/source_configuration/source_configuration_form_state.tsx @@ -27,6 +27,7 @@ export const useSourceConfigurationFormState = (configuration?: InfraSourceConfi podField: configuration.fields.pod, tiebreakerField: configuration.fields.tiebreaker, timestampField: configuration.fields.timestamp, + anomalyThreshold: configuration.anomalyThreshold, } : undefined, [configuration] @@ -79,6 +80,7 @@ export const useSourceConfigurationFormState = (configuration?: InfraSourceConfi timestamp: indicesConfigurationFormState.formState.timestampField, }, logColumns: logColumnsConfigurationFormState.formState.logColumns, + anomalyThreshold: indicesConfigurationFormState.formState.anomalyThreshold, }), [indicesConfigurationFormState.formState, logColumnsConfigurationFormState.formState] ); @@ -97,6 +99,7 @@ export const useSourceConfigurationFormState = (configuration?: InfraSourceConfi timestamp: indicesConfigurationFormState.formStateChanges.timestampField, }, logColumns: logColumnsConfigurationFormState.formStateChanges.logColumns, + anomalyThreshold: indicesConfigurationFormState.formStateChanges.anomalyThreshold, }), [ indicesConfigurationFormState.formStateChanges, diff --git a/x-pack/plugins/infra/public/components/source_configuration/source_configuration_settings.tsx b/x-pack/plugins/infra/public/components/source_configuration/source_configuration_settings.tsx index bdf4584bc6287..e63f43470497d 100644 --- a/x-pack/plugins/infra/public/components/source_configuration/source_configuration_settings.tsx +++ b/x-pack/plugins/infra/public/components/source_configuration/source_configuration_settings.tsx @@ -26,6 +26,8 @@ import { NameConfigurationPanel } from './name_configuration_panel'; import { useSourceConfigurationFormState } from './source_configuration_form_state'; import { SourceLoadingPage } from '../source_loading_page'; import { Prompt } from '../../utils/navigation_warning_prompt'; +import { MLConfigurationPanel } from './ml_configuration_panel'; +import { useInfraMLCapabilitiesContext } from '../../containers/ml/infra_ml_capabilities'; interface SourceConfigurationSettingsProps { shouldAllowEdit: boolean; @@ -52,7 +54,6 @@ export const SourceConfigurationSettings = ({ formState, formStateChanges, } = useSourceConfigurationFormState(source && source.configuration); - const persistUpdates = useCallback(async () => { if (sourceExists) { await updateSourceConfiguration(formStateChanges); @@ -74,6 +75,8 @@ export const SourceConfigurationSettings = ({ source, ]); + const { hasInfraMLCapabilities } = useInfraMLCapabilitiesContext(); + if ((isLoading || isUninitialized) && !source) { return ; } @@ -125,6 +128,18 @@ export const SourceConfigurationSettings = ({ /> + {hasInfraMLCapabilities && ( + <> + + + + + + )} {errors.length > 0 ? ( <> diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/subscription_splash_content.tsx b/x-pack/plugins/infra/public/components/subscription_splash_content.tsx similarity index 58% rename from x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/subscription_splash_content.tsx rename to x-pack/plugins/infra/public/components/subscription_splash_content.tsx index e05759ab57dd5..a6477dfc7d172 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/subscription_splash_content.tsx +++ b/x-pack/plugins/infra/public/components/subscription_splash_content.tsx @@ -22,11 +22,11 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { LoadingPage } from '../../../../../../components/loading_page'; -import { useTrialStatus } from '../../../../../../hooks/use_trial_status'; -import { useKibana } from '../../../../../../../../../../src/plugins/kibana_react/public'; -import { euiStyled } from '../../../../../../../../../../src/plugins/kibana_react/common'; -import { HttpStart } from '../../../../../../../../../../src/core/public'; +import { useKibana } from '../../../../../src/plugins/kibana_react/public'; +import { euiStyled, EuiThemeProvider } from '../../../../../src/plugins/kibana_react/common'; +import { HttpStart } from '../../../../../src/core/public'; +import { useTrialStatus } from '../hooks/use_trial_status'; +import { LoadingPage } from '../components/loading_page'; export const SubscriptionSplashContent: React.FC = () => { const { services } = useKibana<{ http: HttpStart }>(); @@ -102,58 +102,60 @@ export const SubscriptionSplashContent: React.FC = () => { } return ( - - - - - - -

{title}

+ + + + + + + +

{title}

+
+ + +

{description}

+
+ +
{cta}
+
+ + + +
+ + +

+ +

- - -

{description}

-
- -
{cta}
-
- - - -
- - -

+ -

-
- - - -
-
-
-
+ + + + + + ); }; diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_capabilities.tsx b/x-pack/plugins/infra/public/containers/ml/infra_ml_capabilities.tsx index 72dc4da01d867..661ce8f8a253c 100644 --- a/x-pack/plugins/infra/public/containers/ml/infra_ml_capabilities.tsx +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_capabilities.tsx @@ -52,11 +52,11 @@ export const useInfraMLCapabilities = () => { const hasInfraMLSetupCapabilities = mlCapabilities.capabilities.canCreateJob; const hasInfraMLReadCapabilities = mlCapabilities.capabilities.canGetJobs; - const hasInfraMLCapabilites = + const hasInfraMLCapabilities = mlCapabilities.isPlatinumOrTrialLicense && mlCapabilities.mlFeatureEnabledInSpace; return { - hasInfraMLCapabilites, + hasInfraMLCapabilities, hasInfraMLReadCapabilities, hasInfraMLSetupCapabilities, isLoading, diff --git a/x-pack/plugins/infra/public/containers/with_kuery_autocompletion.tsx b/x-pack/plugins/infra/public/containers/with_kuery_autocompletion.tsx index 379ac9774c242..1a759950f640d 100644 --- a/x-pack/plugins/infra/public/containers/with_kuery_autocompletion.tsx +++ b/x-pack/plugins/infra/public/containers/with_kuery_autocompletion.tsx @@ -56,7 +56,8 @@ class WithKueryAutocompletionComponent extends React.Component< private loadSuggestions = async ( expression: string, cursorPosition: number, - maxSuggestions?: number + maxSuggestions?: number, + transformSuggestions?: (s: QuerySuggestion[]) => QuerySuggestion[] ) => { const { indexPattern } = this.props; const language = 'kuery'; @@ -86,6 +87,10 @@ class WithKueryAutocompletionComponent extends React.Component< boolFilter: [], })) || []; + const transformedSuggestions = transformSuggestions + ? transformSuggestions(suggestions) + : suggestions; + this.setState((state) => state.currentRequest && state.currentRequest.expression !== expression && @@ -94,7 +99,9 @@ class WithKueryAutocompletionComponent extends React.Component< : { ...state, currentRequest: null, - suggestions: maxSuggestions ? suggestions.slice(0, maxSuggestions) : suggestions, + suggestions: maxSuggestions + ? transformedSuggestions.slice(0, maxSuggestions) + : transformedSuggestions, } ); }; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx index f0fdd79bcd93d..628df397998ee 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx @@ -7,13 +7,13 @@ import { i18n } from '@kbn/i18n'; import React, { useCallback, useEffect } from 'react'; +import { SubscriptionSplashContent } from '../../../components/subscription_splash_content'; import { isJobStatusWithResults } from '../../../../common/log_analysis'; import { LoadingPage } from '../../../components/loading_page'; import { LogAnalysisSetupStatusUnknownPrompt, MissingResultsPrivilegesPrompt, MissingSetupPrivilegesPrompt, - SubscriptionSplashContent, } from '../../../components/logging/log_analysis_setup'; import { LogAnalysisSetupFlyout, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx index 4d06d23ef93ef..5fd00527b8b70 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx @@ -7,13 +7,13 @@ import { i18n } from '@kbn/i18n'; import React, { memo, useEffect, useCallback } from 'react'; +import { SubscriptionSplashContent } from '../../../components/subscription_splash_content'; import { isJobStatusWithResults } from '../../../../common/log_analysis'; import { LoadingPage } from '../../../components/loading_page'; import { LogAnalysisSetupStatusUnknownPrompt, MissingResultsPrivilegesPrompt, MissingSetupPrivilegesPrompt, - SubscriptionSplashContent, } from '../../../components/logging/log_analysis_setup'; import { LogAnalysisSetupFlyout, diff --git a/x-pack/plugins/infra/public/pages/metrics/index.tsx b/x-pack/plugins/infra/public/pages/metrics/index.tsx index 52c2a70f2d359..8fd32bda7fbc8 100644 --- a/x-pack/plugins/infra/public/pages/metrics/index.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/index.tsx @@ -35,12 +35,11 @@ import { WaffleOptionsProvider } from './inventory_view/hooks/use_waffle_options import { WaffleTimeProvider } from './inventory_view/hooks/use_waffle_time'; import { WaffleFiltersProvider } from './inventory_view/hooks/use_waffle_filters'; -import { InventoryAlertDropdown } from '../../alerting/inventory/components/alert_dropdown'; -import { MetricsAlertDropdown } from '../../alerting/metric_threshold/components/alert_dropdown'; +import { MetricsAlertDropdown } from '../../alerting/common/components/metrics_alert_dropdown'; import { SavedView } from '../../containers/saved_view/saved_view'; import { AlertPrefillProvider } from '../../alerting/use_alert_prefill'; import { InfraMLCapabilitiesProvider } from '../../containers/ml/infra_ml_capabilities'; -import { AnomalyDetectionFlyout } from './inventory_view/components/ml/anomaly_detection/anomoly_detection_flyout'; +import { AnomalyDetectionFlyout } from './inventory_view/components/ml/anomaly_detection/anomaly_detection_flyout'; import { HeaderMenuPortal } from '../../../../observability/public'; import { HeaderActionMenuContext } from '../../utils/header_action_menu_provider'; @@ -83,8 +82,7 @@ export const InfrastructurePage = ({ match }: RouteComponentProps) => {
- - + { jobSummaries: k8sJobSummaries, } = useMetricK8sModuleContext(); const { - hasInfraMLCapabilites, + hasInfraMLCapabilities, hasInfraMLReadCapabilities, hasInfraMLSetupCapabilities, } = useInfraMLCapabilitiesContext(); @@ -69,7 +69,7 @@ export const FlyoutHome = (props: Props) => { } }, [fetchK8sJobStatus, fetchHostJobStatus, hasInfraMLReadCapabilities]); - if (!hasInfraMLCapabilites) { + if (!hasInfraMLCapabilities) { return ; } else if (!hasInfraMLReadCapabilities) { return ; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/timeline/timeline.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/timeline/timeline.tsx index a6a296f7d5725..0248241d616dc 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/timeline/timeline.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/timeline/timeline.tsx @@ -51,7 +51,7 @@ interface Props { } export const Timeline: React.FC = ({ interval, yAxisFormatter, isVisible }) => { - const { sourceId } = useSourceContext(); + const { sourceId, source } = useSourceContext(); const { metric, nodeType, accountId, region } = useWaffleOptionsContext(); const { currentTime, jumpToTime, stopAutoReload } = useWaffleTimeContext(); const { filterQueryAsJson } = useWaffleFiltersContext(); @@ -70,6 +70,7 @@ export const Timeline: React.FC = ({ interval, yAxisFormatter, isVisible const anomalyParams = { sourceId: 'default', + anomalyThreshold: source?.configuration.anomalyThreshold || 0, startTime, endTime, defaultSortOptions: { diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_hosts_anomalies.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_hosts_anomalies.ts index c3732fb22cb63..25afd05633fa5 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_hosts_anomalies.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_hosts_anomalies.ts @@ -138,6 +138,7 @@ export const useMetricsHostsAnomaliesResults = ({ endTime, startTime, sourceId, + anomalyThreshold, defaultSortOptions, defaultPaginationOptions, onGetMetricsHostsAnomaliesDatasetsError, @@ -146,6 +147,7 @@ export const useMetricsHostsAnomaliesResults = ({ endTime: number; startTime: number; sourceId: string; + anomalyThreshold: number; defaultSortOptions: Sort; defaultPaginationOptions: Pick; onGetMetricsHostsAnomaliesDatasetsError?: (error: Error) => void; @@ -182,6 +184,7 @@ export const useMetricsHostsAnomaliesResults = ({ return await callGetMetricHostsAnomaliesAPI( { sourceId, + anomalyThreshold, startTime: queryStartTime, endTime: queryEndTime, metric, @@ -215,6 +218,7 @@ export const useMetricsHostsAnomaliesResults = ({ }, [ sourceId, + anomalyThreshold, dispatch, reducerState.timeRange, reducerState.sortOptions, @@ -296,6 +300,7 @@ export const useMetricsHostsAnomaliesResults = ({ interface RequestArgs { sourceId: string; + anomalyThreshold: number; startTime: number; endTime: number; metric: Metric; @@ -307,13 +312,14 @@ export const callGetMetricHostsAnomaliesAPI = async ( requestArgs: RequestArgs, fetch: HttpHandler ) => { - const { sourceId, startTime, endTime, metric, sort, pagination } = requestArgs; + const { sourceId, anomalyThreshold, startTime, endTime, metric, sort, pagination } = requestArgs; const response = await fetch(INFA_ML_GET_METRICS_HOSTS_ANOMALIES_PATH, { method: 'POST', body: JSON.stringify( getMetricsHostsAnomaliesRequestPayloadRT.encode({ data: { sourceId, + anomalyThreshold, timeRange: { startTime, endTime, diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_k8s_anomalies.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_k8s_anomalies.ts index 2a8beeaa814fc..c135a2c5e6661 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_k8s_anomalies.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_k8s_anomalies.ts @@ -138,6 +138,7 @@ export const useMetricsK8sAnomaliesResults = ({ endTime, startTime, sourceId, + anomalyThreshold, defaultSortOptions, defaultPaginationOptions, onGetMetricsHostsAnomaliesDatasetsError, @@ -146,6 +147,7 @@ export const useMetricsK8sAnomaliesResults = ({ endTime: number; startTime: number; sourceId: string; + anomalyThreshold: number; defaultSortOptions: Sort; defaultPaginationOptions: Pick; onGetMetricsHostsAnomaliesDatasetsError?: (error: Error) => void; @@ -183,6 +185,7 @@ export const useMetricsK8sAnomaliesResults = ({ return await callGetMetricsK8sAnomaliesAPI( { sourceId, + anomalyThreshold, startTime: queryStartTime, endTime: queryEndTime, metric, @@ -217,6 +220,7 @@ export const useMetricsK8sAnomaliesResults = ({ }, [ sourceId, + anomalyThreshold, dispatch, reducerState.timeRange, reducerState.sortOptions, @@ -298,6 +302,7 @@ export const useMetricsK8sAnomaliesResults = ({ interface RequestArgs { sourceId: string; + anomalyThreshold: number; startTime: number; endTime: number; metric: Metric; @@ -310,13 +315,23 @@ export const callGetMetricsK8sAnomaliesAPI = async ( requestArgs: RequestArgs, fetch: HttpHandler ) => { - const { sourceId, startTime, endTime, metric, sort, pagination, datasets } = requestArgs; + const { + sourceId, + anomalyThreshold, + startTime, + endTime, + metric, + sort, + pagination, + datasets, + } = requestArgs; const response = await fetch(INFA_ML_GET_METRICS_K8S_ANOMALIES_PATH, { method: 'POST', body: JSON.stringify( getMetricsK8sAnomaliesRequestPayloadRT.encode({ data: { sourceId, + anomalyThreshold, timeRange: { startTime, endTime, diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/kuery_bar.tsx b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/kuery_bar.tsx index 44391568741f3..e22c6fa661181 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/kuery_bar.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/kuery_bar.tsx @@ -10,7 +10,19 @@ import { i18n } from '@kbn/i18n'; import React, { useEffect, useState } from 'react'; import { WithKueryAutocompletion } from '../../../../containers/with_kuery_autocompletion'; import { AutocompleteField } from '../../../../components/autocomplete_field'; -import { esKuery, IIndexPattern } from '../../../../../../../../src/plugins/data/public'; +import { + esKuery, + IIndexPattern, + QuerySuggestion, +} from '../../../../../../../../src/plugins/data/public'; + +type LoadSuggestionsFn = ( + e: string, + p: number, + m?: number, + transform?: (s: QuerySuggestion[]) => QuerySuggestion[] +) => void; +export type CurryLoadSuggestionsType = (loadSuggestions: LoadSuggestionsFn) => LoadSuggestionsFn; interface Props { derivedIndexPattern: IIndexPattern; @@ -18,6 +30,7 @@ interface Props { onChange?: (query: string) => void; value?: string | null; placeholder?: string; + curryLoadSuggestions?: CurryLoadSuggestionsType; } function validateQuery(query: string) { @@ -35,6 +48,7 @@ export const MetricsExplorerKueryBar = ({ onChange, value, placeholder, + curryLoadSuggestions = defaultCurryLoadSuggestions, }: Props) => { const [draftQuery, setDraftQuery] = useState(value || ''); const [isValid, setValidation] = useState(true); @@ -73,7 +87,7 @@ export const MetricsExplorerKueryBar = ({ aria-label={placeholder} isLoadingSuggestions={isLoadingSuggestions} isValid={isValid} - loadSuggestions={loadSuggestions} + loadSuggestions={curryLoadSuggestions(loadSuggestions)} onChange={handleChange} onSubmit={onSubmit} placeholder={placeholder || defaultPlaceholder} @@ -84,3 +98,6 @@ export const MetricsExplorerKueryBar = ({ ); }; + +const defaultCurryLoadSuggestions: CurryLoadSuggestionsType = (loadSuggestions) => (...args) => + loadSuggestions(...args); diff --git a/x-pack/plugins/infra/public/plugin.ts b/x-pack/plugins/infra/public/plugin.ts index 8e7d165f8a535..d4bb83e8668ba 100644 --- a/x-pack/plugins/infra/public/plugin.ts +++ b/x-pack/plugins/infra/public/plugin.ts @@ -10,6 +10,7 @@ import { AppMountParameters, PluginInitializerContext } from 'kibana/public'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { createMetricThresholdAlertType } from './alerting/metric_threshold'; import { createInventoryMetricAlertType } from './alerting/inventory'; +import { createMetricAnomalyAlertType } from './alerting/metric_anomaly'; import { getAlertType as getLogsAlertType } from './alerting/log_threshold'; import { registerFeatures } from './register_feature'; import { @@ -35,6 +36,7 @@ export class Plugin implements InfraClientPluginClass { pluginsSetup.triggersActionsUi.alertTypeRegistry.register(createInventoryMetricAlertType()); pluginsSetup.triggersActionsUi.alertTypeRegistry.register(getLogsAlertType()); pluginsSetup.triggersActionsUi.alertTypeRegistry.register(createMetricThresholdAlertType()); + pluginsSetup.triggersActionsUi.alertTypeRegistry.register(createMetricAnomalyAlertType()); if (pluginsSetup.observability) { pluginsSetup.observability.dashboard.register({ diff --git a/x-pack/plugins/infra/public/types.ts b/x-pack/plugins/infra/public/types.ts index b18b6e8a6eba6..4d70676d25e40 100644 --- a/x-pack/plugins/infra/public/types.ts +++ b/x-pack/plugins/infra/public/types.ts @@ -23,7 +23,7 @@ import type { ObservabilityPluginStart, } from '../../observability/public'; import type { SpacesPluginStart } from '../../spaces/public'; -import { MlPluginStart } from '../../ml/public'; +import { MlPluginStart, MlPluginSetup } from '../../ml/public'; import type { EmbeddableStart } from '../../../../src/plugins/embeddable/public'; // Our own setup and start contract values @@ -36,6 +36,7 @@ export interface InfraClientSetupDeps { observability: ObservabilityPluginSetup; triggersActionsUi: TriggersAndActionsUIPublicPluginSetup; usageCollection: UsageCollectionSetup; + ml: MlPluginSetup; embeddable: EmbeddableSetup; } diff --git a/x-pack/plugins/infra/public/utils/fixtures/metrics_explorer.ts b/x-pack/plugins/infra/public/utils/fixtures/metrics_explorer.ts index 6d8f9ae476044..27648b6d7b193 100644 --- a/x-pack/plugins/infra/public/utils/fixtures/metrics_explorer.ts +++ b/x-pack/plugins/infra/public/utils/fixtures/metrics_explorer.ts @@ -40,6 +40,7 @@ export const source = { message: ['message'], tiebreaker: '@timestamp', }, + anomalyThreshold: 20, }; export const chartOptions: MetricsExplorerChartOptions = { diff --git a/x-pack/plugins/infra/server/lib/alerting/common/messages.ts b/x-pack/plugins/infra/server/lib/alerting/common/messages.ts index 9f0be1679448f..b692629209849 100644 --- a/x-pack/plugins/infra/server/lib/alerting/common/messages.ts +++ b/x-pack/plugins/infra/server/lib/alerting/common/messages.ts @@ -19,6 +19,9 @@ export const stateToAlertMessage = { [AlertStates.ALERT]: i18n.translate('xpack.infra.metrics.alerting.threshold.alertState', { defaultMessage: 'ALERT', }), + [AlertStates.WARNING]: i18n.translate('xpack.infra.metrics.alerting.threshold.warningState', { + defaultMessage: 'WARNING', + }), [AlertStates.NO_DATA]: i18n.translate('xpack.infra.metrics.alerting.threshold.noDataState', { defaultMessage: 'NO DATA', }), diff --git a/x-pack/plugins/infra/server/lib/alerting/common/types.ts b/x-pack/plugins/infra/server/lib/alerting/common/types.ts index e4db2600e316d..0b809429de0d2 100644 --- a/x-pack/plugins/infra/server/lib/alerting/common/types.ts +++ b/x-pack/plugins/infra/server/lib/alerting/common/types.ts @@ -29,6 +29,15 @@ export enum Aggregators { export enum AlertStates { OK, ALERT, + WARNING, NO_DATA, ERROR, } + +export interface PreviewResult { + fired: number; + warning: number; + noData: number; + error: number; + notifications: number; +} diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts index 16f74d579969a..ea37f7adda7c4 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts @@ -26,6 +26,7 @@ import { getNodes } from '../../../routes/snapshot/lib/get_nodes'; type ConditionResult = InventoryMetricConditions & { shouldFire: boolean[]; + shouldWarn: boolean[]; currentValue: number; isNoData: boolean[]; isError: boolean; @@ -39,8 +40,8 @@ export const evaluateCondition = async ( filterQuery?: string, lookbackSize?: number ): Promise> => { - const { comparator, metric, customMetric } = condition; - let { threshold } = condition; + const { comparator, warningComparator, metric, customMetric } = condition; + let { threshold, warningThreshold } = condition; const timerange = { to: Date.now(), @@ -62,19 +63,22 @@ export const evaluateCondition = async ( ); threshold = threshold.map((n) => convertMetricValue(metric, n)); - - const comparisonFunction = comparatorMap[comparator]; + warningThreshold = warningThreshold?.map((n) => convertMetricValue(metric, n)); + + const valueEvaluator = (value?: DataValue, t?: number[], c?: Comparator) => { + if (value === undefined || value === null || !t || !c) return [false]; + const comparisonFunction = comparatorMap[c]; + return Array.isArray(value) + ? value.map((v) => comparisonFunction(Number(v), t)) + : [comparisonFunction(value as number, t)]; + }; const result = mapValues(currentValues, (value) => { if (isTooManyBucketsPreviewException(value)) throw value; return { ...condition, - shouldFire: - value !== undefined && - value !== null && - (Array.isArray(value) - ? value.map((v) => comparisonFunction(Number(v), threshold)) - : [comparisonFunction(value as number, threshold)]), + shouldFire: valueEvaluator(value, threshold, comparator), + shouldWarn: valueEvaluator(value, warningThreshold, warningComparator), isNoData: Array.isArray(value) ? value.map((v) => v === null) : [value === null], isError: value === undefined, currentValue: getCurrentValue(value), @@ -90,6 +94,7 @@ const getCurrentValue: (value: any) => number = (value) => { return NaN; }; +type DataValue = number | null | Array; const getData = async ( callCluster: AlertServices['callCluster'], nodeType: InventoryItemType, diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts index 2658fa6820274..a15f1010194a5 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts @@ -81,6 +81,7 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = // Grab the result of the most recent bucket last(result[item].shouldFire) ); + const shouldAlertWarn = results.every((result) => last(result[item].shouldWarn)); // AND logic; because we need to evaluate all criteria, if one of them reports no data then the // whole alert is in a No Data/Error state @@ -93,12 +94,20 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = ? AlertStates.NO_DATA : shouldAlertFire ? AlertStates.ALERT + : shouldAlertWarn + ? AlertStates.WARNING : AlertStates.OK; let reason; - if (nextState === AlertStates.ALERT) { + if (nextState === AlertStates.ALERT || nextState === AlertStates.WARNING) { reason = results - .map((result) => buildReasonWithVerboseMetricName(result[item], buildFiredAlertReason)) + .map((result) => + buildReasonWithVerboseMetricName( + result[item], + buildFiredAlertReason, + nextState === AlertStates.WARNING + ) + ) .join('\n'); } else if (nextState === AlertStates.OK && prevState?.alertState === AlertStates.ALERT) { /* @@ -125,7 +134,11 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = } if (reason) { const actionGroupId = - nextState === AlertStates.OK ? RecoveredActionGroup.id : FIRED_ACTIONS_ID; + nextState === AlertStates.OK + ? RecoveredActionGroup.id + : nextState === AlertStates.WARNING + ? WARNING_ACTIONS.id + : FIRED_ACTIONS.id; alertInstance.scheduleActions( /** * TODO: We're lying to the compiler here as explicitly calling `scheduleActions` on @@ -152,7 +165,11 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = } }; -const buildReasonWithVerboseMetricName = (resultItem: any, buildReason: (r: any) => string) => { +const buildReasonWithVerboseMetricName = ( + resultItem: any, + buildReason: (r: any) => string, + useWarningThreshold?: boolean +) => { if (!resultItem) return ''; const resultWithVerboseMetricName = { ...resultItem, @@ -162,6 +179,8 @@ const buildReasonWithVerboseMetricName = (resultItem: any, buildReason: (r: any) ? getCustomMetricLabel(resultItem.customMetric) : resultItem.metric), currentValue: formatMetric(resultItem.metric, resultItem.currentValue), + threshold: useWarningThreshold ? resultItem.warningThreshold! : resultItem.threshold, + comparator: useWarningThreshold ? resultItem.warningComparator! : resultItem.comparator, }; return buildReason(resultWithVerboseMetricName); }; @@ -177,11 +196,18 @@ const mapToConditionsLookup = ( {} ); -export const FIRED_ACTIONS_ID = 'metrics.invenotry_threshold.fired'; +export const FIRED_ACTIONS_ID = 'metrics.inventory_threshold.fired'; export const FIRED_ACTIONS: ActionGroup = { id: FIRED_ACTIONS_ID, name: i18n.translate('xpack.infra.metrics.alerting.inventory.threshold.fired', { - defaultMessage: 'Fired', + defaultMessage: 'Alert', + }), +}; +export const WARNING_ACTIONS_ID = 'metrics.inventory_threshold.warning'; +export const WARNING_ACTIONS = { + id: WARNING_ACTIONS_ID, + name: i18n.translate('xpack.infra.metrics.alerting.threshold.warning', { + defaultMessage: 'Warning', }), }; diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/preview_inventory_metric_threshold_alert.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/preview_inventory_metric_threshold_alert.ts index 528c0f92d20e7..5fff76260e5c6 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/preview_inventory_metric_threshold_alert.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/preview_inventory_metric_threshold_alert.ts @@ -7,6 +7,7 @@ import { Unit } from '@elastic/datemath'; import { first } from 'lodash'; +import { PreviewResult } from '../common/types'; import { InventoryMetricConditions } from './types'; import { TOO_MANY_BUCKETS_PREVIEW_EXCEPTION, @@ -35,7 +36,9 @@ interface PreviewInventoryMetricThresholdAlertParams { alertOnNoData: boolean; } -export const previewInventoryMetricThresholdAlert = async ({ +export const previewInventoryMetricThresholdAlert: ( + params: PreviewInventoryMetricThresholdAlertParams +) => Promise = async ({ callCluster, params, source, @@ -43,7 +46,7 @@ export const previewInventoryMetricThresholdAlert = async ({ alertInterval, alertThrottle, alertOnNoData, -}: PreviewInventoryMetricThresholdAlertParams) => { +}) => { const { criteria, filterQuery, nodeType } = params as InventoryMetricThresholdParams; if (criteria.length === 0) throw new Error('Cannot execute an alert with 0 conditions'); @@ -74,6 +77,7 @@ export const previewInventoryMetricThresholdAlert = async ({ const numberOfResultBuckets = lookbackSize; const numberOfExecutionBuckets = Math.floor(numberOfResultBuckets / alertResultsPerExecution); let numberOfTimesFired = 0; + let numberOfTimesWarned = 0; let numberOfNoDataResults = 0; let numberOfErrors = 0; let numberOfNotifications = 0; @@ -88,6 +92,9 @@ export const previewInventoryMetricThresholdAlert = async ({ const shouldFire = result[item].shouldFire as boolean[]; return shouldFire[mappedBucketIndex]; }); + const allConditionsWarnInMappedBucket = + !allConditionsFiredInMappedBucket && + results.every((result) => result[item].shouldWarn[mappedBucketIndex]); const someConditionsNoDataInMappedBucket = results.some((result) => { const hasNoData = result[item].isNoData as boolean[]; return hasNoData[mappedBucketIndex]; @@ -108,6 +115,9 @@ export const previewInventoryMetricThresholdAlert = async ({ } else if (allConditionsFiredInMappedBucket) { numberOfTimesFired++; notifyWithThrottle(); + } else if (allConditionsWarnInMappedBucket) { + numberOfTimesWarned++; + notifyWithThrottle(); } else if (throttleTracker > 0) { throttleTracker++; } @@ -115,7 +125,13 @@ export const previewInventoryMetricThresholdAlert = async ({ throttleTracker = 0; } } - return [numberOfTimesFired, numberOfNoDataResults, numberOfErrors, numberOfNotifications]; + return { + fired: numberOfTimesFired, + warning: numberOfTimesWarned, + noData: numberOfNoDataResults, + error: numberOfErrors, + notifications: numberOfNotifications, + }; }); return previewResults; diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts index 4ae1a0e4d5d49..6c439225d9d00 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts @@ -7,11 +7,17 @@ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; -import { AlertType, AlertInstanceState, AlertInstanceContext } from '../../../../../alerts/server'; +import { + AlertType, + AlertInstanceState, + AlertInstanceContext, + ActionGroupIdsOf, +} from '../../../../../alerts/server'; import { createInventoryMetricThresholdExecutor, FIRED_ACTIONS, FIRED_ACTIONS_ID, + WARNING_ACTIONS, } from './inventory_metric_threshold_executor'; import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, Comparator } from './types'; import { InfraBackendLibs } from '../../infra_types'; @@ -25,7 +31,6 @@ import { metricActionVariableDescription, thresholdActionVariableDescription, } from '../common/messages'; -import { RecoveredActionGroupId } from '../../../../../alerts/common'; const condition = schema.object({ threshold: schema.arrayOf(schema.number()), @@ -33,6 +38,8 @@ const condition = schema.object({ timeUnit: schema.string(), timeSize: schema.number(), metric: schema.string(), + warningThreshold: schema.maybe(schema.arrayOf(schema.number())), + warningComparator: schema.maybe(oneOfLiterals(Object.values(Comparator))), customMetric: schema.maybe( schema.object({ type: schema.literal('custom'), @@ -44,7 +51,9 @@ const condition = schema.object({ ), }); -export type InventoryMetricThresholdAllowedActionGroups = typeof FIRED_ACTIONS_ID; +export type InventoryMetricThresholdAllowedActionGroups = ActionGroupIdsOf< + typeof FIRED_ACTIONS | typeof WARNING_ACTIONS +>; export const registerMetricInventoryThresholdAlertType = ( libs: InfraBackendLibs @@ -56,8 +65,7 @@ export const registerMetricInventoryThresholdAlertType = ( Record, AlertInstanceState, AlertInstanceContext, - InventoryMetricThresholdAllowedActionGroups, - RecoveredActionGroupId + InventoryMetricThresholdAllowedActionGroups > => ({ id: METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, name: i18n.translate('xpack.infra.metrics.inventory.alertName', { @@ -78,7 +86,7 @@ export const registerMetricInventoryThresholdAlertType = ( ), }, defaultActionGroupId: FIRED_ACTIONS_ID, - actionGroups: [FIRED_ACTIONS], + actionGroups: [FIRED_ACTIONS, WARNING_ACTIONS], producer: 'infrastructure', minimumLicenseRequired: 'basic', executor: createInventoryMetricThresholdExecutor(libs), diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/types.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/types.ts index 28c41de9b10d6..120fa47c079ab 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/types.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/types.ts @@ -22,4 +22,6 @@ export interface InventoryMetricConditions { threshold: number[]; comparator: Comparator; customMetric?: SnapshotCustomMetricInput; + warningThreshold?: number[]; + warningComparator?: Comparator; } diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/evaluate_condition.ts b/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/evaluate_condition.ts new file mode 100644 index 0000000000000..b7ef8ec7d2312 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/evaluate_condition.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { MetricAnomalyParams } from '../../../../common/alerting/metrics'; +import { getMetricsHostsAnomalies, getMetricK8sAnomalies } from '../../infra_ml'; +import { MlSystem, MlAnomalyDetectors } from '../../../types'; + +type ConditionParams = Omit & { + spaceId: string; + startTime: number; + endTime: number; + mlSystem: MlSystem; + mlAnomalyDetectors: MlAnomalyDetectors; +}; + +export const evaluateCondition = async ({ + nodeType, + spaceId, + sourceId, + mlSystem, + mlAnomalyDetectors, + startTime, + endTime, + metric, + threshold, + influencerFilter, +}: ConditionParams) => { + const getAnomalies = nodeType === 'k8s' ? getMetricK8sAnomalies : getMetricsHostsAnomalies; + + const result = await getAnomalies( + { + spaceId, + mlSystem, + mlAnomalyDetectors, + }, + sourceId ?? 'default', + threshold, + startTime, + endTime, + metric, + { field: 'anomalyScore', direction: 'desc' }, + { pageSize: 100 }, + influencerFilter + ); + + return result; +}; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/metric_anomaly_executor.ts b/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/metric_anomaly_executor.ts new file mode 100644 index 0000000000000..ec95aac7268ad --- /dev/null +++ b/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/metric_anomaly_executor.ts @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import { first } from 'lodash'; +import moment from 'moment'; +import { stateToAlertMessage } from '../common/messages'; +import { MetricAnomalyParams } from '../../../../common/alerting/metrics'; +import { MappedAnomalyHit } from '../../infra_ml'; +import { AlertStates } from '../common/types'; +import { + ActionGroup, + AlertInstanceContext, + AlertInstanceState, +} from '../../../../../alerts/common'; +import { AlertExecutorOptions } from '../../../../../alerts/server'; +import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds'; +import { MetricAnomalyAllowedActionGroups } from './register_metric_anomaly_alert_type'; +import { MlPluginSetup } from '../../../../../ml/server'; +import { KibanaRequest } from '../../../../../../../src/core/server'; +import { InfraBackendLibs } from '../../infra_types'; +import { evaluateCondition } from './evaluate_condition'; + +export const createMetricAnomalyExecutor = (libs: InfraBackendLibs, ml?: MlPluginSetup) => async ({ + services, + params, + startedAt, +}: AlertExecutorOptions< + /** + * TODO: Remove this use of `any` by utilizing a proper type + */ + Record, + Record, + AlertInstanceState, + AlertInstanceContext, + MetricAnomalyAllowedActionGroups +>) => { + if (!ml) { + return; + } + const request = {} as KibanaRequest; + const mlSystem = ml.mlSystemProvider(request, services.savedObjectsClient); + const mlAnomalyDetectors = ml.anomalyDetectorsProvider(request, services.savedObjectsClient); + + const { + metric, + alertInterval, + influencerFilter, + sourceId, + nodeType, + threshold, + } = params as MetricAnomalyParams; + + const alertInstance = services.alertInstanceFactory(`${nodeType}-${metric}`); + + const bucketInterval = getIntervalInSeconds('15m') * 1000; + const alertIntervalInMs = getIntervalInSeconds(alertInterval ?? '1m') * 1000; + + const endTime = startedAt.getTime(); + // Anomalies are bucketed at :00, :15, :30, :45 minutes every hour + const previousBucketStartTime = endTime - (endTime % bucketInterval); + + // If the alert interval is less than 15m, make sure that it actually queries an anomaly bucket + const startTime = Math.min(endTime - alertIntervalInMs, previousBucketStartTime); + + const { data } = await evaluateCondition({ + sourceId: sourceId ?? 'default', + spaceId: 'default', + mlSystem, + mlAnomalyDetectors, + startTime, + endTime, + metric, + threshold, + nodeType, + influencerFilter, + }); + + const shouldAlertFire = data.length > 0; + + if (shouldAlertFire) { + const { startTime: anomalyStartTime, anomalyScore, actual, typical, influencers } = first( + data as MappedAnomalyHit[] + )!; + + alertInstance.scheduleActions(FIRED_ACTIONS_ID, { + alertState: stateToAlertMessage[AlertStates.ALERT], + timestamp: moment(anomalyStartTime).toISOString(), + anomalyScore, + actual, + typical, + metric: metricNameMap[metric], + summary: generateSummaryMessage(actual, typical), + influencers: influencers.join(', '), + }); + } +}; + +export const FIRED_ACTIONS_ID = 'metrics.anomaly.fired'; +export const FIRED_ACTIONS: ActionGroup = { + id: FIRED_ACTIONS_ID, + name: i18n.translate('xpack.infra.metrics.alerting.anomaly.fired', { + defaultMessage: 'Fired', + }), +}; + +const generateSummaryMessage = (actual: number, typical: number) => { + const differential = (Math.max(actual, typical) / Math.min(actual, typical)) + .toFixed(1) + .replace('.0', ''); + if (actual > typical) { + return i18n.translate('xpack.infra.metrics.alerting.anomaly.summaryHigher', { + defaultMessage: '{differential}x higher', + values: { + differential, + }, + }); + } else { + return i18n.translate('xpack.infra.metrics.alerting.anomaly.summaryLower', { + defaultMessage: '{differential}x lower', + values: { + differential, + }, + }); + } +}; + +const metricNameMap = { + memory_usage: i18n.translate('xpack.infra.metrics.alerting.anomaly.memoryUsage', { + defaultMessage: 'Memory usage', + }), + network_in: i18n.translate('xpack.infra.metrics.alerting.anomaly.networkIn', { + defaultMessage: 'Network in', + }), + network_out: i18n.translate('xpack.infra.metrics.alerting.anomaly.networkOut', { + defaultMessage: 'Network out', + }), +}; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/preview_metric_anomaly_alert.ts b/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/preview_metric_anomaly_alert.ts new file mode 100644 index 0000000000000..98992701e3bb4 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/preview_metric_anomaly_alert.ts @@ -0,0 +1,120 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Unit } from '@elastic/datemath'; +import { countBy } from 'lodash'; +import { MappedAnomalyHit } from '../../infra_ml'; +import { MlSystem, MlAnomalyDetectors } from '../../../types'; +import { MetricAnomalyParams } from '../../../../common/alerting/metrics'; +import { + TOO_MANY_BUCKETS_PREVIEW_EXCEPTION, + isTooManyBucketsPreviewException, +} from '../../../../common/alerting/metrics'; +import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds'; +import { evaluateCondition } from './evaluate_condition'; + +interface PreviewMetricAnomalyAlertParams { + mlSystem: MlSystem; + mlAnomalyDetectors: MlAnomalyDetectors; + spaceId: string; + params: MetricAnomalyParams; + sourceId: string; + lookback: Unit; + alertInterval: string; + alertThrottle: string; + alertOnNoData: boolean; +} + +export const previewMetricAnomalyAlert = async ({ + mlSystem, + mlAnomalyDetectors, + spaceId, + params, + sourceId, + lookback, + alertInterval, + alertThrottle, +}: PreviewMetricAnomalyAlertParams) => { + const { metric, threshold, influencerFilter, nodeType } = params as MetricAnomalyParams; + + const alertIntervalInSeconds = getIntervalInSeconds(alertInterval); + const throttleIntervalInSeconds = getIntervalInSeconds(alertThrottle); + const executionsPerThrottle = Math.floor(throttleIntervalInSeconds / alertIntervalInSeconds); + + const lookbackInterval = `1${lookback}`; + const lookbackIntervalInSeconds = getIntervalInSeconds(lookbackInterval); + const endTime = Date.now(); + const startTime = endTime - lookbackIntervalInSeconds * 1000; + + const numberOfExecutions = Math.floor(lookbackIntervalInSeconds / alertIntervalInSeconds); + const bucketIntervalInSeconds = getIntervalInSeconds('15m'); + const bucketsPerExecution = Math.max( + 1, + Math.floor(alertIntervalInSeconds / bucketIntervalInSeconds) + ); + + try { + let anomalies: MappedAnomalyHit[] = []; + const { data } = await evaluateCondition({ + nodeType, + spaceId, + sourceId, + mlSystem, + mlAnomalyDetectors, + startTime, + endTime, + metric, + threshold, + influencerFilter, + }); + anomalies = [...anomalies, ...data]; + + const anomaliesByTime = countBy(anomalies, ({ startTime: anomStartTime }) => anomStartTime); + + let numberOfTimesFired = 0; + let numberOfNotifications = 0; + let throttleTracker = 0; + const notifyWithThrottle = () => { + if (throttleTracker === 0) numberOfNotifications++; + throttleTracker++; + }; + // Mock each alert evaluation + for (let i = 0; i < numberOfExecutions; i++) { + const executionTime = startTime + alertIntervalInSeconds * 1000 * i; + // Get an array of bucket times this mock alert evaluation will be looking at + // Anomalies are bucketed at :00, :15, :30, :45 minutes every hour, + // so this is an array of how many of those times occurred between this evaluation + // and the previous one + const bucketsLookedAt = Array.from(Array(bucketsPerExecution), (_, idx) => { + const previousBucketStartTime = + executionTime - + (executionTime % (bucketIntervalInSeconds * 1000)) - + idx * bucketIntervalInSeconds * 1000; + return previousBucketStartTime; + }); + const anomaliesDetectedInBuckets = bucketsLookedAt.some((bucketTime) => + Reflect.has(anomaliesByTime, bucketTime) + ); + + if (anomaliesDetectedInBuckets) { + numberOfTimesFired++; + notifyWithThrottle(); + } else if (throttleTracker > 0) { + throttleTracker++; + } + if (throttleTracker === executionsPerThrottle) { + throttleTracker = 0; + } + } + + return { fired: numberOfTimesFired, notifications: numberOfNotifications }; + } catch (e) { + if (!isTooManyBucketsPreviewException(e)) throw e; + const { maxBuckets } = e; + throw new Error(`${TOO_MANY_BUCKETS_PREVIEW_EXCEPTION}:${maxBuckets}`); + } +}; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/register_metric_anomaly_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/register_metric_anomaly_alert_type.ts new file mode 100644 index 0000000000000..8ac62c125515a --- /dev/null +++ b/x-pack/plugins/infra/server/lib/alerting/metric_anomaly/register_metric_anomaly_alert_type.ts @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import { i18n } from '@kbn/i18n'; +import { MlPluginSetup } from '../../../../../ml/server'; +import { AlertType, AlertInstanceState, AlertInstanceContext } from '../../../../../alerts/server'; +import { + createMetricAnomalyExecutor, + FIRED_ACTIONS, + FIRED_ACTIONS_ID, +} from './metric_anomaly_executor'; +import { METRIC_ANOMALY_ALERT_TYPE_ID } from '../../../../common/alerting/metrics'; +import { InfraBackendLibs } from '../../infra_types'; +import { oneOfLiterals, validateIsStringElasticsearchJSONFilter } from '../common/utils'; +import { alertStateActionVariableDescription } from '../common/messages'; +import { RecoveredActionGroupId } from '../../../../../alerts/common'; + +export type MetricAnomalyAllowedActionGroups = typeof FIRED_ACTIONS_ID; + +export const registerMetricAnomalyAlertType = ( + libs: InfraBackendLibs, + ml?: MlPluginSetup +): AlertType< + /** + * TODO: Remove this use of `any` by utilizing a proper type + */ + Record, + Record, + AlertInstanceState, + AlertInstanceContext, + MetricAnomalyAllowedActionGroups, + RecoveredActionGroupId +> => ({ + id: METRIC_ANOMALY_ALERT_TYPE_ID, + name: i18n.translate('xpack.infra.metrics.anomaly.alertName', { + defaultMessage: 'Infrastructure anomaly', + }), + validate: { + params: schema.object( + { + nodeType: oneOfLiterals(['hosts', 'k8s']), + alertInterval: schema.string(), + metric: oneOfLiterals(['memory_usage', 'network_in', 'network_out']), + threshold: schema.number(), + filterQuery: schema.maybe( + schema.string({ validate: validateIsStringElasticsearchJSONFilter }) + ), + sourceId: schema.string(), + }, + { unknowns: 'allow' } + ), + }, + defaultActionGroupId: FIRED_ACTIONS_ID, + actionGroups: [FIRED_ACTIONS], + producer: 'infrastructure', + minimumLicenseRequired: 'basic', + executor: createMetricAnomalyExecutor(libs, ml), + actionVariables: { + context: [ + { name: 'alertState', description: alertStateActionVariableDescription }, + { + name: 'metric', + description: i18n.translate('xpack.infra.metrics.alerting.anomalyMetricDescription', { + defaultMessage: 'The metric name in the specified condition.', + }), + }, + { + name: 'timestamp', + description: i18n.translate('xpack.infra.metrics.alerting.anomalyTimestampDescription', { + defaultMessage: 'A timestamp of when the anomaly was detected.', + }), + }, + { + name: 'anomalyScore', + description: i18n.translate('xpack.infra.metrics.alerting.anomalyScoreDescription', { + defaultMessage: 'The exact severity score of the detected anomaly.', + }), + }, + { + name: 'actual', + description: i18n.translate('xpack.infra.metrics.alerting.anomalyActualDescription', { + defaultMessage: 'The actual value of the monitored metric at the time of the anomaly.', + }), + }, + { + name: 'typical', + description: i18n.translate('xpack.infra.metrics.alerting.anomalyTypicalDescription', { + defaultMessage: 'The typical value of the monitored metric at the time of the anomaly.', + }), + }, + { + name: 'summary', + description: i18n.translate('xpack.infra.metrics.alerting.anomalySummaryDescription', { + defaultMessage: 'A description of the anomaly, e.g. "2x higher."', + }), + }, + { + name: 'influencers', + description: i18n.translate('xpack.infra.metrics.alerting.anomalyInfluencersDescription', { + defaultMessage: 'A list of node names that influenced the anomaly.', + }), + }, + ], + }, +}); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts index f9661e2cd56bb..029445a441eea 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts @@ -60,8 +60,17 @@ export const evaluateAlert = { + if (!t || !c) return [false]; + const comparisonFunction = comparatorMap[c]; + return Array.isArray(points) + ? points.map( + (point) => t && typeof point.value === 'number' && comparisonFunction(point.value, t) + ) + : [false]; + }; + return mapValues(currentValues, (points: any[] | typeof NaN | null) => { if (isTooManyBucketsPreviewException(points)) throw points; return { @@ -69,12 +78,8 @@ export const evaluateAlert = - typeof point.value === 'number' && comparisonFunction(point.value, threshold) - ) - : [false], + shouldFire: pointsEvaluator(points, threshold, comparator), + shouldWarn: pointsEvaluator(points, warningThreshold, warningComparator), isNoData: Array.isArray(points) ? points.map((point) => point?.value === null || point === null) : [points === null], diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts index 17b9ab1cab907..b822d71b3f812 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts @@ -18,7 +18,7 @@ import { stateToAlertMessage, } from '../common/messages'; import { createFormatter } from '../../../../common/formatters'; -import { AlertStates } from './types'; +import { AlertStates, Comparator } from './types'; import { evaluateAlert, EvaluatedAlertParams } from './lib/evaluate_alert'; import { MetricThresholdAlertExecutorOptions, @@ -60,6 +60,7 @@ export const createMetricThresholdExecutor = ( // Grab the result of the most recent bucket last(result[group].shouldFire) ); + const shouldAlertWarn = alertResults.every((result) => last(result[group].shouldWarn)); // AND logic; because we need to evaluate all criteria, if one of them reports no data then the // whole alert is in a No Data/Error state const isNoData = alertResults.some((result) => last(result[group].isNoData)); @@ -71,12 +72,18 @@ export const createMetricThresholdExecutor = ( ? AlertStates.NO_DATA : shouldAlertFire ? AlertStates.ALERT + : shouldAlertWarn + ? AlertStates.WARNING : AlertStates.OK; let reason; - if (nextState === AlertStates.ALERT) { + if (nextState === AlertStates.ALERT || nextState === AlertStates.WARNING) { reason = alertResults - .map((result) => buildFiredAlertReason(formatAlertResult(result[group]))) + .map((result) => + buildFiredAlertReason( + formatAlertResult(result[group], nextState === AlertStates.WARNING) + ) + ) .join('\n'); } else if (nextState === AlertStates.OK && prevState?.alertState === AlertStates.ALERT) { /* @@ -105,7 +112,11 @@ export const createMetricThresholdExecutor = ( const firstResult = first(alertResults); const timestamp = (firstResult && firstResult[group].timestamp) ?? moment().toISOString(); const actionGroupId = - nextState === AlertStates.OK ? RecoveredActionGroup.id : FIRED_ACTIONS.id; + nextState === AlertStates.OK + ? RecoveredActionGroup.id + : nextState === AlertStates.WARNING + ? WARNING_ACTIONS.id + : FIRED_ACTIONS.id; alertInstance.scheduleActions(actionGroupId, { group, alertState: stateToAlertMessage[nextState], @@ -132,7 +143,14 @@ export const createMetricThresholdExecutor = ( export const FIRED_ACTIONS = { id: 'metrics.threshold.fired', name: i18n.translate('xpack.infra.metrics.alerting.threshold.fired', { - defaultMessage: 'Fired', + defaultMessage: 'Alert', + }), +}; + +export const WARNING_ACTIONS = { + id: 'metrics.threshold.warning', + name: i18n.translate('xpack.infra.metrics.alerting.threshold.warning', { + defaultMessage: 'Warning', }), }; @@ -152,9 +170,20 @@ const formatAlertResult = ( metric: string; currentValue: number; threshold: number[]; - } & AlertResult + comparator: Comparator; + warningThreshold?: number[]; + warningComparator?: Comparator; + } & AlertResult, + useWarningThreshold?: boolean ) => { - const { metric, currentValue, threshold } = alertResult; + const { + metric, + currentValue, + threshold, + comparator, + warningThreshold, + warningComparator, + } = alertResult; const noDataValue = i18n.translate( 'xpack.infra.metrics.alerting.threshold.noDataFormattedValue', { @@ -167,12 +196,17 @@ const formatAlertResult = ( currentValue: currentValue ?? noDataValue, }; const formatter = createFormatter('percent'); + const thresholdToFormat = useWarningThreshold ? warningThreshold! : threshold; + const comparatorToFormat = useWarningThreshold ? warningComparator! : comparator; return { ...alertResult, currentValue: currentValue !== null && typeof currentValue !== 'undefined' ? formatter(currentValue) : noDataValue, - threshold: Array.isArray(threshold) ? threshold.map((v: number) => formatter(v)) : threshold, + threshold: Array.isArray(thresholdToFormat) + ? thresholdToFormat.map((v: number) => formatter(v)) + : thresholdToFormat, + comparator: comparatorToFormat, }; }; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.test.ts index 8576fd7b59299..1adca25504b1f 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.test.ts @@ -20,10 +20,10 @@ describe('Previewing the metric threshold alert type', () => { alertThrottle: '1m', alertOnNoData: true, }); - const [firedResults, noDataResults, errorResults, notifications] = ungroupedResult; - expect(firedResults).toBe(30); - expect(noDataResults).toBe(0); - expect(errorResults).toBe(0); + const { fired, noData, error, notifications } = ungroupedResult; + expect(fired).toBe(30); + expect(noData).toBe(0); + expect(error).toBe(0); expect(notifications).toBe(30); }); @@ -35,10 +35,10 @@ describe('Previewing the metric threshold alert type', () => { alertThrottle: '3m', alertOnNoData: true, }); - const [firedResults, noDataResults, errorResults, notifications] = ungroupedResult; - expect(firedResults).toBe(10); - expect(noDataResults).toBe(0); - expect(errorResults).toBe(0); + const { fired, noData, error, notifications } = ungroupedResult; + expect(fired).toBe(10); + expect(noData).toBe(0); + expect(error).toBe(0); expect(notifications).toBe(10); }); test('returns the expected results using a bucket interval longer than the alert interval', async () => { @@ -49,10 +49,10 @@ describe('Previewing the metric threshold alert type', () => { alertThrottle: '30s', alertOnNoData: true, }); - const [firedResults, noDataResults, errorResults, notifications] = ungroupedResult; - expect(firedResults).toBe(60); - expect(noDataResults).toBe(0); - expect(errorResults).toBe(0); + const { fired, noData, error, notifications } = ungroupedResult; + expect(fired).toBe(60); + expect(noData).toBe(0); + expect(error).toBe(0); expect(notifications).toBe(60); }); test('returns the expected results using a throttle interval longer than the alert interval', async () => { @@ -63,10 +63,10 @@ describe('Previewing the metric threshold alert type', () => { alertThrottle: '3m', alertOnNoData: true, }); - const [firedResults, noDataResults, errorResults, notifications] = ungroupedResult; - expect(firedResults).toBe(30); - expect(noDataResults).toBe(0); - expect(errorResults).toBe(0); + const { fired, noData, error, notifications } = ungroupedResult; + expect(fired).toBe(30); + expect(noData).toBe(0); + expect(error).toBe(0); expect(notifications).toBe(15); }); }); @@ -83,15 +83,25 @@ describe('Previewing the metric threshold alert type', () => { alertThrottle: '1m', alertOnNoData: true, }); - const [firedResultsA, noDataResultsA, errorResultsA, notificationsA] = resultA; - expect(firedResultsA).toBe(30); - expect(noDataResultsA).toBe(0); - expect(errorResultsA).toBe(0); + const { + fired: firedA, + noData: noDataA, + error: errorA, + notifications: notificationsA, + } = resultA; + expect(firedA).toBe(30); + expect(noDataA).toBe(0); + expect(errorA).toBe(0); expect(notificationsA).toBe(30); - const [firedResultsB, noDataResultsB, errorResultsB, notificationsB] = resultB; - expect(firedResultsB).toBe(60); - expect(noDataResultsB).toBe(0); - expect(errorResultsB).toBe(0); + const { + fired: firedB, + noData: noDataB, + error: errorB, + notifications: notificationsB, + } = resultB; + expect(firedB).toBe(60); + expect(noDataB).toBe(0); + expect(errorB).toBe(0); expect(notificationsB).toBe(60); }); }); @@ -113,10 +123,10 @@ describe('Previewing the metric threshold alert type', () => { alertThrottle: '1m', alertOnNoData: true, }); - const [firedResults, noDataResults, errorResults, notifications] = ungroupedResult; - expect(firedResults).toBe(25); - expect(noDataResults).toBe(10); - expect(errorResults).toBe(0); + const { fired, noData, error, notifications } = ungroupedResult; + expect(fired).toBe(25); + expect(noData).toBe(10); + expect(error).toBe(0); expect(notifications).toBe(35); }); }); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.ts index ac6372a94b1fe..b9fa6659d5fcd 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.ts @@ -14,6 +14,7 @@ import { import { ILegacyScopedClusterClient } from '../../../../../../../src/core/server'; import { InfraSource } from '../../../../common/http_api/source_api'; import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds'; +import { PreviewResult } from '../common/types'; import { MetricExpressionParams } from './types'; import { evaluateAlert } from './lib/evaluate_alert'; @@ -39,7 +40,7 @@ export const previewMetricThresholdAlert: ( params: PreviewMetricThresholdAlertParams, iterations?: number, precalculatedNumberOfGroups?: number -) => Promise = async ( +) => Promise = async ( { callCluster, params, @@ -98,6 +99,7 @@ export const previewMetricThresholdAlert: ( numberOfResultBuckets / alertResultsPerExecution ); let numberOfTimesFired = 0; + let numberOfTimesWarned = 0; let numberOfNoDataResults = 0; let numberOfErrors = 0; let numberOfNotifications = 0; @@ -111,6 +113,9 @@ export const previewMetricThresholdAlert: ( const allConditionsFiredInMappedBucket = alertResults.every( (alertResult) => alertResult[group].shouldFire[mappedBucketIndex] ); + const allConditionsWarnInMappedBucket = + !allConditionsFiredInMappedBucket && + alertResults.every((alertResult) => alertResult[group].shouldWarn[mappedBucketIndex]); const someConditionsNoDataInMappedBucket = alertResults.some((alertResult) => { const hasNoData = alertResult[group].isNoData as boolean[]; return hasNoData[mappedBucketIndex]; @@ -131,6 +136,9 @@ export const previewMetricThresholdAlert: ( } else if (allConditionsFiredInMappedBucket) { numberOfTimesFired++; notifyWithThrottle(); + } else if (allConditionsWarnInMappedBucket) { + numberOfTimesWarned++; + notifyWithThrottle(); } else if (throttleTracker > 0) { throttleTracker += alertIntervalInSeconds; } @@ -138,7 +146,13 @@ export const previewMetricThresholdAlert: ( throttleTracker = 0; } } - return [numberOfTimesFired, numberOfNoDataResults, numberOfErrors, numberOfNotifications]; + return { + fired: numberOfTimesFired, + warning: numberOfTimesWarned, + noData: numberOfNoDataResults, + error: numberOfErrors, + notifications: numberOfNotifications, + }; }) ); return previewResults; @@ -199,7 +213,12 @@ export const previewMetricThresholdAlert: ( .reduce((a, b) => { if (!a) return b; if (!b) return a; - return [a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]]; + const res = { ...a }; + const entries = (Object.entries(b) as unknown) as Array<[keyof PreviewResult, number]>; + for (const [key, value] of entries) { + res[key] += value; + } + return res; }) ); return zippedResult; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts index 6d8790f4f430c..e5e3a7bff329e 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts @@ -15,7 +15,11 @@ import { ActionGroupIdsOf, } from '../../../../../alerts/server'; import { METRIC_EXPLORER_AGGREGATIONS } from '../../../../common/http_api/metrics_explorer'; -import { createMetricThresholdExecutor, FIRED_ACTIONS } from './metric_threshold_executor'; +import { + createMetricThresholdExecutor, + FIRED_ACTIONS, + WARNING_ACTIONS, +} from './metric_threshold_executor'; import { METRIC_THRESHOLD_ALERT_TYPE_ID, Comparator } from './types'; import { InfraBackendLibs } from '../../infra_types'; import { oneOfLiterals, validateIsStringElasticsearchJSONFilter } from '../common/utils'; @@ -37,7 +41,7 @@ export type MetricThresholdAlertType = AlertType< Record, AlertInstanceState, AlertInstanceContext, - ActionGroupIdsOf + ActionGroupIdsOf >; export type MetricThresholdAlertExecutorOptions = AlertExecutorOptions< /** @@ -47,7 +51,7 @@ export type MetricThresholdAlertExecutorOptions = AlertExecutorOptions< Record, AlertInstanceState, AlertInstanceContext, - ActionGroupIdsOf + ActionGroupIdsOf >; export function registerMetricThresholdAlertType(libs: InfraBackendLibs): MetricThresholdAlertType { @@ -56,6 +60,8 @@ export function registerMetricThresholdAlertType(libs: InfraBackendLibs): Metric comparator: oneOfLiterals(Object.values(Comparator)), timeUnit: schema.string(), timeSize: schema.number(), + warningThreshold: schema.maybe(schema.arrayOf(schema.number())), + warningComparator: schema.maybe(oneOfLiterals(Object.values(Comparator))), }; const nonCountCriterion = schema.object({ @@ -92,7 +98,7 @@ export function registerMetricThresholdAlertType(libs: InfraBackendLibs): Metric ), }, defaultActionGroupId: FIRED_ACTIONS.id, - actionGroups: [FIRED_ACTIONS], + actionGroups: [FIRED_ACTIONS, WARNING_ACTIONS], minimumLicenseRequired: 'basic', executor: createMetricThresholdExecutor(libs), actionVariables: { diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/types.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/types.ts index f876e40d9cd1f..37f21022f183d 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/types.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/types.ts @@ -29,6 +29,8 @@ interface BaseMetricExpressionParams { sourceId?: string; threshold: number[]; comparator: Comparator; + warningComparator?: Comparator; + warningThreshold?: number[]; } interface NonCountMetricExpressionParams extends BaseMetricExpressionParams { diff --git a/x-pack/plugins/infra/server/lib/alerting/register_alert_types.ts b/x-pack/plugins/infra/server/lib/alerting/register_alert_types.ts index 0b4df6805759e..11fbe269b854d 100644 --- a/x-pack/plugins/infra/server/lib/alerting/register_alert_types.ts +++ b/x-pack/plugins/infra/server/lib/alerting/register_alert_types.ts @@ -8,13 +8,21 @@ import { PluginSetupContract } from '../../../../alerts/server'; import { registerMetricThresholdAlertType } from './metric_threshold/register_metric_threshold_alert_type'; import { registerMetricInventoryThresholdAlertType } from './inventory_metric_threshold/register_inventory_metric_threshold_alert_type'; +import { registerMetricAnomalyAlertType } from './metric_anomaly/register_metric_anomaly_alert_type'; + import { registerLogThresholdAlertType } from './log_threshold/register_log_threshold_alert_type'; import { InfraBackendLibs } from '../infra_types'; +import { MlPluginSetup } from '../../../../ml/server'; -const registerAlertTypes = (alertingPlugin: PluginSetupContract, libs: InfraBackendLibs) => { +const registerAlertTypes = ( + alertingPlugin: PluginSetupContract, + libs: InfraBackendLibs, + ml?: MlPluginSetup +) => { if (alertingPlugin) { alertingPlugin.registerType(registerMetricThresholdAlertType(libs)); alertingPlugin.registerType(registerMetricInventoryThresholdAlertType(libs)); + alertingPlugin.registerType(registerMetricAnomalyAlertType(libs, ml)); const registerFns = [registerLogThresholdAlertType]; registerFns.forEach((fn) => { diff --git a/x-pack/plugins/infra/server/lib/infra_ml/common.ts b/x-pack/plugins/infra/server/lib/infra_ml/common.ts index 0182cb0e4099a..686f27d714cc1 100644 --- a/x-pack/plugins/infra/server/lib/infra_ml/common.ts +++ b/x-pack/plugins/infra/server/lib/infra_ml/common.ts @@ -17,6 +17,23 @@ import { import { decodeOrThrow } from '../../../common/runtime_types'; import { startTracingSpan, TracingSpan } from '../../../common/performance_tracing'; +export interface MappedAnomalyHit { + id: string; + anomalyScore: number; + typical: number; + actual: number; + jobId: string; + startTime: number; + duration: number; + influencers: string[]; + categoryId?: string; +} + +export interface InfluencerFilter { + fieldName: string; + fieldValue: string; +} + export async function fetchMlJob(mlAnomalyDetectors: MlAnomalyDetectors, jobId: string) { const finalizeMlGetJobSpan = startTracingSpan('Fetch ml job from ES'); const { diff --git a/x-pack/plugins/infra/server/lib/infra_ml/index.ts b/x-pack/plugins/infra/server/lib/infra_ml/index.ts index d346b71d76aa8..82093b1a359d0 100644 --- a/x-pack/plugins/infra/server/lib/infra_ml/index.ts +++ b/x-pack/plugins/infra/server/lib/infra_ml/index.ts @@ -8,3 +8,4 @@ export * from './errors'; export * from './metrics_hosts_anomalies'; export * from './metrics_k8s_anomalies'; +export { MappedAnomalyHit } from './common'; diff --git a/x-pack/plugins/infra/server/lib/infra_ml/metrics_hosts_anomalies.ts b/x-pack/plugins/infra/server/lib/infra_ml/metrics_hosts_anomalies.ts index 072f07dfaffdb..f6e11f5294191 100644 --- a/x-pack/plugins/infra/server/lib/infra_ml/metrics_hosts_anomalies.ts +++ b/x-pack/plugins/infra/server/lib/infra_ml/metrics_hosts_anomalies.ts @@ -5,11 +5,10 @@ * 2.0. */ -import type { InfraPluginRequestHandlerContext } from '../../types'; import { InfraRequestHandlerContext } from '../../types'; import { TracingSpan, startTracingSpan } from '../../../common/performance_tracing'; -import { fetchMlJob } from './common'; -import { getJobId, metricsHostsJobTypes } from '../../../common/infra_ml'; +import { fetchMlJob, MappedAnomalyHit, InfluencerFilter } from './common'; +import { getJobId, metricsHostsJobTypes, ANOMALY_THRESHOLD } from '../../../common/infra_ml'; import { Sort, Pagination } from '../../../common/http_api/infra_ml'; import type { MlSystem, MlAnomalyDetectors } from '../../types'; import { InsufficientAnomalyMlJobsConfigured, isMlPrivilegesError } from './errors'; @@ -19,18 +18,6 @@ import { createMetricsHostsAnomaliesQuery, } from './queries/metrics_hosts_anomalies'; -interface MappedAnomalyHit { - id: string; - anomalyScore: number; - typical: number; - actual: number; - jobId: string; - startTime: number; - duration: number; - influencers: string[]; - categoryId?: string; -} - async function getCompatibleAnomaliesJobIds( spaceId: string, sourceId: string, @@ -74,13 +61,15 @@ async function getCompatibleAnomaliesJobIds( } export async function getMetricsHostsAnomalies( - context: InfraPluginRequestHandlerContext & { infra: Required }, + context: Required, sourceId: string, + anomalyThreshold: ANOMALY_THRESHOLD, startTime: number, endTime: number, metric: 'memory_usage' | 'network_in' | 'network_out' | undefined, sort: Sort, - pagination: Pagination + pagination: Pagination, + influencerFilter?: InfluencerFilter ) { const finalizeMetricsHostsAnomaliesSpan = startTracingSpan('get metrics hosts entry anomalies'); @@ -88,10 +77,10 @@ export async function getMetricsHostsAnomalies( jobIds, timing: { spans: jobSpans }, } = await getCompatibleAnomaliesJobIds( - context.infra.spaceId, + context.spaceId, sourceId, metric, - context.infra.mlAnomalyDetectors + context.mlAnomalyDetectors ); if (jobIds.length === 0) { @@ -107,12 +96,14 @@ export async function getMetricsHostsAnomalies( hasMoreEntries, timing: { spans: fetchLogEntryAnomaliesSpans }, } = await fetchMetricsHostsAnomalies( - context.infra.mlSystem, + context.mlSystem, + anomalyThreshold, jobIds, startTime, endTime, sort, - pagination + pagination, + influencerFilter ); const data = anomalies.map((anomaly) => { @@ -162,11 +153,13 @@ const parseAnomalyResult = (anomaly: MappedAnomalyHit, jobId: string) => { async function fetchMetricsHostsAnomalies( mlSystem: MlSystem, + anomalyThreshold: ANOMALY_THRESHOLD, jobIds: string[], startTime: number, endTime: number, sort: Sort, - pagination: Pagination + pagination: Pagination, + influencerFilter?: InfluencerFilter ) { // We'll request 1 extra entry on top of our pageSize to determine if there are // more entries to be fetched. This avoids scenarios where the client side can't @@ -178,7 +171,15 @@ async function fetchMetricsHostsAnomalies( const results = decodeOrThrow(metricsHostsAnomaliesResponseRT)( await mlSystem.mlAnomalySearch( - createMetricsHostsAnomaliesQuery(jobIds, startTime, endTime, sort, expandedPagination), + createMetricsHostsAnomaliesQuery({ + jobIds, + anomalyThreshold, + startTime, + endTime, + sort, + pagination: expandedPagination, + influencerFilter, + }), jobIds ) ); diff --git a/x-pack/plugins/infra/server/lib/infra_ml/metrics_k8s_anomalies.ts b/x-pack/plugins/infra/server/lib/infra_ml/metrics_k8s_anomalies.ts index 44837d88ddb43..34039e9107f00 100644 --- a/x-pack/plugins/infra/server/lib/infra_ml/metrics_k8s_anomalies.ts +++ b/x-pack/plugins/infra/server/lib/infra_ml/metrics_k8s_anomalies.ts @@ -5,11 +5,10 @@ * 2.0. */ -import type { InfraPluginRequestHandlerContext } from '../../types'; import { InfraRequestHandlerContext } from '../../types'; import { TracingSpan, startTracingSpan } from '../../../common/performance_tracing'; -import { fetchMlJob } from './common'; -import { getJobId, metricsK8SJobTypes } from '../../../common/infra_ml'; +import { fetchMlJob, MappedAnomalyHit, InfluencerFilter } from './common'; +import { getJobId, metricsK8SJobTypes, ANOMALY_THRESHOLD } from '../../../common/infra_ml'; import { Sort, Pagination } from '../../../common/http_api/infra_ml'; import type { MlSystem, MlAnomalyDetectors } from '../../types'; import { InsufficientAnomalyMlJobsConfigured, isMlPrivilegesError } from './errors'; @@ -19,18 +18,6 @@ import { createMetricsK8sAnomaliesQuery, } from './queries/metrics_k8s_anomalies'; -interface MappedAnomalyHit { - id: string; - anomalyScore: number; - typical: number; - actual: number; - jobId: string; - startTime: number; - influencers: string[]; - duration: number; - categoryId?: string; -} - async function getCompatibleAnomaliesJobIds( spaceId: string, sourceId: string, @@ -74,13 +61,15 @@ async function getCompatibleAnomaliesJobIds( } export async function getMetricK8sAnomalies( - context: InfraPluginRequestHandlerContext & { infra: Required }, + context: Required, sourceId: string, + anomalyThreshold: ANOMALY_THRESHOLD, startTime: number, endTime: number, metric: 'memory_usage' | 'network_in' | 'network_out' | undefined, sort: Sort, - pagination: Pagination + pagination: Pagination, + influencerFilter?: InfluencerFilter ) { const finalizeMetricsK8sAnomaliesSpan = startTracingSpan('get metrics k8s entry anomalies'); @@ -88,10 +77,10 @@ export async function getMetricK8sAnomalies( jobIds, timing: { spans: jobSpans }, } = await getCompatibleAnomaliesJobIds( - context.infra.spaceId, + context.spaceId, sourceId, metric, - context.infra.mlAnomalyDetectors + context.mlAnomalyDetectors ); if (jobIds.length === 0) { @@ -106,12 +95,14 @@ export async function getMetricK8sAnomalies( hasMoreEntries, timing: { spans: fetchLogEntryAnomaliesSpans }, } = await fetchMetricK8sAnomalies( - context.infra.mlSystem, + context.mlSystem, + anomalyThreshold, jobIds, startTime, endTime, sort, - pagination + pagination, + influencerFilter ); const data = anomalies.map((anomaly) => { @@ -158,11 +149,13 @@ const parseAnomalyResult = (anomaly: MappedAnomalyHit, jobId: string) => { async function fetchMetricK8sAnomalies( mlSystem: MlSystem, + anomalyThreshold: ANOMALY_THRESHOLD, jobIds: string[], startTime: number, endTime: number, sort: Sort, - pagination: Pagination + pagination: Pagination, + influencerFilter?: InfluencerFilter | undefined ) { // We'll request 1 extra entry on top of our pageSize to determine if there are // more entries to be fetched. This avoids scenarios where the client side can't @@ -174,7 +167,15 @@ async function fetchMetricK8sAnomalies( const results = decodeOrThrow(metricsK8sAnomaliesResponseRT)( await mlSystem.mlAnomalySearch( - createMetricsK8sAnomaliesQuery(jobIds, startTime, endTime, sort, expandedPagination), + createMetricsK8sAnomaliesQuery({ + jobIds, + anomalyThreshold, + startTime, + endTime, + sort, + pagination: expandedPagination, + influencerFilter, + }), jobIds ) ); diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts index b3676fc54aeaa..6f996a672a44a 100644 --- a/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts @@ -77,3 +77,35 @@ export const createDatasetsFilters = (datasets?: string[]) => }, ] : []; + +export const createInfluencerFilter = ({ + fieldName, + fieldValue, +}: { + fieldName: string; + fieldValue: string; +}) => [ + { + nested: { + path: 'influencers', + query: { + bool: { + must: [ + { + match: { + 'influencers.influencer_field_name': fieldName, + }, + }, + { + query_string: { + fields: ['influencers.influencer_field_values'], + query: fieldValue, + minimum_should_match: 1, + }, + }, + ], + }, + }, + }, + }, +]; diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_host_anomalies.test.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_host_anomalies.test.ts new file mode 100644 index 0000000000000..4c3e0ca8bc26f --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_host_anomalies.test.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createMetricsHostsAnomaliesQuery } from './metrics_hosts_anomalies'; +import { Sort, Pagination } from '../../../../common/http_api/infra_ml'; + +describe('createMetricsHostAnomaliesQuery', () => { + const jobIds = ['kibana-metrics-ui-default-default-hosts_memory_usage']; + const anomalyThreshold = 30; + const startTime = 1612454527112; + const endTime = 1612541227112; + const sort: Sort = { field: 'anomalyScore', direction: 'desc' }; + const pagination: Pagination = { pageSize: 101 }; + + test('returns the correct query', () => { + expect( + createMetricsHostsAnomaliesQuery({ + jobIds, + anomalyThreshold, + startTime, + endTime, + sort, + pagination, + }) + ).toMatchObject({ + allowNoIndices: true, + ignoreUnavailable: true, + trackScores: false, + trackTotalHits: false, + body: { + query: { + bool: { + filter: [ + { terms: { job_id: ['kibana-metrics-ui-default-default-hosts_memory_usage'] } }, + { range: { record_score: { gte: 30 } } }, + { range: { timestamp: { gte: 1612454527112, lte: 1612541227112 } } }, + { terms: { result_type: ['record'] } }, + ], + }, + }, + sort: [{ record_score: 'desc' }, { _doc: 'desc' }], + size: 101, + _source: [ + 'job_id', + 'record_score', + 'typical', + 'actual', + 'partition_field_value', + 'timestamp', + 'bucket_span', + 'by_field_value', + 'host.name', + 'influencers.influencer_field_name', + 'influencers.influencer_field_values', + ], + }, + }); + }); +}); diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_hosts_anomalies.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_hosts_anomalies.ts index 07b25931d838e..7808851508a7c 100644 --- a/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_hosts_anomalies.ts +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_hosts_anomalies.ts @@ -6,6 +6,7 @@ */ import * as rt from 'io-ts'; +import { ANOMALY_THRESHOLD } from '../../../../common/infra_ml'; import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; import { createJobIdsFilters, @@ -13,7 +14,9 @@ import { createResultTypeFilters, defaultRequestParameters, createAnomalyScoreFilter, + createInfluencerFilter, } from './common'; +import { InfluencerFilter } from '../common'; import { Sort, Pagination } from '../../../../common/http_api/infra_ml'; // TODO: Reassess validity of this against ML docs @@ -25,23 +28,37 @@ const sortToMlFieldMap = { startTime: 'timestamp', }; -export const createMetricsHostsAnomaliesQuery = ( - jobIds: string[], - startTime: number, - endTime: number, - sort: Sort, - pagination: Pagination -) => { +export const createMetricsHostsAnomaliesQuery = ({ + jobIds, + anomalyThreshold, + startTime, + endTime, + sort, + pagination, + influencerFilter, +}: { + jobIds: string[]; + anomalyThreshold: ANOMALY_THRESHOLD; + startTime: number; + endTime: number; + sort: Sort; + pagination: Pagination; + influencerFilter?: InfluencerFilter; +}) => { const { field } = sort; const { pageSize } = pagination; const filters = [ ...createJobIdsFilters(jobIds), - ...createAnomalyScoreFilter(50), + ...createAnomalyScoreFilter(anomalyThreshold), ...createTimeRangeFilters(startTime, endTime), ...createResultTypeFilters(['record']), ]; + const influencerQuery = influencerFilter + ? { must: createInfluencerFilter(influencerFilter) } + : {}; + const sourceFields = [ 'job_id', 'record_score', @@ -69,6 +86,7 @@ export const createMetricsHostsAnomaliesQuery = ( query: { bool: { filter: filters, + ...influencerQuery, }, }, search_after: queryCursor, diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.test.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.test.ts new file mode 100644 index 0000000000000..81dcb390dff56 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.test.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createMetricsK8sAnomaliesQuery } from './metrics_k8s_anomalies'; +import { Sort, Pagination } from '../../../../common/http_api/infra_ml'; + +describe('createMetricsK8sAnomaliesQuery', () => { + const jobIds = ['kibana-metrics-ui-default-default-k8s_memory_usage']; + const anomalyThreshold = 30; + const startTime = 1612454527112; + const endTime = 1612541227112; + const sort: Sort = { field: 'anomalyScore', direction: 'desc' }; + const pagination: Pagination = { pageSize: 101 }; + + test('returns the correct query', () => { + expect( + createMetricsK8sAnomaliesQuery({ + jobIds, + anomalyThreshold, + startTime, + endTime, + sort, + pagination, + }) + ).toMatchObject({ + allowNoIndices: true, + ignoreUnavailable: true, + trackScores: false, + trackTotalHits: false, + body: { + query: { + bool: { + filter: [ + { terms: { job_id: ['kibana-metrics-ui-default-default-k8s_memory_usage'] } }, + { range: { record_score: { gte: 30 } } }, + { range: { timestamp: { gte: 1612454527112, lte: 1612541227112 } } }, + { terms: { result_type: ['record'] } }, + ], + }, + }, + sort: [{ record_score: 'desc' }, { _doc: 'desc' }], + size: 101, + _source: [ + 'job_id', + 'record_score', + 'typical', + 'actual', + 'partition_field_value', + 'timestamp', + 'bucket_span', + 'by_field_value', + 'influencers.influencer_field_name', + 'influencers.influencer_field_values', + ], + }, + }); + }); +}); diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.ts index 8a6e9396fb098..54eea067177ed 100644 --- a/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.ts +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.ts @@ -6,6 +6,7 @@ */ import * as rt from 'io-ts'; +import { ANOMALY_THRESHOLD } from '../../../../common/infra_ml'; import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; import { createJobIdsFilters, @@ -13,7 +14,9 @@ import { createResultTypeFilters, defaultRequestParameters, createAnomalyScoreFilter, + createInfluencerFilter, } from './common'; +import { InfluencerFilter } from '../common'; import { Sort, Pagination } from '../../../../common/http_api/infra_ml'; // TODO: Reassess validity of this against ML docs @@ -25,23 +28,37 @@ const sortToMlFieldMap = { startTime: 'timestamp', }; -export const createMetricsK8sAnomaliesQuery = ( - jobIds: string[], - startTime: number, - endTime: number, - sort: Sort, - pagination: Pagination -) => { +export const createMetricsK8sAnomaliesQuery = ({ + jobIds, + anomalyThreshold, + startTime, + endTime, + sort, + pagination, + influencerFilter, +}: { + jobIds: string[]; + anomalyThreshold: ANOMALY_THRESHOLD; + startTime: number; + endTime: number; + sort: Sort; + pagination: Pagination; + influencerFilter?: InfluencerFilter; +}) => { const { field } = sort; const { pageSize } = pagination; const filters = [ ...createJobIdsFilters(jobIds), - ...createAnomalyScoreFilter(50), + ...createAnomalyScoreFilter(anomalyThreshold), ...createTimeRangeFilters(startTime, endTime), ...createResultTypeFilters(['record']), ]; + const influencerQuery = influencerFilter + ? { must: createInfluencerFilter(influencerFilter) } + : {}; + const sourceFields = [ 'job_id', 'record_score', @@ -68,6 +85,7 @@ export const createMetricsK8sAnomaliesQuery = ( query: { bool: { filter: filters, + ...influencerQuery, }, }, search_after: queryCursor, diff --git a/x-pack/plugins/infra/server/lib/sources/defaults.ts b/x-pack/plugins/infra/server/lib/sources/defaults.ts index ce7c4410baca9..1b924619a905c 100644 --- a/x-pack/plugins/infra/server/lib/sources/defaults.ts +++ b/x-pack/plugins/infra/server/lib/sources/defaults.ts @@ -45,4 +45,5 @@ export const defaultSourceConfiguration: InfraSourceConfiguration = { }, }, ], + anomalyThreshold: 50, }; diff --git a/x-pack/plugins/infra/server/lib/sources/errors.ts b/x-pack/plugins/infra/server/lib/sources/errors.ts index fb0dc3b031511..082dfc611cc5b 100644 --- a/x-pack/plugins/infra/server/lib/sources/errors.ts +++ b/x-pack/plugins/infra/server/lib/sources/errors.ts @@ -4,10 +4,17 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +/* eslint-disable max-classes-per-file */ export class NotFoundError extends Error { constructor(message?: string) { super(message); Object.setPrototypeOf(this, new.target.prototype); } } + +export class AnomalyThresholdRangeError extends Error { + constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} diff --git a/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.test.ts b/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.test.ts index 4cea6cbe32cfb..21b7643ca6a7f 100644 --- a/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.test.ts +++ b/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.test.ts @@ -126,6 +126,7 @@ const createTestSourceConfiguration = (logAlias: string, metricAlias: string) => ], logAlias, metricAlias, + anomalyThreshold: 20, }, id: 'TEST_ID', type: infraSourceConfigurationSavedObjectName, diff --git a/x-pack/plugins/infra/server/lib/sources/sources.ts b/x-pack/plugins/infra/server/lib/sources/sources.ts index aad877a077acf..fe005b04978da 100644 --- a/x-pack/plugins/infra/server/lib/sources/sources.ts +++ b/x-pack/plugins/infra/server/lib/sources/sources.ts @@ -10,9 +10,10 @@ import { failure } from 'io-ts/lib/PathReporter'; import { identity, constant } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import { map, fold } from 'fp-ts/lib/Either'; +import { inRange } from 'lodash'; import { SavedObjectsClientContract } from 'src/core/server'; import { defaultSourceConfiguration } from './defaults'; -import { NotFoundError } from './errors'; +import { AnomalyThresholdRangeError, NotFoundError } from './errors'; import { infraSourceConfigurationSavedObjectName } from './saved_object_type'; import { InfraSavedSourceConfiguration, @@ -104,6 +105,9 @@ export class InfraSources { source: InfraSavedSourceConfiguration ) { const staticDefaultSourceConfiguration = await this.getStaticDefaultSourceConfiguration(); + const { anomalyThreshold } = source; + if (anomalyThreshold && !inRange(anomalyThreshold, 0, 101)) + throw new AnomalyThresholdRangeError('anomalyThreshold must be 1-100'); const newSourceConfiguration = mergeSourceConfiguration( staticDefaultSourceConfiguration, @@ -140,6 +144,10 @@ export class InfraSources { sourceProperties: InfraSavedSourceConfiguration ) { const staticDefaultSourceConfiguration = await this.getStaticDefaultSourceConfiguration(); + const { anomalyThreshold } = sourceProperties; + + if (anomalyThreshold && !inRange(anomalyThreshold, 0, 101)) + throw new AnomalyThresholdRangeError('anomalyThreshold must be 1-100'); const { configuration, version } = await this.getSourceConfiguration( savedObjectsClient, diff --git a/x-pack/plugins/infra/server/plugin.ts b/x-pack/plugins/infra/server/plugin.ts index 99555fa56acd5..0ac49e05b36b9 100644 --- a/x-pack/plugins/infra/server/plugin.ts +++ b/x-pack/plugins/infra/server/plugin.ts @@ -137,7 +137,7 @@ export class InfraServerPlugin implements Plugin { ]); initInfraServer(this.libs); - registerAlertTypes(plugins.alerts, this.libs); + registerAlertTypes(plugins.alerts, this.libs, plugins.ml); core.http.registerRouteHandlerContext( 'infra', diff --git a/x-pack/plugins/infra/server/routes/alerting/preview.ts b/x-pack/plugins/infra/server/routes/alerting/preview.ts index ba16221108958..3da560135eaf4 100644 --- a/x-pack/plugins/infra/server/routes/alerting/preview.ts +++ b/x-pack/plugins/infra/server/routes/alerting/preview.ts @@ -5,20 +5,25 @@ * 2.0. */ +import { PreviewResult } from '../../lib/alerting/common/types'; import { METRIC_THRESHOLD_ALERT_TYPE_ID, METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, + METRIC_ANOMALY_ALERT_TYPE_ID, INFRA_ALERT_PREVIEW_PATH, TOO_MANY_BUCKETS_PREVIEW_EXCEPTION, alertPreviewRequestParamsRT, alertPreviewSuccessResponsePayloadRT, MetricThresholdAlertPreviewRequestParams, InventoryAlertPreviewRequestParams, + MetricAnomalyAlertPreviewRequestParams, } from '../../../common/alerting/metrics'; import { createValidationFunction } from '../../../common/runtime_types'; import { previewInventoryMetricThresholdAlert } from '../../lib/alerting/inventory_metric_threshold/preview_inventory_metric_threshold_alert'; import { previewMetricThresholdAlert } from '../../lib/alerting/metric_threshold/preview_metric_threshold_alert'; +import { previewMetricAnomalyAlert } from '../../lib/alerting/metric_anomaly/preview_metric_anomaly_alert'; import { InfraBackendLibs } from '../../lib/infra_types'; +import { assertHasInfraMlPlugins } from '../../utils/request_context'; export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs) => { const { callWithRequest } = framework; @@ -32,8 +37,6 @@ export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs) }, framework.router.handleLegacyErrors(async (requestContext, request, response) => { const { - criteria, - filterQuery, lookback, sourceId, alertType, @@ -54,7 +57,11 @@ export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs) try { switch (alertType) { case METRIC_THRESHOLD_ALERT_TYPE_ID: { - const { groupBy } = request.body as MetricThresholdAlertPreviewRequestParams; + const { + groupBy, + criteria, + filterQuery, + } = request.body as MetricThresholdAlertPreviewRequestParams; const previewResult = await previewMetricThresholdAlert({ callCluster, params: { criteria, filterQuery, groupBy }, @@ -65,33 +72,17 @@ export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs) alertOnNoData, }); - const numberOfGroups = previewResult.length; - const resultTotals = previewResult.reduce( - (totals, [firedResult, noDataResult, errorResult, notifications]) => { - return { - ...totals, - fired: totals.fired + firedResult, - noData: totals.noData + noDataResult, - error: totals.error + errorResult, - notifications: totals.notifications + notifications, - }; - }, - { - fired: 0, - noData: 0, - error: 0, - notifications: 0, - } - ); + const payload = processPreviewResults(previewResult); return response.ok({ - body: alertPreviewSuccessResponsePayloadRT.encode({ - numberOfGroups, - resultTotals, - }), + body: alertPreviewSuccessResponsePayloadRT.encode(payload), }); } case METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID: { - const { nodeType } = request.body as InventoryAlertPreviewRequestParams; + const { + nodeType, + criteria, + filterQuery, + } = request.body as InventoryAlertPreviewRequestParams; const previewResult = await previewInventoryMetricThresholdAlert({ callCluster, params: { criteria, filterQuery, nodeType }, @@ -102,29 +93,42 @@ export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs) alertOnNoData, }); - const numberOfGroups = previewResult.length; - const resultTotals = previewResult.reduce( - (totals, [firedResult, noDataResult, errorResult, notifications]) => { - return { - ...totals, - fired: totals.fired + firedResult, - noData: totals.noData + noDataResult, - error: totals.error + errorResult, - notifications: totals.notifications + notifications, - }; - }, - { - fired: 0, - noData: 0, - error: 0, - notifications: 0, - } - ); + const payload = processPreviewResults(previewResult); + + return response.ok({ + body: alertPreviewSuccessResponsePayloadRT.encode(payload), + }); + } + case METRIC_ANOMALY_ALERT_TYPE_ID: { + assertHasInfraMlPlugins(requestContext); + const { + nodeType, + metric, + threshold, + influencerFilter, + } = request.body as MetricAnomalyAlertPreviewRequestParams; + const { mlAnomalyDetectors, mlSystem, spaceId } = requestContext.infra; + + const previewResult = await previewMetricAnomalyAlert({ + mlAnomalyDetectors, + mlSystem, + spaceId, + params: { nodeType, metric, threshold, influencerFilter }, + lookback, + sourceId: source.id, + alertInterval, + alertThrottle, + alertOnNoData, + }); return response.ok({ body: alertPreviewSuccessResponsePayloadRT.encode({ - numberOfGroups, - resultTotals, + numberOfGroups: 1, + resultTotals: { + ...previewResult, + error: 0, + noData: 0, + }, }), }); } @@ -150,3 +154,27 @@ export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs) }) ); }; + +const processPreviewResults = (previewResult: PreviewResult[]) => { + const numberOfGroups = previewResult.length; + const resultTotals = previewResult.reduce( + (totals, { fired, warning, noData, error, notifications }) => { + return { + ...totals, + fired: totals.fired + fired, + warning: totals.warning + warning, + noData: totals.noData + noData, + error: totals.error + error, + notifications: totals.notifications + notifications, + }; + }, + { + fired: 0, + warning: 0, + noData: 0, + error: 0, + notifications: 0, + } + ); + return { numberOfGroups, resultTotals }; +}; diff --git a/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_hosts_anomalies.ts b/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_hosts_anomalies.ts index 215ebf3280c03..6e227cfc12d11 100644 --- a/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_hosts_anomalies.ts +++ b/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_hosts_anomalies.ts @@ -34,6 +34,7 @@ export const initGetHostsAnomaliesRoute = ({ framework }: InfraBackendLibs) => { const { data: { sourceId, + anomalyThreshold, timeRange: { startTime, endTime }, sort: sortParam, pagination: paginationParam, @@ -52,8 +53,9 @@ export const initGetHostsAnomaliesRoute = ({ framework }: InfraBackendLibs) => { hasMoreEntries, timing, } = await getMetricsHostsAnomalies( - requestContext, + requestContext.infra, sourceId, + anomalyThreshold, startTime, endTime, metric, diff --git a/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_k8s_anomalies.ts b/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_k8s_anomalies.ts index 906278be657d3..1c2c4947a02ea 100644 --- a/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_k8s_anomalies.ts +++ b/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_k8s_anomalies.ts @@ -33,6 +33,7 @@ export const initGetK8sAnomaliesRoute = ({ framework }: InfraBackendLibs) => { const { data: { sourceId, + anomalyThreshold, timeRange: { startTime, endTime }, sort: sortParam, pagination: paginationParam, @@ -51,8 +52,9 @@ export const initGetK8sAnomaliesRoute = ({ framework }: InfraBackendLibs) => { hasMoreEntries, timing, } = await getMetricK8sAnomalies( - requestContext, + requestContext.infra, sourceId, + anomalyThreshold, startTime, endTime, metric, diff --git a/x-pack/plugins/infra/server/routes/source/index.ts b/x-pack/plugins/infra/server/routes/source/index.ts index f1132049bd03c..5c3827e56ce79 100644 --- a/x-pack/plugins/infra/server/routes/source/index.ts +++ b/x-pack/plugins/infra/server/routes/source/index.ts @@ -16,6 +16,7 @@ import { import { InfraBackendLibs } from '../../lib/infra_types'; import { hasData } from '../../lib/sources/has_data'; import { createSearchClient } from '../../lib/create_search_client'; +import { AnomalyThresholdRangeError } from '../../lib/sources/errors'; const typeToInfraIndexType = (value: string | undefined) => { switch (value) { @@ -137,6 +138,15 @@ export const initSourceRoute = (libs: InfraBackendLibs) => { throw error; } + if (error instanceof AnomalyThresholdRangeError) { + return response.customError({ + statusCode: 400, + body: { + message: error.message, + }, + }); + } + return response.customError({ statusCode: error.statusCode ?? 500, body: { diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts index 16a45dc6489ee..bc4976a068f4d 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts @@ -279,6 +279,7 @@ const createSourceConfigurationMock = (): InfraSource => ({ timestamp: 'TIMESTAMP_FIELD', tiebreaker: 'TIEBREAKER_FIELD', }, + anomalyThreshold: 20, }, }); diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts index 6bcc61f2be4a6..7ac8b71c04b2a 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts @@ -216,6 +216,7 @@ const createSourceConfigurationMock = () => ({ timestamp: 'TIMESTAMP_FIELD', tiebreaker: 'TIEBREAKER_FIELD', }, + anomalyThreshold: 20, }, }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx index e5b07aacee16e..393c7363dc03f 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx @@ -7,7 +7,7 @@ import './config_panel.scss'; -import React, { useMemo, memo, useEffect, useState, useCallback } from 'react'; +import React, { useMemo, memo } from 'react'; import { EuiFlexItem, EuiToolTip, EuiButton, EuiForm } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Visualization } from '../../../types'; @@ -16,6 +16,7 @@ import { trackUiEvent } from '../../../lens_ui_telemetry'; import { generateId } from '../../../id_generator'; import { removeLayer, appendLayer } from './layer_actions'; import { ConfigPanelWrapperProps } from './types'; +import { useFocusUpdate } from './use_focus_update'; export const ConfigPanelWrapper = memo(function ConfigPanelWrapper(props: ConfigPanelWrapperProps) { const activeVisualization = props.visualizationMap[props.activeVisualizationId || '']; @@ -26,50 +27,6 @@ export const ConfigPanelWrapper = memo(function ConfigPanelWrapper(props: Config ) : null; }); -function useFocusUpdate(layerIds: string[]) { - const [nextFocusedLayerId, setNextFocusedLayerId] = useState(null); - const [layerRefs, setLayersRefs] = useState>({}); - - useEffect(() => { - const focusable = nextFocusedLayerId && layerRefs[nextFocusedLayerId]; - if (focusable) { - focusable.focus(); - setNextFocusedLayerId(null); - } - }, [layerIds, layerRefs, nextFocusedLayerId]); - - const setLayerRef = useCallback((layerId, el) => { - if (el) { - setLayersRefs((refs) => ({ - ...refs, - [layerId]: el, - })); - } - }, []); - - const removeLayerRef = useCallback( - (layerId) => { - if (layerIds.length <= 1) { - return setNextFocusedLayerId(layerId); - } - - const removedLayerIndex = layerIds.findIndex((l) => l === layerId); - const nextFocusedLayerIdId = - removedLayerIndex === 0 ? layerIds[1] : layerIds[removedLayerIndex - 1]; - - setLayersRefs((refs) => { - const newLayerRefs = { ...refs }; - delete newLayerRefs[layerId]; - return newLayerRefs; - }); - return setNextFocusedLayerId(nextFocusedLayerIdId); - }, - [layerIds] - ); - - return { setNextFocusedLayerId, removeLayerRef, setLayerRef }; -} - export function LayerPanels( props: ConfigPanelWrapperProps & { activeDatasourceId: string; @@ -85,7 +42,11 @@ export function LayerPanels( } = props; const layerIds = activeVisualization.getLayerIds(visualizationState); - const { setNextFocusedLayerId, removeLayerRef, setLayerRef } = useFocusUpdate(layerIds); + const { + setNextFocusedId: setNextFocusedLayerId, + removeRef: removeLayerRef, + registerNewRef: registerNewLayerRef, + } = useFocusUpdate(layerIds); const setVisualizationState = useMemo( () => (newState: unknown) => { @@ -145,7 +106,7 @@ export function LayerPanels( void; }) { const dropType = layerDatasource.getDropTypes({ ...layerDatasourceDropProps, @@ -94,8 +96,17 @@ export function DraggableDimensionButton({ [group.accessors] ); + const registerNewButtonRefMemoized = useCallback((el) => registerNewButtonRef(columnId, el), [ + registerNewButtonRef, + columnId, + ]); + return ( -
+
{ dispatch: jest.fn(), core: coreMock.createStart(), layerIndex: 0, - setLayerRef: jest.fn(), + registerNewLayerRef: jest.fn(), }; } @@ -620,17 +620,26 @@ describe('LayerPanel', () => { ); - - component.find(DragDrop).at(1).prop('onDrop')!(draggingOperation, 'reorder'); + act(() => { + component.find(DragDrop).at(1).prop('onDrop')!(draggingOperation, 'reorder'); + }); expect(mockDatasource.onDrop).toHaveBeenCalledWith( expect.objectContaining({ dropType: 'reorder', droppedItem: draggingOperation, }) ); + const secondButton = component + .find(DragDrop) + .at(1) + .find('[data-test-subj="lnsDragDrop-keyboardHandler"]') + .instance(); + const focusedEl = document.activeElement; + expect(focusedEl).toEqual(secondButton); }); it('should copy when dropping on empty slot in the same group', () => { + (generateId as jest.Mock).mockReturnValue(`newid`); mockVisualization.getConfiguration.mockReturnValue({ groups: [ { @@ -657,9 +666,12 @@ describe('LayerPanel', () => { ); - component.find(DragDrop).at(2).prop('onDrop')!(draggingOperation, 'duplicate_in_group'); + act(() => { + component.find(DragDrop).at(2).prop('onDrop')!(draggingOperation, 'duplicate_in_group'); + }); expect(mockDatasource.onDrop).toHaveBeenCalledWith( expect.objectContaining({ + columnId: 'newid', dropType: 'duplicate_in_group', droppedItem: draggingOperation, }) diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index 80e9ed05b982d..5ba73e98b42c1 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -26,6 +26,7 @@ import { RemoveLayerButton } from './remove_layer_button'; import { EmptyDimensionButton } from './empty_dimension_button'; import { DimensionButton } from './dimension_button'; import { DraggableDimensionButton } from './draggable_dimension_button'; +import { useFocusUpdate } from './use_focus_update'; const initialActiveDimensionState = { isNew: false, @@ -45,7 +46,7 @@ export function LayerPanel( newVisualizationState: unknown ) => void; onRemoveLayer: () => void; - setLayerRef: (layerId: string, instance: HTMLDivElement | null) => void; + registerNewLayerRef: (layerId: string, instance: HTMLDivElement | null) => void; } ) { const dragDropContext = useContext(DragContext); @@ -58,7 +59,7 @@ export function LayerPanel( layerId, isOnlyLayer, onRemoveLayer, - setLayerRef, + registerNewLayerRef, layerIndex, activeVisualization, updateVisualization, @@ -70,7 +71,10 @@ export function LayerPanel( setActiveDimension(initialActiveDimensionState); }, [activeVisualization.id]); - const setLayerRefMemoized = useCallback((el) => setLayerRef(layerId, el), [layerId, setLayerRef]); + const registerLayerRef = useCallback((el) => registerNewLayerRef(layerId, el), [ + layerId, + registerNewLayerRef, + ]); const layerVisualizationConfigProps = { layerId, @@ -114,6 +118,16 @@ export function LayerPanel( const { setDimension, removeDimension } = activeVisualization; const layerDatasourceOnDrop = layerDatasource.onDrop; + const allAccessors = groups.flatMap((group) => + group.accessors.map((accessor) => accessor.columnId) + ); + + const { + setNextFocusedId: setNextFocusedButtonId, + removeRef: removeButtonRef, + registerNewRef: registerNewButtonRef, + } = useFocusUpdate(allAccessors); + const onDrop = useMemo(() => { return ( droppedItem: DragDropIdentifier, @@ -127,7 +141,12 @@ export function LayerPanel( columnId, groupId, layerId: targetLayerId, - } = (targetItem as unknown) as DraggedOperation; // TODO: correct misleading name + } = (targetItem as unknown) as DraggedOperation; + if (dropType === 'reorder' || dropType === 'field_replace' || dropType === 'field_add') { + setNextFocusedButtonId(droppedItem.id); + } else { + setNextFocusedButtonId(columnId); + } const filterOperations = groups.find(({ groupId: gId }) => gId === targetItem.groupId)?.filterOperations || @@ -171,11 +190,12 @@ export function LayerPanel( setDimension, removeDimension, layerDatasourceDropProps, + setNextFocusedButtonId, ]); return ( -
+
@@ -264,6 +284,7 @@ export function LayerPanel( return ( { + const focusableSelector = 'button, [href], input, select, textarea, [tabindex]'; + if (!el) { + return null; + } + if (el.matches(focusableSelector)) { + return el; + } + const firstFocusable = el.querySelector(focusableSelector); + if (!firstFocusable) { + return null; + } + return (firstFocusable as unknown) as { focus: () => void }; +}; + +type RefsById = Record; + +export function useFocusUpdate(ids: string[]) { + const [nextFocusedId, setNextFocusedId] = useState(null); + const [refsById, setRefsById] = useState({}); + + useEffect(() => { + const element = nextFocusedId && refsById[nextFocusedId]; + if (element) { + const focusable = getFirstFocusable(element); + focusable?.focus(); + setNextFocusedId(null); + } + }, [ids, refsById, nextFocusedId]); + + const registerNewRef = useCallback((id, el) => { + if (el) { + setRefsById((r) => ({ + ...r, + [id]: el, + })); + } + }, []); + + const removeRef = useCallback( + (id) => { + if (ids.length <= 1) { + return setNextFocusedId(id); + } + + const removedIndex = ids.findIndex((l) => l === id); + + setRefsById((refs) => { + const newRefsById = { ...refs }; + delete newRefsById[id]; + return newRefsById; + }); + const next = removedIndex === 0 ? ids[1] : ids[removedIndex - 1]; + return setNextFocusedId(next); + }, + [ids] + ); + + return { setNextFocusedId, removeRef, registerNewRef }; +} diff --git a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts index 62de8baa66d5f..7a21599605b52 100644 --- a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts @@ -8,7 +8,11 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ import { Query } from 'src/plugins/data/public'; -import { StyleDescriptor, VectorStyleDescriptor } from './style_property_descriptor_types'; +import { + HeatmapStyleDescriptor, + StyleDescriptor, + VectorStyleDescriptor, +} from './style_property_descriptor_types'; import { DataRequestDescriptor } from './data_request_descriptor_types'; import { AbstractSourceDescriptor, TermJoinSourceDescriptor } from './source_descriptor_types'; @@ -40,3 +44,7 @@ export type LayerDescriptor = { export type VectorLayerDescriptor = LayerDescriptor & { style: VectorStyleDescriptor; }; + +export type HeatmapLayerDescriptor = LayerDescriptor & { + style: HeatmapStyleDescriptor; +}; diff --git a/x-pack/plugins/maps/kibana.json b/x-pack/plugins/maps/kibana.json index 3966af9e28742..1d4f76db79751 100644 --- a/x-pack/plugins/maps/kibana.json +++ b/x-pack/plugins/maps/kibana.json @@ -11,7 +11,7 @@ "features", "inspector", "data", - "mapsFileUpload", + "fileUpload", "uiActions", "navigation", "visualizations", diff --git a/x-pack/plugins/maps/public/actions/data_request_actions.ts b/x-pack/plugins/maps/public/actions/data_request_actions.ts index 2e6a8098e5c21..5e8a18348ac5a 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -40,7 +40,7 @@ import { UPDATE_SOURCE_DATA_REQUEST, } from './map_action_constants'; import { ILayer } from '../classes/layers/layer'; -import { IVectorLayer } from '../classes/layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../classes/layers/vector_layer'; import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types'; import { DataRequestAbortError } from '../classes/util/data_request'; import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_util'; diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index 16aa44af4460f..d68e4744975f1 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -42,7 +42,7 @@ import { clearDataRequests, syncDataForLayerId, updateStyleMeta } from './data_r import { cleanTooltipStateForLayer } from './tooltip_actions'; import { JoinDescriptor, LayerDescriptor, StyleDescriptor } from '../../common/descriptor_types'; import { ILayer } from '../classes/layers/layer'; -import { IVectorLayer } from '../classes/layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../classes/layers/vector_layer'; import { LAYER_STYLE_TYPE, LAYER_TYPE } from '../../common/constants'; import { IVectorStyle } from '../classes/styles/vector/vector_style'; import { notifyLicensedFeatureUsage } from '../licensed_features'; diff --git a/x-pack/plugins/maps/public/classes/joins/inner_join.test.js b/x-pack/plugins/maps/public/classes/joins/inner_join.test.js index 749745530af7e..67fbf94fd1787 100644 --- a/x-pack/plugins/maps/public/classes/joins/inner_join.test.js +++ b/x-pack/plugins/maps/public/classes/joins/inner_join.test.js @@ -9,7 +9,7 @@ import { InnerJoin } from './inner_join'; import { SOURCE_TYPES } from '../../../common/constants'; jest.mock('../../kibana_services', () => {}); -jest.mock('../layers/vector_layer/vector_layer', () => {}); +jest.mock('../layers/vector_layer', () => {}); const rightSource = { type: SOURCE_TYPES.ES_TERM_SOURCE, diff --git a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts index 5d4b915c4e971..d3a4fa4101ac9 100644 --- a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { VectorLayer } from '../vector_layer/vector_layer'; +import { IVectorLayer, VectorLayer } from '../vector_layer'; import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; import { getDefaultDynamicProperties } from '../../styles/vector/vector_style_defaults'; import { IDynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property'; @@ -24,7 +24,6 @@ import { } from '../../../../common/constants'; import { ESGeoGridSource } from '../../sources/es_geo_grid_source/es_geo_grid_source'; import { canSkipSourceUpdate } from '../../util/can_skip_fetch'; -import { IVectorLayer } from '../vector_layer/vector_layer'; import { IESSource } from '../../sources/es_source'; import { ISource } from '../../sources/source'; import { DataRequestContext } from '../../../actions'; diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts index a85ba041c4351..a4955a965d77c 100644 --- a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts @@ -23,7 +23,7 @@ import { ESSearchSourceDescriptor, } from '../../../../common/descriptor_types'; import { VectorStyle } from '../../styles/vector/vector_style'; -import { VectorLayer } from '../vector_layer/vector_layer'; +import { VectorLayer } from '../vector_layer'; import { EMSFileSource } from '../../sources/ems_file_source'; // @ts-ignore import { ESSearchSource } from '../../sources/es_search_source'; diff --git a/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts index 8e0d234445355..658a093321500 100644 --- a/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts @@ -22,8 +22,7 @@ import { } from '../../../common/constants'; import { VectorStyle } from '../styles/vector/vector_style'; import { EMSFileSource } from '../sources/ems_file_source'; -// @ts-ignore -import { VectorLayer } from './vector_layer/vector_layer'; +import { VectorLayer } from './vector_layer'; import { getDefaultDynamicProperties } from '../styles/vector/vector_style_defaults'; import { NUMERICAL_COLOR_PALETTES } from '../styles/color_palettes'; import { getJoinAggKey } from '../../../common/get_agg_key'; diff --git a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts index a9de8c98ee557..e3e5f3878ee56 100644 --- a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts @@ -23,11 +23,9 @@ import { VECTOR_STYLES, } from '../../../common/constants'; import { VectorStyle } from '../styles/vector/vector_style'; -// @ts-ignore import { ESGeoGridSource } from '../sources/es_geo_grid_source'; -import { VectorLayer } from './vector_layer/vector_layer'; -// @ts-ignore -import { HeatmapLayer } from './heatmap_layer/heatmap_layer'; +import { VectorLayer } from './vector_layer'; +import { HeatmapLayer } from './heatmap_layer'; import { getDefaultDynamicProperties } from '../styles/vector/vector_style_defaults'; import { NUMERICAL_COLOR_PALETTES } from '../styles/color_palettes'; import { getSourceAggKey } from '../../../common/get_agg_key'; diff --git a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx b/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx index a61ea4ce713a8..44a22f1529f18 100644 --- a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx @@ -16,10 +16,10 @@ import { } from '../../../../common/constants'; import { getFileUploadComponent } from '../../../kibana_services'; import { GeoJsonFileSource } from '../../sources/geojson_file_source'; -import { VectorLayer } from '../../layers/vector_layer/vector_layer'; +import { VectorLayer } from '../../layers/vector_layer'; import { createDefaultLayerDescriptor } from '../../sources/es_search_source'; import { RenderWizardArguments } from '../../layers/layer_wizard_registry'; -import { FileUploadComponentProps } from '../../../../../maps_file_upload/public'; +import { FileUploadComponentProps } from '../../../../../file_upload/public'; export const INDEX_SETUP_STEP_ID = 'INDEX_SETUP_STEP_ID'; export const INDEXING_STEP_ID = 'INDEXING_STEP_ID'; diff --git a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.js b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.js deleted file mode 100644 index 97cc7151112bf..0000000000000 --- a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.js +++ /dev/null @@ -1,122 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { AbstractLayer } from '../layer'; -import { VectorLayer } from '../vector_layer/vector_layer'; -import { HeatmapStyle } from '../../styles/heatmap/heatmap_style'; -import { EMPTY_FEATURE_COLLECTION, LAYER_TYPE } from '../../../../common/constants'; - -const SCALED_PROPERTY_NAME = '__kbn_heatmap_weight__'; //unique name to store scaled value for weighting - -export class HeatmapLayer extends VectorLayer { - static type = LAYER_TYPE.HEATMAP; - - static createDescriptor(options) { - const heatmapLayerDescriptor = super.createDescriptor(options); - heatmapLayerDescriptor.type = HeatmapLayer.type; - heatmapLayerDescriptor.style = HeatmapStyle.createDescriptor(); - return heatmapLayerDescriptor; - } - - constructor({ layerDescriptor, source }) { - super({ layerDescriptor, source }); - if (!layerDescriptor.style) { - const defaultStyle = HeatmapStyle.createDescriptor(); - this._style = new HeatmapStyle(defaultStyle); - } else { - this._style = new HeatmapStyle(layerDescriptor.style); - } - } - - getStyleForEditing() { - return this._style; - } - - getStyle() { - return this._style; - } - - getCurrentStyle() { - return this._style; - } - - _getPropKeyOfSelectedMetric() { - const metricfields = this.getSource().getMetricFields(); - return metricfields[0].getName(); - } - - _getHeatmapLayerId() { - return this.makeMbLayerId('heatmap'); - } - - getMbLayerIds() { - return [this._getHeatmapLayerId()]; - } - - ownsMbLayerId(mbLayerId) { - return this._getHeatmapLayerId() === mbLayerId; - } - - syncLayerWithMB(mbMap) { - super._syncSourceBindingWithMb(mbMap); - - const heatmapLayerId = this._getHeatmapLayerId(); - if (!mbMap.getLayer(heatmapLayerId)) { - mbMap.addLayer({ - id: heatmapLayerId, - type: 'heatmap', - source: this.getId(), - paint: {}, - }); - } - - const mbSourceAfter = mbMap.getSource(this.getId()); - const sourceDataRequest = this.getSourceDataRequest(); - const featureCollection = sourceDataRequest ? sourceDataRequest.getData() : null; - if (!featureCollection) { - mbSourceAfter.setData(EMPTY_FEATURE_COLLECTION); - return; - } - - const propertyKey = this._getPropKeyOfSelectedMetric(); - const dataBoundToMap = AbstractLayer.getBoundDataForSource(mbMap, this.getId()); - if (featureCollection !== dataBoundToMap) { - let max = 1; //max will be at least one, since counts or sums will be at least one. - for (let i = 0; i < featureCollection.features.length; i++) { - max = Math.max(featureCollection.features[i].properties[propertyKey], max); - } - for (let i = 0; i < featureCollection.features.length; i++) { - featureCollection.features[i].properties[SCALED_PROPERTY_NAME] = - featureCollection.features[i].properties[propertyKey] / max; - } - mbSourceAfter.setData(featureCollection); - } - - this.syncVisibilityWithMb(mbMap, heatmapLayerId); - this.getCurrentStyle().setMBPaintProperties({ - mbMap, - layerId: heatmapLayerId, - propertyName: SCALED_PROPERTY_NAME, - resolution: this.getSource().getGridResolution(), - }); - mbMap.setPaintProperty(heatmapLayerId, 'heatmap-opacity', this.getAlpha()); - mbMap.setLayerZoomRange(heatmapLayerId, this.getMinZoom(), this.getMaxZoom()); - } - - getLayerTypeIconName() { - return 'heatmap'; - } - - async hasLegendDetails() { - return true; - } - - renderLegendDetails() { - const metricFields = this.getSource().getMetricFields(); - return this.getCurrentStyle().renderLegendDetails(metricFields[0]); - } -} diff --git a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts new file mode 100644 index 0000000000000..8eebd7c57afd7 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts @@ -0,0 +1,182 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Map as MbMap, GeoJSONSource as MbGeoJSONSource } from 'mapbox-gl'; +import { FeatureCollection } from 'geojson'; +import { AbstractLayer } from '../layer'; +import { HeatmapStyle } from '../../styles/heatmap/heatmap_style'; +import { EMPTY_FEATURE_COLLECTION, LAYER_TYPE } from '../../../../common/constants'; +import { HeatmapLayerDescriptor, MapQuery } from '../../../../common/descriptor_types'; +import { ESGeoGridSource } from '../../sources/es_geo_grid_source'; +import { addGeoJsonMbSource, syncVectorSource } from '../vector_layer'; +import { DataRequestContext } from '../../../actions'; +import { DataRequestAbortError } from '../../util/data_request'; + +const SCALED_PROPERTY_NAME = '__kbn_heatmap_weight__'; // unique name to store scaled value for weighting + +export class HeatmapLayer extends AbstractLayer { + static type = LAYER_TYPE.HEATMAP; + + private readonly _style: HeatmapStyle; + + static createDescriptor(options: Partial) { + const heatmapLayerDescriptor = super.createDescriptor(options); + heatmapLayerDescriptor.type = HeatmapLayer.type; + heatmapLayerDescriptor.style = HeatmapStyle.createDescriptor(); + return heatmapLayerDescriptor; + } + + constructor({ + layerDescriptor, + source, + }: { + layerDescriptor: HeatmapLayerDescriptor; + source: ESGeoGridSource; + }) { + super({ layerDescriptor, source }); + if (!layerDescriptor.style) { + const defaultStyle = HeatmapStyle.createDescriptor(); + this._style = new HeatmapStyle(defaultStyle); + } else { + this._style = new HeatmapStyle(layerDescriptor.style); + } + } + + getSource(): ESGeoGridSource { + return super.getSource() as ESGeoGridSource; + } + + getStyleForEditing() { + return this._style; + } + + getStyle() { + return this._style; + } + + getCurrentStyle() { + return this._style; + } + + _getPropKeyOfSelectedMetric() { + const metricfields = this.getSource().getMetricFields(); + return metricfields[0].getName(); + } + + _getHeatmapLayerId() { + return this.makeMbLayerId('heatmap'); + } + + getMbLayerIds() { + return [this._getHeatmapLayerId()]; + } + + ownsMbLayerId(mbLayerId: string) { + return this._getHeatmapLayerId() === mbLayerId; + } + + ownsMbSourceId(mbSourceId: string) { + return this.getId() === mbSourceId; + } + + async syncData(syncContext: DataRequestContext) { + if (this.isLoadingBounds()) { + return; + } + + const sourceQuery = this.getQuery() as MapQuery; + try { + await syncVectorSource({ + layerId: this.getId(), + layerName: await this.getDisplayName(this.getSource()), + prevDataRequest: this.getSourceDataRequest(), + requestMeta: { + ...syncContext.dataFilters, + fieldNames: this.getSource().getFieldNames(), + geogridPrecision: this.getSource().getGeoGridPrecision(syncContext.dataFilters.zoom), + sourceQuery: sourceQuery ? sourceQuery : undefined, + applyGlobalQuery: this.getSource().getApplyGlobalQuery(), + applyGlobalTime: this.getSource().getApplyGlobalTime(), + sourceMeta: this.getSource().getSyncMeta(), + }, + syncContext, + source: this.getSource(), + }); + } catch (error) { + if (!(error instanceof DataRequestAbortError)) { + throw error; + } + } + } + + syncLayerWithMB(mbMap: MbMap) { + addGeoJsonMbSource(this._getMbSourceId(), this.getMbLayerIds(), mbMap); + + const heatmapLayerId = this._getHeatmapLayerId(); + if (!mbMap.getLayer(heatmapLayerId)) { + mbMap.addLayer({ + id: heatmapLayerId, + type: 'heatmap', + source: this.getId(), + paint: {}, + }); + } + + const mbGeoJSONSource = mbMap.getSource(this.getId()) as MbGeoJSONSource; + const sourceDataRequest = this.getSourceDataRequest(); + const featureCollection = sourceDataRequest + ? (sourceDataRequest.getData() as FeatureCollection) + : null; + if (!featureCollection) { + mbGeoJSONSource.setData(EMPTY_FEATURE_COLLECTION); + return; + } + + const propertyKey = this._getPropKeyOfSelectedMetric(); + const dataBoundToMap = AbstractLayer.getBoundDataForSource(mbMap, this.getId()); + if (featureCollection !== dataBoundToMap) { + let max = 1; // max will be at least one, since counts or sums will be at least one. + for (let i = 0; i < featureCollection.features.length; i++) { + max = Math.max(featureCollection.features[i].properties?.[propertyKey], max); + } + for (let i = 0; i < featureCollection.features.length; i++) { + if (featureCollection.features[i].properties) { + featureCollection.features[i].properties![SCALED_PROPERTY_NAME] = + featureCollection.features[i].properties![propertyKey] / max; + } + } + mbGeoJSONSource.setData(featureCollection); + } + + this.syncVisibilityWithMb(mbMap, heatmapLayerId); + this.getCurrentStyle().setMBPaintProperties({ + mbMap, + layerId: heatmapLayerId, + propertyName: SCALED_PROPERTY_NAME, + resolution: this.getSource().getGridResolution(), + }); + mbMap.setPaintProperty(heatmapLayerId, 'heatmap-opacity', this.getAlpha()); + mbMap.setLayerZoomRange(heatmapLayerId, this.getMinZoom(), this.getMaxZoom()); + } + + getLayerTypeIconName() { + return 'heatmap'; + } + + async getFields() { + return this.getSource().getFields(); + } + + async hasLegendDetails() { + return true; + } + + renderLegendDetails() { + const metricFields = this.getSource().getMetricFields(); + return this.getCurrentStyle().renderLegendDetails(metricFields[0]); + } +} diff --git a/x-pack/plugins/maps_file_upload/server/models/import_data/index.js b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/index.ts similarity index 83% rename from x-pack/plugins/maps_file_upload/server/models/import_data/index.js rename to x-pack/plugins/maps/public/classes/layers/heatmap_layer/index.ts index c1ba4b84975e5..ba15d97a39219 100644 --- a/x-pack/plugins/maps_file_upload/server/models/import_data/index.js +++ b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { importDataProvider } from './import_data'; +export { HeatmapLayer } from './heatmap_layer'; diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index aedf7af08b2c8..89c6d70a217c9 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -21,6 +21,7 @@ import { MAX_ZOOM, MB_SOURCE_ID_LAYER_ID_PREFIX_DELIMITER, MIN_ZOOM, + SOURCE_BOUNDS_DATA_REQUEST_ID, SOURCE_DATA_REQUEST_ID, SOURCE_TYPES, STYLE_TYPE, @@ -66,6 +67,7 @@ export interface ILayer { getImmutableSourceProperties(): Promise; renderSourceSettingsEditor({ onChange }: SourceEditorArgs): ReactElement | null; isLayerLoading(): boolean; + isLoadingBounds(): boolean; isFilteredByGlobalTime(): Promise; hasErrors(): boolean; getErrors(): string; @@ -401,6 +403,11 @@ export class AbstractLayer implements ILayer { return this._dataRequests.some((dataRequest) => dataRequest.isLoading()); } + isLoadingBounds() { + const boundsDataRequest = this.getDataRequest(SOURCE_BOUNDS_DATA_REQUEST_ID); + return !!boundsDataRequest && boundsDataRequest.isLoading(); + } + hasErrors(): boolean { return _.get(this._descriptor, '__isInErrorState', false); } diff --git a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts b/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts index a32ae15405fac..bed7599f89073 100644 --- a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts +++ b/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts @@ -9,7 +9,6 @@ import { registerLayerWizard } from './layer_wizard_registry'; import { uploadLayerWizardConfig } from './file_upload_wizard'; // @ts-ignore import { esDocumentsLayerWizardConfig } from '../sources/es_search_source'; -// @ts-ignore import { clustersLayerWizardConfig, heatmapLayerWizardConfig } from '../sources/es_geo_grid_source'; import { geoLineLayerWizardConfig } from '../sources/es_geo_line_source'; // @ts-ignore diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts index c312ddec42572..b9cfb0067abd2 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts @@ -176,7 +176,6 @@ describe('createLayerDescriptor', () => { __dataRequests: [], alpha: 0.75, id: '12345', - joins: [], label: '[Performance] Duration', maxZoom: 24, minZoom: 0, diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts index fd9147d62cc26..03870e7668189 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts @@ -31,11 +31,9 @@ import { OBSERVABILITY_METRIC_TYPE } from './metric_select'; import { DISPLAY } from './display_select'; import { VectorStyle } from '../../../styles/vector/vector_style'; import { EMSFileSource } from '../../../sources/ems_file_source'; -// @ts-ignore import { ESGeoGridSource } from '../../../sources/es_geo_grid_source'; -import { VectorLayer } from '../../vector_layer/vector_layer'; -// @ts-ignore -import { HeatmapLayer } from '../../heatmap_layer/heatmap_layer'; +import { VectorLayer } from '../../vector_layer'; +import { HeatmapLayer } from '../../heatmap_layer'; import { getDefaultDynamicProperties } from '../../../styles/vector/vector_style_defaults'; // redefining APM constant to avoid making maps app depend on APM plugin diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.ts b/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.ts index 74a66276459c7..b2283196a41dd 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.ts +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.ts @@ -22,7 +22,7 @@ import { SYMBOLIZE_AS_TYPES, VECTOR_STYLES, } from '../../../../../common/constants'; -import { VectorLayer } from '../../vector_layer/vector_layer'; +import { VectorLayer } from '../../vector_layer'; import { VectorStyle } from '../../../styles/vector/vector_style'; // @ts-ignore import { ESSearchSource } from '../../../sources/es_search_source'; diff --git a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx index d98396b960cbd..477b17ae03d7b 100644 --- a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx @@ -15,7 +15,7 @@ import { EuiIcon } from '@elastic/eui'; import { Feature } from 'geojson'; import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; import { SOURCE_DATA_REQUEST_ID, LAYER_TYPE } from '../../../../common/constants'; -import { VectorLayer, VectorLayerArguments } from '../vector_layer/vector_layer'; +import { VectorLayer, VectorLayerArguments } from '../vector_layer'; import { ITiledSingleLayerVectorSource } from '../../sources/vector_source'; import { DataRequestContext } from '../../../actions'; import { diff --git a/x-pack/plugins/maps/public/classes/util/assign_feature_ids.test.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.test.ts similarity index 97% rename from x-pack/plugins/maps/public/classes/util/assign_feature_ids.test.ts rename to x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.test.ts index 4fe3804968b81..137d443b39b91 100644 --- a/x-pack/plugins/maps/public/classes/util/assign_feature_ids.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.test.ts @@ -6,7 +6,7 @@ */ import { assignFeatureIds } from './assign_feature_ids'; -import { FEATURE_ID_PROPERTY_NAME } from '../../../common/constants'; +import { FEATURE_ID_PROPERTY_NAME } from '../../../../common/constants'; import { FeatureCollection, Feature, Point } from 'geojson'; const featureId = 'myFeature1'; diff --git a/x-pack/plugins/maps/public/classes/util/assign_feature_ids.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.ts similarity index 96% rename from x-pack/plugins/maps/public/classes/util/assign_feature_ids.ts rename to x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.ts index f6b7851159586..c40c8299ad04c 100644 --- a/x-pack/plugins/maps/public/classes/util/assign_feature_ids.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.ts @@ -7,7 +7,7 @@ import _ from 'lodash'; import { FeatureCollection, Feature } from 'geojson'; -import { FEATURE_ID_PROPERTY_NAME } from '../../../common/constants'; +import { FEATURE_ID_PROPERTY_NAME } from '../../../../common/constants'; let idCounter = 0; diff --git a/x-pack/plugins/maps_file_upload/server/telemetry/index.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts similarity index 63% rename from x-pack/plugins/maps_file_upload/server/telemetry/index.ts rename to x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts index 83cd64c3f0e6f..4b509ba5dff00 100644 --- a/x-pack/plugins/maps_file_upload/server/telemetry/index.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts @@ -5,5 +5,5 @@ * 2.0. */ -export { registerFileUploadUsageCollector } from './file_upload_usage_collector'; -export { fileUploadTelemetryMappingsType } from './mappings'; +export { addGeoJsonMbSource, syncVectorSource } from './utils'; +export { IVectorLayer, VectorLayer, VectorLayerArguments } from './vector_layer'; diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/utils.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/utils.tsx new file mode 100644 index 0000000000000..a3754b20de818 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/utils.tsx @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FeatureCollection } from 'geojson'; +import { Map as MbMap } from 'mapbox-gl'; +import { + EMPTY_FEATURE_COLLECTION, + SOURCE_DATA_REQUEST_ID, + VECTOR_SHAPE_TYPE, +} from '../../../../common/constants'; +import { VectorSourceRequestMeta } from '../../../../common/descriptor_types'; +import { DataRequestContext } from '../../../actions'; +import { IVectorSource } from '../../sources/vector_source'; +import { DataRequestAbortError } from '../../util/data_request'; +import { DataRequest } from '../../util/data_request'; +import { getCentroidFeatures } from '../../../../common/get_centroid_features'; +import { canSkipSourceUpdate } from '../../util/can_skip_fetch'; +import { assignFeatureIds } from './assign_feature_ids'; + +export function addGeoJsonMbSource(mbSourceId: string, mbLayerIds: string[], mbMap: MbMap) { + const mbSource = mbMap.getSource(mbSourceId); + if (!mbSource) { + mbMap.addSource(mbSourceId, { + type: 'geojson', + data: EMPTY_FEATURE_COLLECTION, + }); + } else if (mbSource.type !== 'geojson') { + // Recreate source when existing source is not geojson. This can occur when layer changes from tile layer to vector layer. + mbLayerIds.forEach((mbLayerId) => { + if (mbMap.getLayer(mbLayerId)) { + mbMap.removeLayer(mbLayerId); + } + }); + + mbMap.removeSource(mbSourceId); + mbMap.addSource(mbSourceId, { + type: 'geojson', + data: EMPTY_FEATURE_COLLECTION, + }); + } +} + +export async function syncVectorSource({ + layerId, + layerName, + prevDataRequest, + requestMeta, + syncContext, + source, +}: { + layerId: string; + layerName: string; + prevDataRequest: DataRequest | undefined; + requestMeta: VectorSourceRequestMeta; + syncContext: DataRequestContext; + source: IVectorSource; +}): Promise<{ refreshed: boolean; featureCollection: FeatureCollection }> { + const { + startLoading, + stopLoading, + onLoadError, + registerCancelCallback, + isRequestStillActive, + } = syncContext; + const dataRequestId = SOURCE_DATA_REQUEST_ID; + const requestToken = Symbol(`${layerId}-${dataRequestId}`); + const canSkipFetch = await canSkipSourceUpdate({ + source, + prevDataRequest, + nextMeta: requestMeta, + }); + if (canSkipFetch) { + return { + refreshed: false, + featureCollection: prevDataRequest + ? (prevDataRequest.getData() as FeatureCollection) + : EMPTY_FEATURE_COLLECTION, + }; + } + + try { + startLoading(dataRequestId, requestToken, requestMeta); + const { data: sourceFeatureCollection, meta } = await source.getGeoJsonWithMeta( + layerName, + requestMeta, + registerCancelCallback.bind(null, requestToken), + () => { + return isRequestStillActive(dataRequestId, requestToken); + } + ); + const layerFeatureCollection = assignFeatureIds(sourceFeatureCollection); + const supportedShapes = await source.getSupportedShapeTypes(); + if ( + supportedShapes.includes(VECTOR_SHAPE_TYPE.LINE) || + supportedShapes.includes(VECTOR_SHAPE_TYPE.POLYGON) + ) { + layerFeatureCollection.features.push(...getCentroidFeatures(layerFeatureCollection)); + } + stopLoading(dataRequestId, requestToken, layerFeatureCollection, meta); + return { + refreshed: true, + featureCollection: layerFeatureCollection, + }; + } catch (error) { + if (!(error instanceof DataRequestAbortError)) { + onLoadError(dataRequestId, requestToken, error.message); + } + throw error; + } +} diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index e9c0cb29c7c17..7e87d99fd4f93 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -13,10 +13,8 @@ import { EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { AbstractLayer } from '../layer'; import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; -import { getCentroidFeatures } from '../../../../common/get_centroid_features'; import { FEATURE_ID_PROPERTY_NAME, - SOURCE_DATA_REQUEST_ID, SOURCE_META_DATA_REQUEST_ID, SOURCE_FORMATTERS_DATA_REQUEST_ID, SOURCE_BOUNDS_DATA_REQUEST_ID, @@ -25,10 +23,8 @@ import { KBN_TOO_MANY_FEATURES_PROPERTY, LAYER_TYPE, FIELD_ORIGIN, - LAYER_STYLE_TYPE, KBN_TOO_MANY_FEATURES_IMAGE_ID, FieldFormatter, - VECTOR_SHAPE_TYPE, } from '../../../../common/constants'; import { JoinTooltipProperty } from '../../tooltips/join_tooltip_property'; import { DataRequestAbortError } from '../../util/data_request'; @@ -37,7 +33,6 @@ import { canSkipStyleMetaUpdate, canSkipFormattersUpdate, } from '../../util/can_skip_fetch'; -import { assignFeatureIds } from '../../util/assign_feature_ids'; import { getFeatureCollectionBounds } from '../../util/get_feature_collection_bounds'; import { getCentroidFilterExpression, @@ -65,6 +60,7 @@ import { IDynamicStyleProperty } from '../../styles/vector/properties/dynamic_st import { IESSource } from '../../sources/es_source'; import { PropertiesMap } from '../../../../common/elasticsearch_util'; import { ITermJoinSource } from '../../sources/term_join_source'; +import { addGeoJsonMbSource, syncVectorSource } from './utils'; interface SourceResult { refreshed: boolean; @@ -95,7 +91,7 @@ export interface IVectorLayer extends ILayer { hasJoins(): boolean; } -export class VectorLayer extends AbstractLayer { +export class VectorLayer extends AbstractLayer implements IVectorLayer { static type = LAYER_TYPE.VECTOR; protected readonly _style: IVectorStyle; @@ -288,11 +284,6 @@ export class VectorLayer extends AbstractLayer { return bounds; } - isLoadingBounds() { - const boundsDataRequest = this.getDataRequest(SOURCE_BOUNDS_DATA_REQUEST_ID); - return !!boundsDataRequest && boundsDataRequest.isLoading(); - } - async getLeftJoinFields() { return await this.getSource().getLeftJoinFields(); } @@ -420,11 +411,9 @@ export class VectorLayer extends AbstractLayer { source: IVectorSource, style: IVectorStyle ): VectorSourceRequestMeta { - const styleFieldNames = - style.getType() === LAYER_STYLE_TYPE.VECTOR ? style.getSourceFieldNames() : []; const fieldNames = [ ...source.getFieldNames(), - ...styleFieldNames, + ...style.getSourceFieldNames(), ...this.getValidJoins().map((join) => join.getLeftField().getName()), ]; @@ -485,82 +474,11 @@ export class VectorLayer extends AbstractLayer { } } - async _syncSource( - syncContext: DataRequestContext, - source: IVectorSource, - style: IVectorStyle - ): Promise { - const { - startLoading, - stopLoading, - onLoadError, - registerCancelCallback, - dataFilters, - isRequestStillActive, - } = syncContext; - const dataRequestId = SOURCE_DATA_REQUEST_ID; - const requestToken = Symbol(`layer-${this.getId()}-${dataRequestId}`); - const searchFilters: VectorSourceRequestMeta = this._getSearchFilters( - dataFilters, - source, - style - ); - const prevDataRequest = this.getSourceDataRequest(); - const canSkipFetch = await canSkipSourceUpdate({ - source, - prevDataRequest, - nextMeta: searchFilters, - }); - if (canSkipFetch) { - return { - refreshed: false, - featureCollection: prevDataRequest - ? (prevDataRequest.getData() as FeatureCollection) - : EMPTY_FEATURE_COLLECTION, - }; - } - - try { - startLoading(dataRequestId, requestToken, searchFilters); - const layerName = await this.getDisplayName(source); - const { data: sourceFeatureCollection, meta } = await source.getGeoJsonWithMeta( - layerName, - searchFilters, - registerCancelCallback.bind(null, requestToken), - () => { - return isRequestStillActive(dataRequestId, requestToken); - } - ); - const layerFeatureCollection = assignFeatureIds(sourceFeatureCollection); - const supportedShapes = await source.getSupportedShapeTypes(); - if ( - supportedShapes.includes(VECTOR_SHAPE_TYPE.LINE) || - supportedShapes.includes(VECTOR_SHAPE_TYPE.POLYGON) - ) { - layerFeatureCollection.features.push(...getCentroidFeatures(layerFeatureCollection)); - } - stopLoading(dataRequestId, requestToken, layerFeatureCollection, meta); - return { - refreshed: true, - featureCollection: layerFeatureCollection, - }; - } catch (error) { - if (!(error instanceof DataRequestAbortError)) { - onLoadError(dataRequestId, requestToken, error.message); - } - throw error; - } - } - async _syncSourceStyleMeta( syncContext: DataRequestContext, source: IVectorSource, style: IVectorStyle ) { - if (this.getCurrentStyle().getType() !== LAYER_STYLE_TYPE.VECTOR) { - return; - } - const sourceQuery = this.getQuery() as MapQuery; return this._syncStyleMeta({ source, @@ -665,10 +583,6 @@ export class VectorLayer extends AbstractLayer { source: IVectorSource, style: IVectorStyle ) { - if (style.getType() !== LAYER_STYLE_TYPE.VECTOR) { - return; - } - return this._syncFormatters({ source, dataRequestId: SOURCE_FORMATTERS_DATA_REQUEST_ID, @@ -773,7 +687,14 @@ export class VectorLayer extends AbstractLayer { try { await this._syncSourceStyleMeta(syncContext, source, style); await this._syncSourceFormatters(syncContext, source, style); - const sourceResult = await this._syncSource(syncContext, source, style); + const sourceResult = await syncVectorSource({ + layerId: this.getId(), + layerName: await this.getDisplayName(source), + prevDataRequest: this.getSourceDataRequest(), + requestMeta: this._getSearchFilters(syncContext.dataFilters, source, style), + syncContext, + source, + }); if ( !sourceResult.featureCollection || !sourceResult.featureCollection.features.length || @@ -1061,31 +982,8 @@ export class VectorLayer extends AbstractLayer { this._setMbCentroidProperties(mbMap); } - _syncSourceBindingWithMb(mbMap: MbMap) { - const mbSource = mbMap.getSource(this._getMbSourceId()); - if (!mbSource) { - mbMap.addSource(this._getMbSourceId(), { - type: 'geojson', - data: EMPTY_FEATURE_COLLECTION, - }); - } else if (mbSource.type !== 'geojson') { - // Recreate source when existing source is not geojson. This can occur when layer changes from tile layer to vector layer. - this.getMbLayerIds().forEach((mbLayerId) => { - if (mbMap.getLayer(mbLayerId)) { - mbMap.removeLayer(mbLayerId); - } - }); - - mbMap.removeSource(this._getMbSourceId()); - mbMap.addSource(this._getMbSourceId(), { - type: 'geojson', - data: EMPTY_FEATURE_COLLECTION, - }); - } - } - syncLayerWithMB(mbMap: MbMap) { - this._syncSourceBindingWithMb(mbMap); + addGeoJsonMbSource(this._getMbSourceId(), this.getMbLayerIds(), mbMap); this._syncFeatureCollectionWithMb(mbMap); this._syncStylePropertiesWithMb(mbMap); } diff --git a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_boundaries_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_boundaries_layer_wizard.tsx index 3acc3c59e5930..d4cf4dbee7943 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_boundaries_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_boundaries_layer_wizard.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { VectorLayer } from '../../layers/vector_layer/vector_layer'; +import { VectorLayer } from '../../layers/vector_layer'; import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; import { EMSFileCreateSourceEditor } from './create_source_editor'; import { EMSFileSource, getSourceTitle } from './ems_file_source'; diff --git a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.test.tsx b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.test.tsx index 5a0a3ed8df596..e711fb900e39a 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.test.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.test.tsx @@ -7,7 +7,7 @@ import { EMSFileSource } from './ems_file_source'; -jest.mock('../../layers/vector_layer/vector_layer', () => {}); +jest.mock('../../layers/vector_layer', () => {}); function makeEMSFileSource(tooltipProperties: string[]) { const emsFileSource = new EMSFileSource({ tooltipProperties }); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx index 8951b7b278459..36dd28cb5bbf1 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx @@ -9,10 +9,9 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; -// @ts-ignore import { ESGeoGridSource, clustersTitle } from './es_geo_grid_source'; import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; -import { VectorLayer } from '../../layers/vector_layer/vector_layer'; +import { VectorLayer } from '../../layers/vector_layer'; import { ESGeoGridSourceDescriptor, ColorDynamicOptions, diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/heatmap_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/heatmap_layer_wizard.tsx index 83a7e02383f77..8fc26f3593750 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/heatmap_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/heatmap_layer_wizard.tsx @@ -9,11 +9,9 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; -// @ts-ignore import { ESGeoGridSource, heatmapTitle } from './es_geo_grid_source'; import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; -// @ts-ignore -import { HeatmapLayer } from '../../layers/heatmap_layer/heatmap_layer'; +import { HeatmapLayer } from '../../layers/heatmap_layer'; import { ESGeoGridSourceDescriptor } from '../../../../common/descriptor_types'; import { LAYER_WIZARD_CATEGORY, RENDER_AS } from '../../../../common/constants'; import { HeatmapLayerIcon } from '../../layers/icons/heatmap_layer_icon'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/index.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/index.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/index.js rename to x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/index.ts diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/layer_wizard.tsx index 6a1dfc74271d8..8da7037a5a34c 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/layer_wizard.tsx @@ -12,7 +12,7 @@ import { ESGeoLineSource, geoLineTitle, REQUIRES_GOLD_LICENSE_MSG } from './es_g import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; import { LAYER_WIZARD_CATEGORY, STYLE_TYPE, VECTOR_STYLES } from '../../../../common/constants'; import { VectorStyle } from '../../styles/vector/vector_style'; -import { VectorLayer } from '../../layers/vector_layer/vector_layer'; +import { VectorLayer } from '../../layers/vector_layer'; import { getIsGoldPlus } from '../../../licensed_features'; import { TracksLayerIcon } from '../../layers/icons/tracks_layer_icon'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx index 49b161711481c..c94c7859a85e7 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { getDefaultDynamicProperties } from '../../styles/vector/vector_style_defaults'; -import { VectorLayer } from '../../layers/vector_layer/vector_layer'; +import { VectorLayer } from '../../layers/vector_layer'; // @ts-ignore import { ESPewPewSource, sourceTitle } from './es_pew_pew_source'; import { VectorStyle } from '../../styles/vector/vector_style'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/create_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/sources/es_search_source/create_layer_descriptor.ts index 2734af5742dbb..41b4e8d7a318a 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/create_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/create_layer_descriptor.ts @@ -9,7 +9,7 @@ import { Query } from 'src/plugins/data/public'; import { LayerDescriptor } from '../../../../common/descriptor_types'; import { ES_GEO_FIELD_TYPE, SCALING_TYPES } from '../../../../common/constants'; import { ESSearchSource } from './es_search_source'; -import { VectorLayer } from '../../layers/vector_layer/vector_layer'; +import { VectorLayer } from '../../layers/vector_layer'; import { getIsGoldPlus } from '../../../licensed_features'; export interface CreateLayerDescriptorParams { diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx index d01ed459e3171..c0606b5f4aec6 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx @@ -13,7 +13,7 @@ import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_re // @ts-ignore import { ESSearchSource, sourceTitle } from './es_search_source'; import { BlendedVectorLayer } from '../../layers/blended_vector_layer/blended_vector_layer'; -import { VectorLayer } from '../../layers/vector_layer/vector_layer'; +import { VectorLayer } from '../../layers/vector_layer'; import { LAYER_WIZARD_CATEGORY, SCALING_TYPES } from '../../../../common/constants'; import { TiledVectorLayer } from '../../layers/tiled_vector_layer/tiled_vector_layer'; import { DocumentsLayerIcon } from '../../layers/icons/documents_layer_icon'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.test.js b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.test.js index a7994db286112..1f4a1ab7c9afa 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.test.js +++ b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.test.js @@ -7,7 +7,7 @@ import { ESTermSource, extractPropertiesMap } from './es_term_source'; -jest.mock('../../layers/vector_layer/vector_layer', () => {}); +jest.mock('../../layers/vector_layer', () => {}); const indexPatternTitle = 'myIndex'; const termFieldName = 'myTermField'; diff --git a/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_layer_wizard.tsx index b41f599ac3d75..907b80e6405a6 100644 --- a/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_layer_wizard.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; // @ts-ignore import { KibanaRegionmapSource, sourceTitle } from './kibana_regionmap_source'; -import { VectorLayer } from '../../layers/vector_layer/vector_layer'; +import { VectorLayer } from '../../layers/vector_layer'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; import { getKibanaRegionList } from '../../../meta'; diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx index f30040cf93b57..fe581a1807b28 100644 --- a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx @@ -31,7 +31,7 @@ export class HeatmapStyle implements IStyle { this._descriptor = HeatmapStyle.createDescriptor(descriptor.colorRampName); } - static createDescriptor(colorRampName: string) { + static createDescriptor(colorRampName?: string) { return { type: LAYER_STYLE_TYPE.HEATMAP, colorRampName: colorRampName ? colorRampName : DEFAULT_HEATMAP_COLOR_RAMP_NAME, diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.test.tsx b/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.test.tsx index 3cfae4a836042..d0d3a7c2abe06 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.test.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { StyleProperties, VectorStyleEditor } from './vector_style_editor'; import { getDefaultStaticProperties } from '../vector_style_defaults'; -import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../../../layers/vector_layer'; import { IVectorSource } from '../../../sources/vector_source'; import { FIELD_ORIGIN, diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.tsx b/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.tsx index b36f3a38e2783..91bcc2dc06859 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.tsx @@ -49,7 +49,7 @@ import { SymbolizeAsProperty } from '../properties/symbolize_as_property'; import { LabelBorderSizeProperty } from '../properties/label_border_size_property'; import { StaticTextProperty } from '../properties/static_text_property'; import { StaticSizeProperty } from '../properties/static_size_property'; -import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../../../layers/vector_layer'; export interface StyleProperties { [key: string]: IStyleProperty; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx index 03b7ce17063c3..b7e0133881ee1 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx @@ -24,7 +24,7 @@ import { } from '../../../../../common/constants'; import { mockField, MockLayer, MockStyle } from './test_helpers/test_util'; import { ColorDynamicOptions } from '../../../../../common/descriptor_types'; -import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../../../layers/vector_layer'; import { IField } from '../../../fields/field'; const makeProperty = (options: ColorDynamicOptions, style?: MockStyle, field?: IField) => { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.test.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.test.tsx index fc4d495f1e40a..46339c5a4a20d 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.test.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.test.tsx @@ -20,7 +20,7 @@ import { DynamicIconProperty } from './dynamic_icon_property'; import { mockField, MockLayer } from './test_helpers/test_util'; import { IconDynamicOptions } from '../../../../../common/descriptor_types'; import { IField } from '../../../fields/field'; -import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../../../layers/vector_layer'; const makeProperty = (options: Partial, field: IField = mockField) => { const defaultOptions: IconDynamicOptions = { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx index 40d72a357218f..64a3e0cf0e322 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx @@ -21,7 +21,7 @@ import { IField } from '../../../fields/field'; import { Map as MbMap } from 'mapbox-gl'; import { SizeDynamicOptions } from '../../../../../common/descriptor_types'; import { mockField, MockLayer, MockStyle } from './test_helpers/test_util'; -import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../../../layers/vector_layer'; export class MockMbMap { _paintPropertyCalls: unknown[]; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.tsx index 52b78b4211a2d..7076775dcce31 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.tsx @@ -20,7 +20,7 @@ import { import { FieldFormatter, MB_LOOKUP_FUNCTION, VECTOR_STYLES } from '../../../../../common/constants'; import { SizeDynamicOptions } from '../../../../../common/descriptor_types'; import { IField } from '../../../fields/field'; -import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../../../layers/vector_layer'; export class DynamicSizeProperty extends DynamicStyleProperty { private readonly _isSymbolizedAsIcon: boolean; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index f62b17ee05ad6..9ffd9a0f1b345 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -34,7 +34,7 @@ import { StyleMetaData, } from '../../../../../common/descriptor_types'; import { IField } from '../../../fields/field'; -import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../../../layers/vector_layer'; import { InnerJoin } from '../../../joins/inner_join'; import { IVectorStyle } from '../vector_style'; import { getComputedFieldName } from '../style_util'; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index c61e72807224a..692be08d07bc6 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -70,7 +70,7 @@ import { DataRequest } from '../../util/data_request'; import { IStyle } from '../style'; import { IStyleProperty } from './properties/style_property'; import { IField } from '../../fields/field'; -import { IVectorLayer } from '../../layers/vector_layer/vector_layer'; +import { IVectorLayer } from '../../layers/vector_layer'; import { IVectorSource } from '../../sources/vector_source'; import { createStyleFieldsHelper, StyleFieldsHelper } from './style_fields_helper'; import { IESAggField } from '../../fields/agg'; diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index 4a7bccb31380d..1fbca669b0d8e 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -27,7 +27,7 @@ export const getIndexPatternService = () => pluginsStart.data.indexPatterns; export const getAutocompleteService = () => pluginsStart.data.autocomplete; export const getInspector = () => pluginsStart.inspector; export const getFileUploadComponent = async () => { - return await pluginsStart.mapsFileUpload.getFileUploadComponent(); + return await pluginsStart.fileUpload.getFileUploadComponent(); }; export const getUiSettings = () => coreStart.uiSettings; export const getIsDarkMode = () => getUiSettings().get('theme:darkMode', false); diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 4c668e0a2276b..12cff9edf55ff 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -54,7 +54,7 @@ import { EmbeddableStart } from '../../../../src/plugins/embeddable/public'; import { MapsLegacyConfig } from '../../../../src/plugins/maps_legacy/config'; import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; import { LicensingPluginSetup, LicensingPluginStart } from '../../licensing/public'; -import { StartContract as FileUploadStartContract } from '../../maps_file_upload/public'; +import { StartContract as FileUploadStartContract } from '../../file_upload/public'; import { SavedObjectsStart } from '../../../../src/plugins/saved_objects/public'; import { PresentationUtilPluginStart } from '../../../../src/plugins/presentation_util/public'; import { @@ -80,7 +80,7 @@ export interface MapsPluginStartDependencies { charts: ChartsPluginStart; data: DataPublicPluginStart; embeddable: EmbeddableStart; - mapsFileUpload: FileUploadStartContract; + fileUpload: FileUploadStartContract; inspector: InspectorStartContract; licensing: LicensingPluginStart; navigation: NavigationPublicPluginStart; diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.test.ts b/x-pack/plugins/maps/public/selectors/map_selectors.test.ts index dd6a9fc377e5b..c2f5fc02c5df2 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.test.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.test.ts @@ -5,10 +5,10 @@ * 2.0. */ -jest.mock('../classes/layers/vector_layer/vector_layer', () => {}); +jest.mock('../classes/layers/vector_layer', () => {}); jest.mock('../classes/layers/tiled_vector_layer/tiled_vector_layer', () => {}); jest.mock('../classes/layers/blended_vector_layer/blended_vector_layer', () => {}); -jest.mock('../classes/layers/heatmap_layer/heatmap_layer', () => {}); +jest.mock('../classes/layers/heatmap_layer', () => {}); jest.mock('../classes/layers/vector_tile_layer/vector_tile_layer', () => {}); jest.mock('../classes/joins/inner_join', () => {}); jest.mock('../kibana_services', () => ({ diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts index 27281fe17f0fa..f53f39ad2fc0c 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts @@ -12,10 +12,9 @@ import { Adapters } from 'src/plugins/inspector/public'; import { TileLayer } from '../classes/layers/tile_layer/tile_layer'; // @ts-ignore import { VectorTileLayer } from '../classes/layers/vector_tile_layer/vector_tile_layer'; -import { IVectorLayer, VectorLayer } from '../classes/layers/vector_layer/vector_layer'; +import { IVectorLayer, VectorLayer } from '../classes/layers/vector_layer'; import { VectorStyle } from '../classes/styles/vector/vector_style'; -// @ts-ignore -import { HeatmapLayer } from '../classes/layers/heatmap_layer/heatmap_layer'; +import { HeatmapLayer } from '../classes/layers/heatmap_layer'; import { BlendedVectorLayer } from '../classes/layers/blended_vector_layer/blended_vector_layer'; import { getTimeFilter } from '../kibana_services'; import { @@ -41,6 +40,7 @@ import { DataRequestDescriptor, DrawState, Goto, + HeatmapLayerDescriptor, LayerDescriptor, MapCenter, MapExtent, @@ -54,6 +54,7 @@ import { Filter, TimeRange } from '../../../../../src/plugins/data/public'; import { ISource } from '../classes/sources/source'; import { ITMSSource } from '../classes/sources/tms_source'; import { IVectorSource } from '../classes/sources/vector_source'; +import { ESGeoGridSource } from '../classes/sources/es_geo_grid_source'; import { ILayer } from '../classes/layers/layer'; export function createLayerInstance( @@ -84,7 +85,10 @@ export function createLayerInstance( case VectorTileLayer.type: return new VectorTileLayer({ layerDescriptor, source: source as ITMSSource }); case HeatmapLayer.type: - return new HeatmapLayer({ layerDescriptor, source }); + return new HeatmapLayer({ + layerDescriptor: layerDescriptor as HeatmapLayerDescriptor, + source: source as ESGeoGridSource, + }); case BlendedVectorLayer.type: return new BlendedVectorLayer({ layerDescriptor: layerDescriptor as VectorLayerDescriptor, diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index 7440b6ee1e1df..cb22a98b70aa8 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -177,6 +177,7 @@ export class MapsPlugin implements Plugin { catalogue: [APP_ID], privileges: { all: { + api: ['fileUpload:import'], app: [APP_ID, 'kibana'], catalogue: [APP_ID], savedObject: { diff --git a/x-pack/plugins/maps/tsconfig.json b/x-pack/plugins/maps/tsconfig.json index b70459c690c07..4a8bfe2ebae66 100644 --- a/x-pack/plugins/maps/tsconfig.json +++ b/x-pack/plugins/maps/tsconfig.json @@ -19,7 +19,7 @@ { "path": "../../../src/plugins/maps_legacy/tsconfig.json" }, { "path": "../features/tsconfig.json" }, { "path": "../licensing/tsconfig.json" }, - { "path": "../maps_file_upload/tsconfig.json" }, + { "path": "../file_upload/tsconfig.json" }, { "path": "../saved_objects_tagging/tsconfig.json" }, ] } diff --git a/x-pack/plugins/maps_file_upload/README.md b/x-pack/plugins/maps_file_upload/README.md deleted file mode 100644 index 1e3343664afb8..0000000000000 --- a/x-pack/plugins/maps_file_upload/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Maps File upload - -Deprecated - plugin targeted for removal and will get merged into file_upload plugin diff --git a/x-pack/plugins/maps_file_upload/common/constants/file_import.ts b/x-pack/plugins/maps_file_upload/common/constants/file_import.ts deleted file mode 100644 index 9e4763c2c8113..0000000000000 --- a/x-pack/plugins/maps_file_upload/common/constants/file_import.ts +++ /dev/null @@ -1,21 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export const MAX_BYTES = 31457280; - -export const MAX_FILE_SIZE = 52428800; - -// Value to use in the Elasticsearch index mapping metadata to identify the -// index as having been created by the File Upload Plugin. -export const INDEX_META_DATA_CREATED_BY = 'file-upload-plugin'; - -export const ES_GEO_FIELD_TYPE = { - GEO_POINT: 'geo_point', - GEO_SHAPE: 'geo_shape', -}; - -export const DEFAULT_KBN_VERSION = 'kbnVersion'; diff --git a/x-pack/plugins/maps_file_upload/jest.config.js b/x-pack/plugins/maps_file_upload/jest.config.js deleted file mode 100644 index e7b45a559df10..0000000000000 --- a/x-pack/plugins/maps_file_upload/jest.config.js +++ /dev/null @@ -1,12 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../..', - roots: ['/x-pack/plugins/maps_file_upload'], -}; diff --git a/x-pack/plugins/maps_file_upload/kibana.json b/x-pack/plugins/maps_file_upload/kibana.json deleted file mode 100644 index f544c56cba517..0000000000000 --- a/x-pack/plugins/maps_file_upload/kibana.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "mapsFileUpload", - "version": "8.0.0", - "kibanaVersion": "kibana", - "server": true, - "ui": true, - "requiredPlugins": ["data", "usageCollection"] -} diff --git a/x-pack/plugins/maps_file_upload/mappings.ts b/x-pack/plugins/maps_file_upload/mappings.ts deleted file mode 100644 index b8b263409f814..0000000000000 --- a/x-pack/plugins/maps_file_upload/mappings.ts +++ /dev/null @@ -1,16 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export const mappings = { - 'file-upload-telemetry': { - properties: { - filesUploadedTotalCount: { - type: 'long', - }, - }, - }, -}; diff --git a/x-pack/plugins/maps_file_upload/server/index.js b/x-pack/plugins/maps_file_upload/server/index.js deleted file mode 100644 index 4bf4e931c7eaa..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/index.js +++ /dev/null @@ -1,12 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FileUploadPlugin } from './plugin'; - -export * from './plugin'; - -export const plugin = () => new FileUploadPlugin(); diff --git a/x-pack/plugins/maps_file_upload/server/kibana_server_services.js b/x-pack/plugins/maps_file_upload/server/kibana_server_services.js deleted file mode 100644 index 8a1278f433ab9..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/kibana_server_services.js +++ /dev/null @@ -1,12 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -let internalRepository; -export const setInternalRepository = (createInternalRepository) => { - internalRepository = createInternalRepository(); -}; -export const getInternalRepository = () => internalRepository; diff --git a/x-pack/plugins/maps_file_upload/server/models/import_data/import_data.js b/x-pack/plugins/maps_file_upload/server/models/import_data/import_data.js deleted file mode 100644 index 7ba491a8ea49e..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/models/import_data/import_data.js +++ /dev/null @@ -1,161 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { INDEX_META_DATA_CREATED_BY } from '../../../common/constants/file_import'; -import uuid from 'uuid'; - -export function importDataProvider(callWithRequest) { - async function importData(id, index, settings, mappings, ingestPipeline, data) { - let createdIndex; - let createdPipelineId; - const docCount = data.length; - - try { - const { id: pipelineId, pipeline } = ingestPipeline; - - if (!id) { - // first chunk of data, create the index and id to return - id = uuid.v1(); - - await createIndex(index, settings, mappings); - createdIndex = index; - - // create the pipeline if one has been supplied - if (pipelineId !== undefined) { - const success = await createPipeline(pipelineId, pipeline); - if (success.acknowledged !== true) { - throw success; - } - } - createdPipelineId = pipelineId; - } else { - createdIndex = index; - createdPipelineId = pipelineId; - } - - let failures = []; - if (data.length) { - const resp = await indexData(index, createdPipelineId, data); - if (resp.success === false) { - if (resp.ingestError) { - // all docs failed, abort - throw resp; - } else { - // some docs failed. - // still report success but with a list of failures - failures = resp.failures || []; - } - } - } - - return { - success: true, - id, - index: createdIndex, - pipelineId: createdPipelineId, - docCount, - failures, - }; - } catch (error) { - return { - success: false, - id, - index: createdIndex, - pipelineId: createdPipelineId, - error: error.error !== undefined ? error.error : error, - docCount, - ingestError: error.ingestError, - failures: error.failures || [], - }; - } - } - - async function createIndex(index, settings, mappings) { - const body = { - mappings: { - _meta: { - created_by: INDEX_META_DATA_CREATED_BY, - }, - properties: mappings, - }, - }; - - if (settings && Object.keys(settings).length) { - body.settings = settings; - } - - await callWithRequest('indices.create', { index, body }); - } - - async function indexData(index, pipelineId, data) { - try { - const body = []; - for (let i = 0; i < data.length; i++) { - body.push({ index: {} }); - body.push(data[i]); - } - - const settings = { index, body }; - if (pipelineId !== undefined) { - settings.pipeline = pipelineId; - } - - const resp = await callWithRequest('bulk', settings); - if (resp.errors) { - throw resp; - } else { - return { - success: true, - docs: data.length, - failures: [], - }; - } - } catch (error) { - let failures = []; - let ingestError = false; - if (error.errors !== undefined && Array.isArray(error.items)) { - // an expected error where some or all of the bulk request - // docs have failed to be ingested. - failures = getFailures(error.items, data); - } else { - // some other error has happened. - ingestError = true; - } - - return { - success: false, - error, - docCount: data.length, - failures, - ingestError, - }; - } - } - - async function createPipeline(id, pipeline) { - return await callWithRequest('ingest.putPipeline', { id, body: pipeline }); - } - - function getFailures(items, data) { - const failures = []; - for (let i = 0; i < items.length; i++) { - const item = items[i]; - if (item.index && item.index.error) { - failures.push({ - item: i, - reason: item.index.error.reason, - doc: data[i], - }); - } - } - return failures; - } - - return { - importData, - }; -} diff --git a/x-pack/plugins/maps_file_upload/server/plugin.js b/x-pack/plugins/maps_file_upload/server/plugin.js deleted file mode 100644 index 1072da863acc7..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/plugin.js +++ /dev/null @@ -1,27 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { initRoutes } from './routes/file_upload'; -import { setInternalRepository } from './kibana_server_services'; -import { registerFileUploadUsageCollector, fileUploadTelemetryMappingsType } from './telemetry'; - -export class FileUploadPlugin { - constructor() { - this.router = null; - } - - setup(core, plugins) { - core.savedObjects.registerType(fileUploadTelemetryMappingsType); - this.router = core.http.createRouter(); - registerFileUploadUsageCollector(plugins.usageCollection); - } - - start(core) { - initRoutes(this.router, core.savedObjects.getSavedObjectsRepository); - setInternalRepository(core.savedObjects.createInternalRepository); - } -} diff --git a/x-pack/plugins/maps_file_upload/server/routes/file_upload.js b/x-pack/plugins/maps_file_upload/server/routes/file_upload.js deleted file mode 100644 index 1b617c44113a2..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/routes/file_upload.js +++ /dev/null @@ -1,130 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { importDataProvider } from '../models/import_data'; -import { updateTelemetry } from '../telemetry/telemetry'; -import { MAX_BYTES } from '../../common/constants/file_import'; -import { schema } from '@kbn/config-schema'; - -export const IMPORT_ROUTE = '/api/maps/fileupload/import'; - -export const querySchema = schema.maybe( - schema.object({ - id: schema.nullable(schema.string()), - }) -); - -export const bodySchema = schema.object( - { - app: schema.maybe(schema.string()), - index: schema.string(), - fileType: schema.string(), - ingestPipeline: schema.maybe( - schema.object( - {}, - { - defaultValue: {}, - unknowns: 'allow', - } - ) - ), - }, - { unknowns: 'allow' } -); - -const options = { - body: { - maxBytes: MAX_BYTES, - accepts: ['application/json'], - }, -}; - -export const idConditionalValidation = (body, boolHasId) => - schema - .object( - { - data: boolHasId - ? schema.arrayOf(schema.object({}, { unknowns: 'allow' }), { minSize: 1 }) - : schema.any(), - settings: boolHasId - ? schema.any() - : schema.object( - {}, - { - defaultValue: { - number_of_shards: 1, - }, - unknowns: 'allow', - } - ), - mappings: boolHasId - ? schema.any() - : schema.object( - {}, - { - defaultValue: {}, - unknowns: 'allow', - } - ), - }, - { unknowns: 'allow' } - ) - .validate(body); - -const finishValidationAndProcessReq = () => { - return async (con, req, { ok, badRequest }) => { - const { - query: { id }, - body, - } = req; - const boolHasId = !!id; - - let resp; - try { - const validIdReqData = idConditionalValidation(body, boolHasId); - const callWithRequest = con.core.elasticsearch.legacy.client.callAsCurrentUser; - const { importData: importDataFunc } = importDataProvider(callWithRequest); - - const { index, settings, mappings, ingestPipeline, data } = validIdReqData; - const processedReq = await importDataFunc( - id, - index, - settings, - mappings, - ingestPipeline, - data - ); - - if (processedReq.success) { - resp = ok({ body: processedReq }); - // If no id's been established then this is a new index, update telemetry - if (!boolHasId) { - await updateTelemetry(); - } - } else { - resp = badRequest(`Error processing request 1: ${processedReq.error.message}`, ['body']); - } - } catch (e) { - resp = badRequest(`Error processing request 2: : ${e.message}`, ['body']); - } - return resp; - }; -}; - -export const initRoutes = (router) => { - router.post( - { - path: `${IMPORT_ROUTE}{id?}`, - validate: { - query: querySchema, - body: bodySchema, - }, - options, - }, - finishValidationAndProcessReq() - ); -}; diff --git a/x-pack/plugins/maps_file_upload/server/routes/file_upload.test.js b/x-pack/plugins/maps_file_upload/server/routes/file_upload.test.js deleted file mode 100644 index e893e103aad72..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/routes/file_upload.test.js +++ /dev/null @@ -1,77 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { querySchema, bodySchema, idConditionalValidation } from './file_upload'; - -const queryWithId = { - id: '123', -}; - -const bodyWithoutQueryId = { - index: 'islandofone', - data: [], - settings: { number_of_shards: 1 }, - mappings: { coordinates: { type: 'geo_point' } }, - ingestPipeline: {}, - fileType: 'json', - app: 'Maps', -}; - -const bodyWithQueryId = { - index: 'islandofone2', - data: [{ coordinates: [], name: 'islandofone2' }], - settings: {}, - mappings: {}, - ingestPipeline: {}, - fileType: 'json', -}; - -describe('route validation', () => { - it(`validates query with id`, async () => { - const validationResult = querySchema.validate(queryWithId); - expect(validationResult.id).toBe(queryWithId.id); - }); - - it(`validates query without id`, async () => { - const validationResult = querySchema.validate({}); - expect(validationResult.id).toBeNull(); - }); - - it(`throws when query contains content other than an id`, async () => { - expect(() => querySchema.validate({ notAnId: 123 })).toThrowError( - `[notAnId]: definition for this key is missing` - ); - }); - - it(`validates body with valid fields`, async () => { - const validationResult = bodySchema.validate(bodyWithoutQueryId); - expect(validationResult).toEqual(bodyWithoutQueryId); - }); - - it(`throws if an expected field is missing`, async () => { - /* eslint-disable no-unused-vars */ - const { index, ...bodyWithoutIndexField } = bodyWithoutQueryId; - expect(() => bodySchema.validate(bodyWithoutIndexField)).toThrowError( - `[index]: expected value of type [string] but got [undefined]` - ); - }); - - it(`validates conditional fields when id has been provided in query`, async () => { - const validationResult = idConditionalValidation(bodyWithQueryId, true); - expect(validationResult).toEqual(bodyWithQueryId); - }); - - it(`validates conditional fields when no id has been provided in query`, async () => { - const validationResultWhenIdPresent = idConditionalValidation(bodyWithoutQueryId, false); - expect(validationResultWhenIdPresent).toEqual(bodyWithoutQueryId); - // Conditions for no id are more strict since this query sets up the index, - // expect it to throw if expected fields aren't present - expect(() => idConditionalValidation(bodyWithoutQueryId, true)).toThrowError( - `[data]: array size is [0], but cannot be smaller than [1]` - ); - }); -}); diff --git a/x-pack/plugins/maps_file_upload/server/telemetry/file_upload_usage_collector.ts b/x-pack/plugins/maps_file_upload/server/telemetry/file_upload_usage_collector.ts deleted file mode 100644 index bf786aa830448..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/telemetry/file_upload_usage_collector.ts +++ /dev/null @@ -1,29 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { getTelemetry, initTelemetry, Telemetry } from './telemetry'; - -export function registerFileUploadUsageCollector(usageCollection: UsageCollectionSetup): void { - const fileUploadUsageCollector = usageCollection.makeUsageCollector({ - type: 'fileUploadTelemetry', - isReady: () => true, - fetch: async () => { - const fileUploadUsage = await getTelemetry(); - if (!fileUploadUsage) { - return initTelemetry(); - } - - return fileUploadUsage; - }, - schema: { - filesUploadedTotalCount: { type: 'long' }, - }, - }); - - usageCollection.registerCollector(fileUploadUsageCollector); -} diff --git a/x-pack/plugins/maps_file_upload/server/telemetry/mappings.ts b/x-pack/plugins/maps_file_upload/server/telemetry/mappings.ts deleted file mode 100644 index ee79e2f6c6d47..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/telemetry/mappings.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { SavedObjectsType } from 'src/core/server'; -import { TELEMETRY_DOC_ID } from './telemetry'; - -export const fileUploadTelemetryMappingsType: SavedObjectsType = { - name: TELEMETRY_DOC_ID, - hidden: false, - namespaceType: 'agnostic', - mappings: { - properties: { - filesUploadedTotalCount: { - type: 'long', - }, - }, - }, -}; diff --git a/x-pack/plugins/maps_file_upload/server/telemetry/telemetry.test.ts b/x-pack/plugins/maps_file_upload/server/telemetry/telemetry.test.ts deleted file mode 100644 index 2ca01b03aa633..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/telemetry/telemetry.test.ts +++ /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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getTelemetry, updateTelemetry } from './telemetry'; - -const internalRepository = () => ({ - get: jest.fn(() => null), - create: jest.fn(() => ({ attributes: 'test' })), - update: jest.fn(() => ({ attributes: 'test' })), -}); - -function mockInit(getVal: any = { attributes: {} }): any { - return { - ...internalRepository(), - get: jest.fn(() => getVal), - }; -} - -describe('file upload plugin telemetry', () => { - describe('getTelemetry', () => { - it('should get existing telemetry', async () => { - const internalRepo = mockInit(); - await getTelemetry(internalRepo); - expect(internalRepo.update.mock.calls.length).toBe(0); - expect(internalRepo.get.mock.calls.length).toBe(1); - expect(internalRepo.create.mock.calls.length).toBe(0); - }); - }); - - describe('updateTelemetry', () => { - it('should update existing telemetry', async () => { - const internalRepo = mockInit({ - attributes: { - filesUploadedTotalCount: 2, - }, - }); - - await updateTelemetry(internalRepo); - expect(internalRepo.update.mock.calls.length).toBe(1); - expect(internalRepo.get.mock.calls.length).toBe(1); - expect(internalRepo.create.mock.calls.length).toBe(0); - }); - }); -}); diff --git a/x-pack/plugins/maps_file_upload/server/telemetry/telemetry.ts b/x-pack/plugins/maps_file_upload/server/telemetry/telemetry.ts deleted file mode 100644 index 0e53c2570e01b..0000000000000 --- a/x-pack/plugins/maps_file_upload/server/telemetry/telemetry.ts +++ /dev/null @@ -1,62 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import _ from 'lodash'; -// @ts-ignore -import { getInternalRepository } from '../kibana_server_services'; - -export const TELEMETRY_DOC_ID = 'file-upload-telemetry'; - -export interface Telemetry { - filesUploadedTotalCount: number; -} - -export interface TelemetrySavedObject { - attributes: Telemetry; -} - -export function initTelemetry(): Telemetry { - return { - filesUploadedTotalCount: 0, - }; -} - -export async function getTelemetry(internalRepo?: object): Promise { - const internalRepository = internalRepo || getInternalRepository(); - let telemetrySavedObject; - - try { - telemetrySavedObject = await internalRepository.get(TELEMETRY_DOC_ID, TELEMETRY_DOC_ID); - } catch (e) { - // Fail silently - } - - return telemetrySavedObject ? telemetrySavedObject.attributes : null; -} - -export async function updateTelemetry(internalRepo?: any) { - const internalRepository = internalRepo || getInternalRepository(); - let telemetry = await getTelemetry(internalRepository); - // Create if doesn't exist - if (!telemetry || _.isEmpty(telemetry)) { - const newTelemetrySavedObject = await internalRepository.create( - TELEMETRY_DOC_ID, - initTelemetry(), - { id: TELEMETRY_DOC_ID } - ); - telemetry = newTelemetrySavedObject.attributes; - } - - await internalRepository.update(TELEMETRY_DOC_ID, TELEMETRY_DOC_ID, incrementCounts(telemetry)); -} - -export function incrementCounts({ filesUploadedTotalCount }: { filesUploadedTotalCount: number }) { - return { - // TODO: get telemetry for app, total file counts, file type - filesUploadedTotalCount: filesUploadedTotalCount + 1, - }; -} diff --git a/x-pack/plugins/maps_file_upload/tsconfig.json b/x-pack/plugins/maps_file_upload/tsconfig.json deleted file mode 100644 index f068d62b71739..0000000000000 --- a/x-pack/plugins/maps_file_upload/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "composite": true, - "outDir": "./target/types", - "emitDeclarationOnly": true, - "declaration": true, - "declarationMap": true - }, - "include": ["common/**/*", "public/**/*", "server/**/*", "mappings.ts"], - "references": [ - { "path": "../../../src/plugins/data/tsconfig.json" }, - { "path": "../../../src/plugins/usage_collection/tsconfig.json" } - ] -} diff --git a/x-pack/plugins/ml/common/types/capabilities.ts b/x-pack/plugins/ml/common/types/capabilities.ts index eb7615c79a363..974a1f2243060 100644 --- a/x-pack/plugins/ml/common/types/capabilities.ts +++ b/x-pack/plugins/ml/common/types/capabilities.ts @@ -99,7 +99,7 @@ export function getPluginPrivileges() { return { admin: { ...privilege, - api: allMlCapabilitiesKeys.map((k) => `ml:${k}`), + api: ['fileUpload:import', ...allMlCapabilitiesKeys.map((k) => `ml:${k}`)], catalogue: [PLUGIN_ID, `${PLUGIN_ID}_file_data_visualizer`], ui: allMlCapabilitiesKeys, savedObject: { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx index 039a00afe52ee..ee66612de97ac 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx @@ -117,6 +117,10 @@ const getAnalyticsJobMeta = (config: CloneDataFrameAnalyticsConfig): AnalyticsJo optional: true, defaultValue: 'maximize_minimum_recall', }, + early_stopping_enabled: { + optional: true, + ignore: true, + }, }, } : {}), @@ -207,6 +211,10 @@ const getAnalyticsJobMeta = (config: CloneDataFrameAnalyticsConfig): AnalyticsJo loss_function_parameter: { optional: true, }, + early_stopping_enabled: { + optional: true, + ignore: true, + }, }, } : {}), diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts index 8de4470b028f5..a70962c45ffcb 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts @@ -56,6 +56,7 @@ export interface State { destinationIndexNameEmpty: boolean; destinationIndexNameValid: boolean; destinationIndexPatternTitleExists: boolean; + earlyStoppingEnabled: undefined | boolean; eta: undefined | number; featureBagFraction: undefined | number; featureInfluenceThreshold: undefined | number; @@ -125,6 +126,7 @@ export const getInitialState = (): State => ({ destinationIndexNameEmpty: true, destinationIndexNameValid: false, destinationIndexPatternTitleExists: false, + earlyStoppingEnabled: undefined, eta: undefined, featureBagFraction: undefined, featureInfluenceThreshold: undefined, @@ -239,7 +241,10 @@ export const getJobConfigFromFormState = ( formState.gamma && { gamma: formState.gamma }, formState.lambda && { lambda: formState.lambda }, formState.maxTrees && { max_trees: formState.maxTrees }, - formState.randomizeSeed && { randomize_seed: formState.randomizeSeed } + formState.randomizeSeed && { randomize_seed: formState.randomizeSeed }, + formState.earlyStoppingEnabled !== undefined && { + early_stopping_enabled: formState.earlyStoppingEnabled, + } ); jobConfig.analysis = { diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_error_callouts.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_error_callouts.tsx index 0535b15912a9b..0fa7de4732c39 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_error_callouts.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_error_callouts.tsx @@ -12,7 +12,7 @@ import { EuiCallOut, EuiSpacer, EuiButtonEmpty, EuiHorizontalRule } from '@elast import numeral from '@elastic/numeral'; import { ErrorResponse } from '../../../../../../common/types/errors'; -import { FILE_SIZE_DISPLAY_FORMAT } from '../../../../../../../file_upload/common'; +import { FILE_SIZE_DISPLAY_FORMAT } from '../../../../../../../file_upload/public'; interface FileTooLargeProps { fileSize: number; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts index 47f262ef45a18..4412390d62c1f 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts @@ -15,7 +15,7 @@ import { MAX_FILE_SIZE_BYTES, ABSOLUTE_MAX_FILE_SIZE_BYTES, FILE_SIZE_DISPLAY_FORMAT, -} from '../../../../../../../file_upload/common'; +} from '../../../../../../../file_upload/public'; import { getUiSettings } from '../../../../util/dependency_cache'; import { FILE_DATA_VISUALIZER_MAX_FILE_SIZE } from '../../../../../../common/constants/settings'; diff --git a/x-pack/plugins/monitoring/server/es_client/monitoring_endpoint_disable_watches.ts b/x-pack/plugins/monitoring/server/es_client/monitoring_endpoint_disable_watches.ts index 454379d17848e..8e9e8d916e496 100644 --- a/x-pack/plugins/monitoring/server/es_client/monitoring_endpoint_disable_watches.ts +++ b/x-pack/plugins/monitoring/server/es_client/monitoring_endpoint_disable_watches.ts @@ -13,7 +13,7 @@ export function monitoringEndpointDisableWatches(Client: any, _config: any, comp params: {}, urls: [ { - fmt: '_monitoring/migrate/alerts', + fmt: '/_monitoring/migrate/alerts', }, ], method: 'POST', diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/verify_alerting_security.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch/verify_alerting_security.ts index c81b9632f0cd7..facb6e29236e3 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/verify_alerting_security.ts +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/verify_alerting_security.ts @@ -44,7 +44,7 @@ export class AlertingSecurity { return { isSufficientlySecure: !isSecurityEnabled || (isSecurityEnabled && isTLSEnabled), - hasPermanentEncryptionKey: Boolean(encryptedSavedObjects), + hasPermanentEncryptionKey: encryptedSavedObjects?.canEncrypt === true, }; }; } diff --git a/x-pack/plugins/remote_clusters/server/routes/api/add_route.test.ts b/x-pack/plugins/remote_clusters/server/routes/api/add_route.test.ts index 066a2d56cbeec..9348fd1eb20df 100644 --- a/x-pack/plugins/remote_clusters/server/routes/api/add_route.test.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/add_route.test.ts @@ -10,13 +10,26 @@ import { register } from './add_route'; import { API_BASE_PATH } from '../../../common/constants'; import { LicenseStatus } from '../../types'; -import { xpackMocks } from '../../../../../mocks'; +import { licensingMock } from '../../../../../plugins/licensing/server/mocks'; + import { elasticsearchServiceMock, httpServerMock, httpServiceMock, + coreMock, } from '../../../../../../src/core/server/mocks'; +// Re-implement the mock that was imported directly from `x-pack/mocks` +function createCoreRequestHandlerContextMock() { + return { + core: coreMock.createRequestHandlerContext(), + licensing: licensingMock.createRequestHandlerContext(), + }; +} + +const xpackMocks = { + createRequestHandlerContext: createCoreRequestHandlerContextMock, +}; interface TestOptions { licenseCheckResult?: LicenseStatus; apiResponses?: Array<() => Promise>; diff --git a/x-pack/plugins/remote_clusters/server/routes/api/delete_route.test.ts b/x-pack/plugins/remote_clusters/server/routes/api/delete_route.test.ts index 29d846314bd9b..ce94f45bb8443 100644 --- a/x-pack/plugins/remote_clusters/server/routes/api/delete_route.test.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/delete_route.test.ts @@ -10,13 +10,26 @@ import { register } from './delete_route'; import { API_BASE_PATH } from '../../../common/constants'; import { LicenseStatus } from '../../types'; -import { xpackMocks } from '../../../../../mocks'; +import { licensingMock } from '../../../../../plugins/licensing/server/mocks'; + import { elasticsearchServiceMock, httpServerMock, httpServiceMock, + coreMock, } from '../../../../../../src/core/server/mocks'; +// Re-implement the mock that was imported directly from `x-pack/mocks` +function createCoreRequestHandlerContextMock() { + return { + core: coreMock.createRequestHandlerContext(), + licensing: licensingMock.createRequestHandlerContext(), + }; +} + +const xpackMocks = { + createRequestHandlerContext: createCoreRequestHandlerContextMock, +}; interface TestOptions { licenseCheckResult?: LicenseStatus; apiResponses?: Array<() => Promise>; diff --git a/x-pack/plugins/remote_clusters/server/routes/api/get_route.test.ts b/x-pack/plugins/remote_clusters/server/routes/api/get_route.test.ts index 33a3142ddc105..25d17d796b0ee 100644 --- a/x-pack/plugins/remote_clusters/server/routes/api/get_route.test.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/get_route.test.ts @@ -12,13 +12,26 @@ import { register } from './get_route'; import { API_BASE_PATH } from '../../../common/constants'; import { LicenseStatus } from '../../types'; -import { xpackMocks } from '../../../../../mocks'; +import { licensingMock } from '../../../../../plugins/licensing/server/mocks'; + import { elasticsearchServiceMock, httpServerMock, httpServiceMock, + coreMock, } from '../../../../../../src/core/server/mocks'; +// Re-implement the mock that was imported directly from `x-pack/mocks` +function createCoreRequestHandlerContextMock() { + return { + core: coreMock.createRequestHandlerContext(), + licensing: licensingMock.createRequestHandlerContext(), + }; +} + +const xpackMocks = { + createRequestHandlerContext: createCoreRequestHandlerContextMock, +}; interface TestOptions { licenseCheckResult?: LicenseStatus; apiResponses?: Array<() => Promise>; diff --git a/x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts b/x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts index 31db362f7c953..22c87786a585c 100644 --- a/x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts @@ -10,13 +10,26 @@ import { register } from './update_route'; import { API_BASE_PATH } from '../../../common/constants'; import { LicenseStatus } from '../../types'; -import { xpackMocks } from '../../../../../mocks'; +import { licensingMock } from '../../../../../plugins/licensing/server/mocks'; + import { elasticsearchServiceMock, httpServerMock, httpServiceMock, + coreMock, } from '../../../../../../src/core/server/mocks'; +// Re-implement the mock that was imported directly from `x-pack/mocks` +function createCoreRequestHandlerContextMock() { + return { + core: coreMock.createRequestHandlerContext(), + licensing: licensingMock.createRequestHandlerContext(), + }; +} + +const xpackMocks = { + createRequestHandlerContext: createCoreRequestHandlerContextMock, +}; interface TestOptions { licenseCheckResult?: LicenseStatus; apiResponses?: Array<() => Promise>; diff --git a/x-pack/plugins/remote_clusters/tsconfig.json b/x-pack/plugins/remote_clusters/tsconfig.json new file mode 100644 index 0000000000000..0bee6300cf0b2 --- /dev/null +++ b/x-pack/plugins/remote_clusters/tsconfig.json @@ -0,0 +1,30 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "fixtures/**/*", + "public/**/*", + "server/**/*", + ], + "references": [ + { "path": "../../../src/core/tsconfig.json" }, + // required plugins + { "path": "../licensing/tsconfig.json" }, + { "path": "../../../src/plugins/management/tsconfig.json" }, + { "path": "../index_management/tsconfig.json" }, + { "path": "../features/tsconfig.json" }, + // optional plugins + { "path": "../../../src/plugins/usage_collection/tsconfig.json" }, + { "path": "../cloud/tsconfig.json" }, + // required bundles + { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, + { "path": "../../../src/plugins/es_ui_shared/tsconfig.json" }, + ] +} diff --git a/x-pack/plugins/rollup/tsconfig.json b/x-pack/plugins/rollup/tsconfig.json new file mode 100644 index 0000000000000..9b994d1710ffc --- /dev/null +++ b/x-pack/plugins/rollup/tsconfig.json @@ -0,0 +1,35 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "fixtures/**/*", + "public/**/*", + "server/**/*", + ], + "references": [ + { "path": "../../../src/core/tsconfig.json" }, + // required plugins + { "path": "../../../src/plugins/index_pattern_management/tsconfig.json" }, + { "path": "../../../src/plugins/management/tsconfig.json" }, + { "path": "../licensing/tsconfig.json" }, + { "path": "../features/tsconfig.json" }, + // optional plugins + { "path": "../../../src/plugins/home/tsconfig.json" }, + { "path": "../index_management/tsconfig.json" }, + { "path": "../../../src/plugins/usage_collection/tsconfig.json" }, + { "path": "../../../src/plugins/vis_type_timeseries/tsconfig.json" }, + // required bundles + { "path": "../../../src/plugins/kibana_utils/tsconfig.json" }, + { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, + { "path": "../../../src/plugins/es_ui_shared/tsconfig.json" }, + { "path": "../../../src/plugins/data/tsconfig.json" }, + + ] +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts index 3ee3c6884a3ec..2efb65c4a49a2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts @@ -18,7 +18,7 @@ describe('read_privileges route', () => { ({ clients, context } = requestContextMock.createTools()); clients.clusterClient.callAsCurrentUser.mockResolvedValue(getMockPrivilegesResult()); - readPrivilegesRoute(server.router, false); + readPrivilegesRoute(server.router, true); }); describe('normal status codes', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.ts index a934f0a0ce134..f006d9250d369 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.ts @@ -14,7 +14,7 @@ import { readPrivileges } from '../../privileges/read_privileges'; export const readPrivilegesRoute = ( router: SecuritySolutionPluginRouter, - usingEphemeralEncryptionKey: boolean + hasEncryptionKey: boolean ) => { router.get( { @@ -39,7 +39,7 @@ export const readPrivilegesRoute = ( const clusterPrivileges = await readPrivileges(clusterClient.callAsCurrentUser, index); const privileges = merge(clusterPrivileges, { is_authenticated: request.auth.isAuthenticated ?? false, - has_encryption_key: !usingEphemeralEncryptionKey, + has_encryption_key: hasEncryptionKey, }); return response.ok({ body: privileges }); diff --git a/x-pack/plugins/security_solution/server/lib/machine_learning/index.test.ts b/x-pack/plugins/security_solution/server/lib/machine_learning/index.test.ts index 86133d93e99c8..1f49ac7bf5019 100644 --- a/x-pack/plugins/security_solution/server/lib/machine_learning/index.test.ts +++ b/x-pack/plugins/security_solution/server/lib/machine_learning/index.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ESFilter } from '../../../../../typings/elasticsearch'; import { getExceptionListItemSchemaMock } from '../../../../lists/common/schemas/response/exception_list_item_schema.mock'; import { getAnomalies, AnomaliesSearchParams } from '.'; @@ -13,8 +14,8 @@ const getFiltersFromMock = (mock: jest.Mock) => { return searchParams.body.query.bool.filter; }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const getBoolCriteriaFromFilters = (filters: any[]) => filters[1].bool.must; +const getBoolCriteriaFromFilters = (filters: ESFilter[]) => + filters.find((filter) => filter?.bool?.must)?.bool?.must; describe('getAnomalies', () => { let searchParams: AnomaliesSearchParams; @@ -104,4 +105,20 @@ describe('getAnomalies', () => { ]) ); }); + + it('ignores anomalies that do not have finalized scores', () => { + const mockMlAnomalySearch = jest.fn(); + getAnomalies(searchParams, mockMlAnomalySearch); + const filters = getFiltersFromMock(mockMlAnomalySearch); + + expect(filters).toEqual( + expect.arrayContaining([ + { + term: { + is_interim: false, + }, + }, + ]) + ); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/machine_learning/index.ts b/x-pack/plugins/security_solution/server/lib/machine_learning/index.ts index 962c44174d891..c3fea9f6d916f 100644 --- a/x-pack/plugins/security_solution/server/lib/machine_learning/index.ts +++ b/x-pack/plugins/security_solution/server/lib/machine_learning/index.ts @@ -47,6 +47,7 @@ export const getAnomalies = async ( analyze_wildcard: false, }, }, + { term: { is_interim: false } }, { bool: { must: boolCriteria, diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 8c35fd2ce8f8b..a34193937c788 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -183,7 +183,7 @@ export class Plugin implements IPlugin { @@ -102,5 +102,5 @@ export const initRoutes = ( readTagsRoute(router); // Privileges API to get the generic user privileges - readPrivilegesRoute(router, usingEphemeralEncryptionKey); + readPrivilegesRoute(router, hasEncryptionKey); }; diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx index 0a9f94f8efae2..27ddb28eed779 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx @@ -126,6 +126,7 @@ describe('EsQueryAlertTypeExpression', () => { index: ['test-index'], timeField: '@timestamp', esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, thresholdComparator: '>', threshold: [0], timeWindowSize: 15, @@ -137,6 +138,7 @@ describe('EsQueryAlertTypeExpression', () => { const errors = { index: [], esQuery: [], + size: [], timeField: [], timeWindowSize: [], }; @@ -169,6 +171,7 @@ describe('EsQueryAlertTypeExpression', () => { test('should render EsQueryAlertTypeExpression with expected components', async () => { const wrapper = await setup(getAlertParams()); expect(wrapper.find('[data-test-subj="indexSelectPopover"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="sizeValueExpression"]').exists()).toBeTruthy(); expect(wrapper.find('[data-test-subj="queryJsonEditor"]').exists()).toBeTruthy(); expect(wrapper.find('[data-test-subj="testQuerySuccess"]').exists()).toBeFalsy(); expect(wrapper.find('[data-test-subj="testQueryError"]').exists()).toBeFalsy(); diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx index 27f8071564c55..37c64688ec49a 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx @@ -30,6 +30,7 @@ import { COMPARATORS, ThresholdExpression, ForLastExpression, + ValueExpression, AlertTypeParamsExpressionProps, } from '../../../../triggers_actions_ui/public'; import { validateExpression } from './validation'; @@ -45,6 +46,7 @@ const DEFAULT_VALUES = { "match_all" : {} } }`, + SIZE: 100, TIME_WINDOW_SIZE: 5, TIME_WINDOW_UNIT: 'm', THRESHOLD: [1000], @@ -53,6 +55,7 @@ const DEFAULT_VALUES = { const expressionFieldsWithValidation = [ 'index', 'esQuery', + 'size', 'timeField', 'threshold0', 'threshold1', @@ -74,6 +77,7 @@ export const EsQueryAlertTypeExpression: React.FunctionComponent< index, timeField, esQuery, + size, thresholdComparator, threshold, timeWindowSize, @@ -83,6 +87,7 @@ export const EsQueryAlertTypeExpression: React.FunctionComponent< const getDefaultParams = () => ({ ...alertParams, esQuery: esQuery ?? DEFAULT_VALUES.QUERY, + size: size ?? DEFAULT_VALUES.SIZE, timeWindowSize: timeWindowSize ?? DEFAULT_VALUES.TIME_WINDOW_SIZE, timeWindowUnit: timeWindowUnit ?? DEFAULT_VALUES.TIME_WINDOW_UNIT, threshold: threshold ?? DEFAULT_VALUES.THRESHOLD, @@ -214,7 +219,7 @@ export const EsQueryAlertTypeExpression: React.FunctionComponent<
@@ -234,6 +239,7 @@ export const EsQueryAlertTypeExpression: React.FunctionComponent< ...alertParams, index: indices, esQuery: DEFAULT_VALUES.QUERY, + size: DEFAULT_VALUES.SIZE, thresholdComparator: DEFAULT_VALUES.THRESHOLD_COMPARATOR, timeWindowSize: DEFAULT_VALUES.TIME_WINDOW_SIZE, timeWindowUnit: DEFAULT_VALUES.TIME_WINDOW_UNIT, @@ -246,6 +252,19 @@ export const EsQueryAlertTypeExpression: React.FunctionComponent< }} onTimeFieldChange={(updatedTimeField: string) => setParam('timeField', updatedTimeField)} /> + { + setParam('size', updatedValue); + }} + />
diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/types.ts b/x-pack/plugins/stack_alerts/public/alert_types/es_query/types.ts index a22af7a7bc8a5..af34b88ba28c5 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/types.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/types.ts @@ -17,6 +17,7 @@ export interface EsQueryAlertParams extends AlertTypeParams { index: string[]; timeField?: string; esQuery: string; + size: number; thresholdComparator?: string; threshold: number[]; timeWindowSize: number; diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/validation.test.ts b/x-pack/plugins/stack_alerts/public/alert_types/es_query/validation.test.ts index 7d604e964fb9d..52278b4576557 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/validation.test.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/validation.test.ts @@ -13,6 +13,7 @@ describe('expression params validation', () => { const initialParams: EsQueryAlertParams = { index: [], esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, timeWindowSize: 1, timeWindowUnit: 's', threshold: [0], @@ -25,6 +26,7 @@ describe('expression params validation', () => { const initialParams: EsQueryAlertParams = { index: ['test'], esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, timeWindowSize: 1, timeWindowUnit: 's', threshold: [0], @@ -37,6 +39,7 @@ describe('expression params validation', () => { const initialParams: EsQueryAlertParams = { index: ['test'], esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n`, + size: 100, timeWindowSize: 1, timeWindowUnit: 's', threshold: [0], @@ -49,6 +52,7 @@ describe('expression params validation', () => { const initialParams: EsQueryAlertParams = { index: ['test'], esQuery: `{\n \"aggs\":{\n \"match_all\" : {}\n }\n}`, + size: 100, timeWindowSize: 1, timeWindowUnit: 's', threshold: [0], @@ -61,6 +65,7 @@ describe('expression params validation', () => { const initialParams: EsQueryAlertParams = { index: ['test'], esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, threshold: [], timeWindowSize: 1, timeWindowUnit: 's', @@ -74,6 +79,7 @@ describe('expression params validation', () => { const initialParams: EsQueryAlertParams = { index: ['test'], esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, threshold: [1], timeWindowSize: 1, timeWindowUnit: 's', @@ -87,6 +93,7 @@ describe('expression params validation', () => { const initialParams: EsQueryAlertParams = { index: ['test'], esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, threshold: [10, 1], timeWindowSize: 1, timeWindowUnit: 's', @@ -97,4 +104,34 @@ describe('expression params validation', () => { 'Threshold 1 must be > Threshold 0.' ); }); + + test('if size property is < 0 should return proper error message', () => { + const initialParams: EsQueryAlertParams = { + index: ['test'], + esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n`, + size: -1, + timeWindowSize: 1, + timeWindowUnit: 's', + threshold: [0], + }; + expect(validateExpression(initialParams).errors.size.length).toBeGreaterThan(0); + expect(validateExpression(initialParams).errors.size[0]).toBe( + 'Size must be between 0 and 10,000.' + ); + }); + + test('if size property is > 10000 should return proper error message', () => { + const initialParams: EsQueryAlertParams = { + index: ['test'], + esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n`, + size: 25000, + timeWindowSize: 1, + timeWindowUnit: 's', + threshold: [0], + }; + expect(validateExpression(initialParams).errors.size.length).toBeGreaterThan(0); + expect(validateExpression(initialParams).errors.size[0]).toBe( + 'Size must be between 0 and 10,000.' + ); + }); }); diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/validation.ts b/x-pack/plugins/stack_alerts/public/alert_types/es_query/validation.ts index 8b402d63ae565..e6449dd4a6089 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/validation.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/validation.ts @@ -10,12 +10,21 @@ import { EsQueryAlertParams } from './types'; import { ValidationResult, builtInComparators } from '../../../../triggers_actions_ui/public'; export const validateExpression = (alertParams: EsQueryAlertParams): ValidationResult => { - const { index, timeField, esQuery, threshold, timeWindowSize, thresholdComparator } = alertParams; + const { + index, + timeField, + esQuery, + size, + threshold, + timeWindowSize, + thresholdComparator, + } = alertParams; const validationResult = { errors: {} }; const errors = { index: new Array(), timeField: new Array(), esQuery: new Array(), + size: new Array(), threshold0: new Array(), threshold1: new Array(), thresholdComparator: new Array(), @@ -94,5 +103,20 @@ export const validateExpression = (alertParams: EsQueryAlertParams): ValidationR }) ); } + if (!size) { + errors.size.push( + i18n.translate('xpack.stackAlerts.esQuery.ui.validation.error.requiredSizeText', { + defaultMessage: 'Size is required.', + }) + ); + } + if ((size && size < 0) || size > 10000) { + errors.size.push( + i18n.translate('xpack.stackAlerts.esQuery.ui.validation.error.invalidSizeRangeText', { + defaultMessage: 'Size must be between 0 and {max, number}.', + values: { max: 10000 }, + }) + ); + } return validationResult; }; diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/action_context.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/action_context.test.ts index d4b2029c11579..9d4edd83a3913 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/action_context.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/action_context.test.ts @@ -14,6 +14,7 @@ describe('ActionContext', () => { index: ['[index]'], timeField: '[timeField]', esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, timeWindowSize: 5, timeWindowUnit: 'm', thresholdComparator: '>', @@ -41,6 +42,7 @@ describe('ActionContext', () => { index: ['[index]'], timeField: '[timeField]', esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, timeWindowSize: 5, timeWindowUnit: 'm', thresholdComparator: 'between', diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts index 2049f9f1153dd..c38dad5134373 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts @@ -57,6 +57,10 @@ describe('alertType', () => { "description": "The string representation of the ES query.", "name": "esQuery", }, + Object { + "description": "The number of hits to retrieve for each query.", + "name": "size", + }, Object { "description": "An array of values to use as the threshold; 'between' and 'notBetween' require two values, the others require one.", "name": "threshold", @@ -75,6 +79,7 @@ describe('alertType', () => { index: ['index-name'], timeField: 'time-field', esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, timeWindowSize: 5, timeWindowUnit: 'm', thresholdComparator: '<', @@ -92,6 +97,7 @@ describe('alertType', () => { index: ['index-name'], timeField: 'time-field', esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, timeWindowSize: 5, timeWindowUnit: 'm', thresholdComparator: 'between', diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.ts index 51c1fc4073d60..8fe988d95d72f 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.ts @@ -23,8 +23,6 @@ import { ESSearchHit } from '../../../../../typings/elasticsearch'; export const ES_QUERY_ID = '.es-query'; -const DEFAULT_MAX_HITS_PER_EXECUTION = 1000; - const ActionGroupId = 'query matched'; const ConditionMetAlertInstanceId = 'query matched'; @@ -88,6 +86,13 @@ export function getAlertType( } ); + const actionVariableContextSizeLabel = i18n.translate( + 'xpack.stackAlerts.esQuery.actionVariableContextSizeLabel', + { + defaultMessage: 'The number of hits to retrieve for each query.', + } + ); + const actionVariableContextThresholdLabel = i18n.translate( 'xpack.stackAlerts.esQuery.actionVariableContextThresholdLabel', { @@ -130,6 +135,7 @@ export function getAlertType( params: [ { name: 'index', description: actionVariableContextIndexLabel }, { name: 'esQuery', description: actionVariableContextQueryLabel }, + { name: 'size', description: actionVariableContextSizeLabel }, { name: 'threshold', description: actionVariableContextThresholdLabel }, { name: 'thresholdComparator', description: actionVariableContextThresholdComparatorLabel }, ], @@ -160,7 +166,7 @@ export function getAlertType( } // During each alert execution, we run the configured query, get a hit count - // (hits.total) and retrieve up to DEFAULT_MAX_HITS_PER_EXECUTION hits. We + // (hits.total) and retrieve up to params.size hits. We // evaluate the threshold condition using the value of hits.total. If the threshold // condition is met, the hits are counted toward the query match and we update // the alert state with the timestamp of the latest hit. In the next execution @@ -200,7 +206,7 @@ export function getAlertType( from: dateStart, to: dateEnd, filter, - size: DEFAULT_MAX_HITS_PER_EXECUTION, + size: params.size, sortOrder: 'desc', searchAfterSortId: undefined, timeField: params.timeField, diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type_params.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type_params.test.ts index a1a697446ff65..ab3ca6a2d4c31 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type_params.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type_params.test.ts @@ -7,12 +7,17 @@ import { TypeOf } from '@kbn/config-schema'; import type { Writable } from '@kbn/utility-types'; -import { EsQueryAlertParamsSchema, EsQueryAlertParams } from './alert_type_params'; +import { + EsQueryAlertParamsSchema, + EsQueryAlertParams, + ES_QUERY_MAX_HITS_PER_EXECUTION, +} from './alert_type_params'; const DefaultParams: Writable> = { index: ['index-name'], timeField: 'time-field', esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, timeWindowSize: 5, timeWindowUnit: 'm', thresholdComparator: '>', @@ -99,6 +104,28 @@ describe('alertType Params validate()', () => { ); }); + it('fails for invalid size', async () => { + delete params.size; + expect(onValidate()).toThrowErrorMatchingInlineSnapshot( + `"[size]: expected value of type [number] but got [undefined]"` + ); + + params.size = 'foo'; + expect(onValidate()).toThrowErrorMatchingInlineSnapshot( + `"[size]: expected value of type [number] but got [string]"` + ); + + params.size = -1; + expect(onValidate()).toThrowErrorMatchingInlineSnapshot( + `"[size]: Value must be equal to or greater than [0]."` + ); + + params.size = ES_QUERY_MAX_HITS_PER_EXECUTION + 1; + expect(onValidate()).toThrowErrorMatchingInlineSnapshot( + `"[size]: Value must be equal to or lower than [10000]."` + ); + }); + it('fails for invalid timeWindowSize', async () => { delete params.timeWindowSize; expect(onValidate()).toThrowErrorMatchingInlineSnapshot( diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type_params.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type_params.ts index 24fed92776b53..23f314b521511 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type_params.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type_params.ts @@ -11,6 +11,8 @@ import { ComparatorFnNames } from '../lib'; import { validateTimeWindowUnits } from '../../../../triggers_actions_ui/server'; import { AlertTypeState } from '../../../../alerts/server'; +export const ES_QUERY_MAX_HITS_PER_EXECUTION = 10000; + // alert type parameters export type EsQueryAlertParams = TypeOf; export interface EsQueryAlertState extends AlertTypeState { @@ -21,6 +23,7 @@ export const EsQueryAlertParamsSchemaProperties = { index: schema.arrayOf(schema.string({ minLength: 1 }), { minSize: 1 }), timeField: schema.string({ minLength: 1 }), esQuery: schema.string({ minLength: 1 }), + size: schema.number({ min: 0, max: ES_QUERY_MAX_HITS_PER_EXECUTION }), timeWindowSize: schema.number({ min: 1 }), timeWindowUnit: schema.string({ validate: validateTimeWindowUnits }), threshold: schema.arrayOf(schema.number(), { minSize: 1, maxSize: 2 }), diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 9e6a0c06808bc..d4b07203e8109 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -2219,13 +2219,6 @@ } } }, - "fileUploadTelemetry": { - "properties": { - "filesUploadedTotalCount": { - "type": "long" - } - } - }, "maps": { "properties": { "settings": { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 278294dea9449..018d2d572eea0 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9676,7 +9676,6 @@ "xpack.infra.alerting.alertFlyout.groupBy.placeholder": "なし(グループなし)", "xpack.infra.alerting.alertFlyout.groupByLabel": "グループ分けの条件", "xpack.infra.alerting.alertsButton": "アラート", - "xpack.infra.alerting.createAlertButton": "アラートの作成", "xpack.infra.alerting.logs.alertsButton": "アラート", "xpack.infra.alerting.logs.createAlertButton": "アラートの作成", "xpack.infra.alerting.logs.manageAlerts": "アラートを管理", @@ -9970,16 +9969,6 @@ "xpack.infra.logs.jumpToTailText": "最も新しいエントリーに移動", "xpack.infra.logs.lastUpdate": "前回の更新 {timestamp}", "xpack.infra.logs.loadingNewEntriesText": "新しいエントリーを読み込み中", - "xpack.infra.logs.logAnalysis.splash.learnMoreLink": "ドキュメンテーションを表示", - "xpack.infra.logs.logAnalysis.splash.learnMoreTitle": "詳細について", - "xpack.infra.logs.logAnalysis.splash.loadingMessage": "ライセンスを確認しています...", - "xpack.infra.logs.logAnalysis.splash.splashImageAlt": "プレースホルダー画像", - "xpack.infra.logs.logAnalysis.splash.startTrialCta": "トライアルを開始", - "xpack.infra.logs.logAnalysis.splash.startTrialDescription": "無料の試用版には、機械学習機能が含まれており、ログで異常を検出することができます。", - "xpack.infra.logs.logAnalysis.splash.startTrialTitle": "異常検知を利用するには、無料の試用版を開始してください", - "xpack.infra.logs.logAnalysis.splash.updateSubscriptionCta": "サブスクリプションのアップグレード", - "xpack.infra.logs.logAnalysis.splash.updateSubscriptionDescription": "機械学習機能を使用するには、プラチナサブスクリプションが必要です。", - "xpack.infra.logs.logAnalysis.splash.updateSubscriptionTitle": "異常検知を利用するには、プラチナサブスクリプションにアップグレードしてください", "xpack.infra.logs.logEntryActionsDetailsButton": "詳細を表示", "xpack.infra.logs.logEntryCategories.analyzeCategoryInMlButtonLabel": "ML で分析", "xpack.infra.logs.logEntryCategories.analyzeCategoryInMlTooltipDescription": "ML アプリでこのカテゴリーを分析します。", @@ -10175,10 +10164,6 @@ "xpack.infra.metrics.alertFlyout.alertPreviewError": "このアラート条件をプレビューするときにエラーが発生しました", "xpack.infra.metrics.alertFlyout.alertPreviewErrorDesc": "しばらくたってから再試行するか、詳細を確認してください。", "xpack.infra.metrics.alertFlyout.alertPreviewErrorResult": "一部のデータを評価するときにエラーが発生しました。", - "xpack.infra.metrics.alertFlyout.alertPreviewGroupsAcross": "すべてを対象にする", - "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResult": "データなしの件数:{boldedResultsNumber}", - "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResultNumber": "{noData, plural, other {件の結果がありました}}", - "xpack.infra.metrics.alertFlyout.alertPreviewResult": "{firedTimes} 回発生しました", "xpack.infra.metrics.alertFlyout.alertPreviewTotalNotifications": "結果として、このアラートは、「{alertThrottle}」に関して選択した[通知間隔]設定に基づいて{notifications}を送信しました。", "xpack.infra.metrics.alertFlyout.alertPreviewTotalNotificationsNumber": "{notifs, plural, other {#通知}}", "xpack.infra.metrics.alertFlyout.conditions": "条件", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 4704cb07d27b0..5a9695b8ddc3d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9702,7 +9702,6 @@ "xpack.infra.alerting.alertFlyout.groupBy.placeholder": "无内容(未分组)", "xpack.infra.alerting.alertFlyout.groupByLabel": "分组依据", "xpack.infra.alerting.alertsButton": "告警", - "xpack.infra.alerting.createAlertButton": "创建告警", "xpack.infra.alerting.logs.alertsButton": "告警", "xpack.infra.alerting.logs.createAlertButton": "创建告警", "xpack.infra.alerting.logs.manageAlerts": "管理告警", @@ -9997,16 +9996,6 @@ "xpack.infra.logs.jumpToTailText": "跳到最近的条目", "xpack.infra.logs.lastUpdate": "上次更新时间 {timestamp}", "xpack.infra.logs.loadingNewEntriesText": "正在加载新条目", - "xpack.infra.logs.logAnalysis.splash.learnMoreLink": "阅读文档", - "xpack.infra.logs.logAnalysis.splash.learnMoreTitle": "希望了解详情?", - "xpack.infra.logs.logAnalysis.splash.loadingMessage": "正在检查许可证......", - "xpack.infra.logs.logAnalysis.splash.splashImageAlt": "占位符图像", - "xpack.infra.logs.logAnalysis.splash.startTrialCta": "开始试用", - "xpack.infra.logs.logAnalysis.splash.startTrialDescription": "我们的免费试用版包含 Machine Learning 功能,可用于检测日志中的异常。", - "xpack.infra.logs.logAnalysis.splash.startTrialTitle": "要访问异常检测,请启动免费试用版", - "xpack.infra.logs.logAnalysis.splash.updateSubscriptionCta": "升级订阅", - "xpack.infra.logs.logAnalysis.splash.updateSubscriptionDescription": "必须具有白金级订阅,才能使用 Machine Learning 功能。", - "xpack.infra.logs.logAnalysis.splash.updateSubscriptionTitle": "要访问异常检测,请升级到白金级订阅", "xpack.infra.logs.logEntryActionsDetailsButton": "查看详情", "xpack.infra.logs.logEntryCategories.analyzeCategoryInMlButtonLabel": "在 ML 中分析", "xpack.infra.logs.logEntryCategories.analyzeCategoryInMlTooltipDescription": "在 ML 应用中分析此类别。", @@ -10202,12 +10191,7 @@ "xpack.infra.metrics.alertFlyout.alertPreviewError": "尝试预览此告警条件时发生错误", "xpack.infra.metrics.alertFlyout.alertPreviewErrorDesc": "请稍后重试或查看详情了解更多信息。", "xpack.infra.metrics.alertFlyout.alertPreviewErrorResult": "尝试评估部分数据时发生错误。", - "xpack.infra.metrics.alertFlyout.alertPreviewGroups": "{numberOfGroups, plural,other {# 个 {groupName}}}", - "xpack.infra.metrics.alertFlyout.alertPreviewGroupsAcross": "在", - "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResult": "存在 {boldedResultsNumber}无数据结果。", - "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResultNumber": "{noData, plural, other {# 个结果}}", - "xpack.infra.metrics.alertFlyout.alertPreviewResult": "有 {firedTimes}", - "xpack.infra.metrics.alertFlyout.alertPreviewResultLookback": "在过去 {lookback} 满足此告警的条件。", + "xpack.infra.metrics.alertFlyout.alertPreviewGroups": "在 {numberOfGroups, plural,other {# 个 {groupName}}}", "xpack.infra.metrics.alertFlyout.alertPreviewTotalNotifications": "因此,此告警将根据“{alertThrottle}”的选定“通知频率”设置发送{notifications}。", "xpack.infra.metrics.alertFlyout.alertPreviewTotalNotificationsNumber": "{notifs, plural, other {# 个通知}}", "xpack.infra.metrics.alertFlyout.conditions": "条件", diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/index.ts b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/index.ts index bfcbba28b4bda..f975375adcb07 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/index.ts @@ -10,3 +10,4 @@ export { OfExpression } from './of'; export { GroupByExpression } from './group_by_over'; export { ThresholdExpression } from './threshold'; export { ForLastExpression } from './for_the_last'; +export { ValueExpression } from './value'; diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/value.test.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/value.test.tsx new file mode 100644 index 0000000000000..e9a3dce84e149 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/value.test.tsx @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as React from 'react'; +import { shallow } from 'enzyme'; +import { act } from 'react-dom/test-utils'; +import { ValueExpression } from './value'; +import { mountWithIntl, nextTick } from '@kbn/test/jest'; + +describe('value expression', () => { + it('renders description and value', () => { + const wrapper = shallow( + + ); + expect(wrapper.find('[data-test-subj="valueFieldTitle"]')).toMatchInlineSnapshot(` + + test + + `); + expect(wrapper.find('[data-test-subj="valueFieldNumberForm"]')).toMatchInlineSnapshot(` + + + + `); + }); + + it('renders errors', () => { + const wrapper = shallow( + + ); + expect(wrapper.find('[data-test-subj="valueFieldNumberForm"]')).toMatchInlineSnapshot(` + + + + `); + }); + + it('renders closed popover initially and opens on click', async () => { + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find('[data-test-subj="valueExpression"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="valueFieldTitle"]').exists()).toBeFalsy(); + expect(wrapper.find('[data-test-subj="valueFieldNumber"]').exists()).toBeFalsy(); + + wrapper.find('[data-test-subj="valueExpression"]').first().simulate('click'); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="valueFieldTitle"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="valueFieldNumber"]').exists()).toBeTruthy(); + }); + + it('emits onChangeSelectedValue action when value is updated', async () => { + const onChangeSelectedValue = jest.fn(); + const wrapper = mountWithIntl( + + ); + + wrapper.find('[data-test-subj="valueExpression"]').first().simulate('click'); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + wrapper + .find('input[data-test-subj="valueFieldNumber"]') + .simulate('change', { target: { value: 3000 } }); + expect(onChangeSelectedValue).toHaveBeenCalledWith(3000); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/value.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/value.tsx new file mode 100644 index 0000000000000..cdf57136fe4b2 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/value.tsx @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { + EuiExpression, + EuiPopover, + EuiFieldNumber, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, +} from '@elastic/eui'; +import { ClosablePopoverTitle } from './components'; +import { IErrorObject } from '../../types'; + +interface ValueExpressionProps { + description: string; + value: number; + onChangeSelectedValue: (updatedValue: number) => void; + popupPosition?: + | 'upCenter' + | 'upLeft' + | 'upRight' + | 'downCenter' + | 'downLeft' + | 'downRight' + | 'leftCenter' + | 'leftUp' + | 'leftDown' + | 'rightCenter' + | 'rightUp' + | 'rightDown'; + display?: 'fullWidth' | 'inline'; + errors: string | string[] | IErrorObject; +} + +export const ValueExpression = ({ + description, + value, + onChangeSelectedValue, + display = 'inline', + popupPosition, + errors, +}: ValueExpressionProps) => { + const [valuePopoverOpen, setValuePopoverOpen] = useState(false); + return ( + { + setValuePopoverOpen(true); + }} + /> + } + isOpen={valuePopoverOpen} + closePopover={() => { + setValuePopoverOpen(false); + }} + ownFocus + display={display === 'fullWidth' ? 'block' : 'inlineBlock'} + anchorPosition={popupPosition ?? 'downLeft'} + repositionOnScroll + > +
+ setValuePopoverOpen(false)} + > + <>{description} + + + + 0 && value !== undefined} + error={errors} + > + 0 && value !== undefined} + onChange={(e: any) => { + onChangeSelectedValue(e.target.value as number); + }} + /> + + + +
+
+ ); +}; diff --git a/x-pack/plugins/uptime/public/apps/plugin.ts b/x-pack/plugins/uptime/public/apps/plugin.ts index 8bbbecf8108fe..e7a22a080d79a 100644 --- a/x-pack/plugins/uptime/public/apps/plugin.ts +++ b/x-pack/plugins/uptime/public/apps/plugin.ts @@ -87,6 +87,28 @@ export class UptimePlugin order: 8400, title: PLUGIN.TITLE, category: DEFAULT_APP_CATEGORIES.observability, + meta: { + keywords: [ + 'Synthetics', + 'pings', + 'checks', + 'availability', + 'response duration', + 'response time', + 'outside in', + 'reachability', + 'reachable', + 'digital', + 'performance', + 'web performance', + 'web perf', + ], + searchDeepLinks: [ + { id: 'Down monitors', title: 'Down monitors', path: '/?statusFilter=down' }, + { id: 'Certificates', title: 'TLS Certificates', path: '/certificates' }, + { id: 'Settings', title: 'Settings', path: '/settings' }, + ], + }, mount: async (params: AppMountParameters) => { const [coreStart, corePlugins] = await core.getStartServices(); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/alert.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/alert.ts index 30fd3aea2b2dc..777caacd465d8 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/alert.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/alert.ts @@ -68,6 +68,7 @@ export default function alertTests({ getService }: FtrProviderContext) { await createAlert({ name: 'never fire', esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, thresholdComparator: '<', threshold: [0], }); @@ -75,6 +76,7 @@ export default function alertTests({ getService }: FtrProviderContext) { await createAlert({ name: 'always fire', esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + size: 100, thresholdComparator: '>', threshold: [-1], }); @@ -123,6 +125,7 @@ export default function alertTests({ getService }: FtrProviderContext) { await createAlert({ name: 'never fire', esQuery: JSON.stringify(rangeQuery(ES_GROUPS_TO_WRITE * ALERT_INTERVALS_TO_WRITE + 1)), + size: 100, thresholdComparator: '>=', threshold: [0], }); @@ -132,6 +135,7 @@ export default function alertTests({ getService }: FtrProviderContext) { esQuery: JSON.stringify( rangeQuery(Math.floor((ES_GROUPS_TO_WRITE * ALERT_INTERVALS_TO_WRITE) / 2)) ), + size: 100, thresholdComparator: '>=', threshold: [0], }); @@ -173,6 +177,7 @@ export default function alertTests({ getService }: FtrProviderContext) { name: string; timeField?: string; esQuery: string; + size: number; thresholdComparator: string; threshold: number[]; timeWindowSize?: number; @@ -215,6 +220,7 @@ export default function alertTests({ getService }: FtrProviderContext) { index: [ES_TEST_INDEX_NAME], timeField: params.timeField || 'date', esQuery: params.esQuery, + size: params.size, timeWindowSize: params.timeWindowSize || ALERT_INTERVAL_SECONDS * 5, timeWindowUnit: 's', thresholdComparator: params.thresholdComparator, diff --git a/x-pack/test/api_integration/apis/metrics_ui/sources.ts b/x-pack/test/api_integration/apis/metrics_ui/sources.ts index 7fb631477cb76..a5bab8de92f38 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/sources.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/sources.ts @@ -17,11 +17,12 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); + const SOURCE_API_URL = '/api/metrics/source/default'; const patchRequest = async ( body: InfraSavedSourceConfiguration ): Promise => { const response = await supertest - .patch('/api/metrics/source/default') + .patch(SOURCE_API_URL) .set('kbn-xsrf', 'xxx') .send(body) .expect(200); @@ -73,6 +74,7 @@ export default function ({ getService }: FtrProviderContext) { expect(configuration?.fields.timestamp).to.be('@timestamp'); expect(configuration?.fields.container).to.be('container.id'); expect(configuration?.logColumns).to.have.length(3); + expect(configuration?.anomalyThreshold).to.be(50); expect(status?.logIndicesExist).to.be(true); expect(status?.metricIndicesExist).to.be(true); }); @@ -173,6 +175,31 @@ export default function ({ getService }: FtrProviderContext) { expect(fieldColumn).to.have.property('id', 'ADDED_COLUMN_ID'); expect(fieldColumn).to.have.property('field', 'ADDED_COLUMN_FIELD'); }); + it('validates anomalyThreshold is between range 1-100', async () => { + // create config with bad request + await supertest + .patch(SOURCE_API_URL) + .set('kbn-xsrf', 'xxx') + .send({ name: 'NAME', anomalyThreshold: -20 }) + .expect(400); + // create config with good request + await supertest + .patch(SOURCE_API_URL) + .set('kbn-xsrf', 'xxx') + .send({ name: 'NAME', anomalyThreshold: 20 }) + .expect(200); + + await supertest + .patch(SOURCE_API_URL) + .set('kbn-xsrf', 'xxx') + .send({ anomalyThreshold: -2 }) + .expect(400); + await supertest + .patch(SOURCE_API_URL) + .set('kbn-xsrf', 'xxx') + .send({ anomalyThreshold: 101 }) + .expect(400); + }); }); }); } diff --git a/x-pack/test/api_integration/apis/security_solution/users.ts b/x-pack/test/api_integration/apis/security_solution/users.ts index 45e06ab72adbb..b888be2bf6276 100644 --- a/x-pack/test/api_integration/apis/security_solution/users.ts +++ b/x-pack/test/api_integration/apis/security_solution/users.ts @@ -23,6 +23,7 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); // Failing: See https://github.com/elastic/kibana/issues/90135 + // Failing: See https://github.com/elastic/kibana/issues/90136 describe.skip('Users', () => { describe('With auditbeat', () => { before(() => esArchiver.load('auditbeat/default')); diff --git a/x-pack/test/api_integration/apis/telemetry/telemetry_local.js b/x-pack/test/api_integration/apis/telemetry/telemetry_local.js index 9a6602ef923d3..3be24b273ae4c 100644 --- a/x-pack/test/api_integration/apis/telemetry/telemetry_local.js +++ b/x-pack/test/api_integration/apis/telemetry/telemetry_local.js @@ -83,7 +83,7 @@ export default function ({ getService }) { expect(stats.stack_stats.kibana.plugins.reporting.enabled).to.be(true); expect(stats.stack_stats.kibana.plugins.rollups.index_patterns).to.be.an('object'); expect(stats.stack_stats.kibana.plugins.spaces.available).to.be(true); - expect(stats.stack_stats.kibana.plugins.fileUploadTelemetry.filesUploadedTotalCount).to.be.a( + expect(stats.stack_stats.kibana.plugins.fileUpload.file_upload.index_creation_count).to.be.a( 'number' ); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/roles_users_utils/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/roles_users_utils/index.ts index 1d3e5244a59ed..9e84ad0a547aa 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/roles_users_utils/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/roles_users_utils/index.ts @@ -6,6 +6,7 @@ */ import { assertUnreachable } from '../../../../plugins/security_solution/common/utility_types'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; import { t1AnalystUser, t2AnalystUser, @@ -26,10 +27,9 @@ import { } from '../../../../plugins/security_solution/server/lib/detection_engine/scripts/roles_users'; import { ROLES } from '../../../../plugins/security_solution/common/test'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; export const createUserAndRole = async ( - securityService: ReturnType, + getService: FtrProviderContext['getService'], role: ROLES ): Promise => { switch (role) { @@ -38,32 +38,47 @@ export const createUserAndRole = async ( ROLES.detections_admin, detectionsAdminRole, detectionsAdminUser, - securityService + getService ); case ROLES.t1_analyst: - return postRoleAndUser(ROLES.t1_analyst, t1AnalystRole, t1AnalystUser, securityService); + return postRoleAndUser(ROLES.t1_analyst, t1AnalystRole, t1AnalystUser, getService); case ROLES.t2_analyst: - return postRoleAndUser(ROLES.t2_analyst, t2AnalystRole, t2AnalystUser, securityService); + return postRoleAndUser(ROLES.t2_analyst, t2AnalystRole, t2AnalystUser, getService); case ROLES.hunter: - return postRoleAndUser(ROLES.hunter, hunterRole, hunterUser, securityService); + return postRoleAndUser(ROLES.hunter, hunterRole, hunterUser, getService); case ROLES.rule_author: - return postRoleAndUser(ROLES.rule_author, ruleAuthorRole, ruleAuthorUser, securityService); + return postRoleAndUser(ROLES.rule_author, ruleAuthorRole, ruleAuthorUser, getService); case ROLES.soc_manager: - return postRoleAndUser(ROLES.soc_manager, socManagerRole, socManagerUser, securityService); + return postRoleAndUser(ROLES.soc_manager, socManagerRole, socManagerUser, getService); case ROLES.platform_engineer: return postRoleAndUser( ROLES.platform_engineer, platformEngineerRole, platformEngineerUser, - securityService + getService ); case ROLES.reader: - return postRoleAndUser(ROLES.reader, readerRole, readerUser, securityService); + return postRoleAndUser(ROLES.reader, readerRole, readerUser, getService); default: return assertUnreachable(role); } }; +/** + * Given a roleName and security service this will delete the roleName + * and user + * @param roleName The user and role to delete with the same name + * @param securityService The security service + */ +export const deleteUserAndRole = async ( + getService: FtrProviderContext['getService'], + roleName: ROLES +): Promise => { + const securityService = getService('security'); + await securityService.user.delete(roleName); + await securityService.role.delete(roleName); +}; + interface UserInterface { password: string; roles: string[]; @@ -95,8 +110,9 @@ export const postRoleAndUser = async ( roleName: string, role: RoleInterface, user: UserInterface, - securityService: ReturnType -) => { + getService: FtrProviderContext['getService'] +): Promise => { + const securityService = getService('security'); await securityService.role.create(roleName, { kibana: role.kibana, elasticsearch: role.elasticsearch, diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_index.ts index c2822b8638d76..a319c30fa20de 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_index.ts @@ -14,16 +14,14 @@ import { import { FtrProviderContext } from '../../common/ftr_provider_context'; import { deleteSignalsIndex } from '../../utils'; import { ROLES } from '../../../../plugins/security_solution/common/test'; -import { createUserAndRole } from '../roles_users_utils'; +import { createUserAndRole, deleteUserAndRole } from '../roles_users_utils'; // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - const security = getService('security'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/90229 - describe.skip('create_index', () => { + describe('create_index', () => { afterEach(async () => { await deleteSignalsIndex(supertest); }); @@ -66,8 +64,13 @@ export default ({ getService }: FtrProviderContext) => { describe('t1_analyst', () => { const role = ROLES.t1_analyst; + beforeEach(async () => { - await createUserAndRole(security, role); + await createUserAndRole(getService, role); + }); + + afterEach(async () => { + await deleteUserAndRole(getService, role); }); it('should return a 404 when the signal index has never been created', async () => { @@ -88,7 +91,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(403); expect(body).to.eql({ message: - 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [t1_analyst], this action is granted by the privileges [read_ilm,manage_ilm,manage,all]', + 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [t1_analyst], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]', status_code: 403, }); }); @@ -111,8 +114,13 @@ export default ({ getService }: FtrProviderContext) => { describe('t2_analyst', () => { const role = ROLES.t2_analyst; + beforeEach(async () => { - await createUserAndRole(security, role); + await createUserAndRole(getService, role); + }); + + afterEach(async () => { + await deleteUserAndRole(getService, role); }); it('should return a 404 when the signal index has never been created', async () => { @@ -133,7 +141,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(403); expect(body).to.eql({ message: - 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [t2_analyst], this action is granted by the privileges [read_ilm,manage_ilm,manage,all]', + 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [t2_analyst], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]', status_code: 403, }); }); @@ -156,8 +164,13 @@ export default ({ getService }: FtrProviderContext) => { describe('detections_admin', () => { const role = ROLES.detections_admin; + beforeEach(async () => { - await createUserAndRole(security, role); + await createUserAndRole(getService, role); + }); + + afterEach(async () => { + await deleteUserAndRole(getService, role); }); it('should return a 404 when the signal index has never been created', async () => { @@ -201,8 +214,13 @@ export default ({ getService }: FtrProviderContext) => { describe('soc_manager', () => { const role = ROLES.soc_manager; + beforeEach(async () => { - await createUserAndRole(security, role); + await createUserAndRole(getService, role); + }); + + afterEach(async () => { + await deleteUserAndRole(getService, role); }); it('should return a 404 when the signal index has never been created', async () => { @@ -223,7 +241,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(403); expect(body).to.eql({ message: - 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [soc_manager], this action is granted by the privileges [read_ilm,manage_ilm,manage,all]', + 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [soc_manager], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]', status_code: 403, }); }); @@ -246,8 +264,13 @@ export default ({ getService }: FtrProviderContext) => { describe('hunter', () => { const role = ROLES.hunter; + beforeEach(async () => { - await createUserAndRole(security, role); + await createUserAndRole(getService, role); + }); + + afterEach(async () => { + await deleteUserAndRole(getService, role); }); it('should return a 404 when the signal index has never been created', async () => { @@ -268,7 +291,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(403); expect(body).to.eql({ message: - 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [hunter], this action is granted by the privileges [read_ilm,manage_ilm,manage,all]', + 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [hunter], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]', status_code: 403, }); }); @@ -291,8 +314,13 @@ export default ({ getService }: FtrProviderContext) => { describe('platform_engineer', () => { const role = ROLES.platform_engineer; + beforeEach(async () => { - await createUserAndRole(security, role); + await createUserAndRole(getService, role); + }); + + afterEach(async () => { + await deleteUserAndRole(getService, role); }); it('should return a 404 when the signal index has never been created', async () => { @@ -336,8 +364,13 @@ export default ({ getService }: FtrProviderContext) => { describe('reader', () => { const role = ROLES.reader; + beforeEach(async () => { - await createUserAndRole(security, role); + await createUserAndRole(getService, role); + }); + + afterEach(async () => { + await deleteUserAndRole(getService, role); }); it('should return a 404 when the signal index has never been created', async () => { @@ -358,7 +391,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(403); expect(body).to.eql({ message: - 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [reader], this action is granted by the privileges [read_ilm,manage_ilm,manage,all]', + 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [reader], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]', status_code: 403, }); }); @@ -381,8 +414,13 @@ export default ({ getService }: FtrProviderContext) => { describe('rule_author', () => { const role = ROLES.rule_author; + beforeEach(async () => { - await createUserAndRole(security, role); + await createUserAndRole(getService, role); + }); + + afterEach(async () => { + await deleteUserAndRole(getService, role); }); it('should return a 404 when the signal index has never been created', async () => { @@ -403,7 +441,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(403); expect(body).to.eql({ message: - 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [rule_author], this action is granted by the privileges [read_ilm,manage_ilm,manage,all]', + 'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [rule_author], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]', status_code: 403, }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts index fc77fba5fa339..dd0052b03382a 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts @@ -21,7 +21,7 @@ import { getIndexNameFromLoad, waitForIndexToPopulate, } from '../../utils'; -import { createUserAndRole } from '../roles_users_utils'; +import { createUserAndRole, deleteUserAndRole } from '../roles_users_utils'; interface CreateResponse { index: string; @@ -34,7 +34,6 @@ export default ({ getService }: FtrProviderContext): void => { const es = getService('es'); const esArchiver = getService('esArchiver'); const kbnClient = getService('kibanaServer'); - const security = getService('security'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); @@ -173,7 +172,7 @@ export default ({ getService }: FtrProviderContext): void => { }); it('rejects the request if the user does not have sufficient privileges', async () => { - await createUserAndRole(security, ROLES.t1_analyst); + await createUserAndRole(getService, ROLES.t1_analyst); await supertestWithoutAuth .post(DETECTION_ENGINE_SIGNALS_MIGRATION_URL) @@ -181,6 +180,8 @@ export default ({ getService }: FtrProviderContext): void => { .auth(ROLES.t1_analyst, 'changeme') .send({ index: [legacySignalsIndexName] }) .expect(400); + + await deleteUserAndRole(getService, ROLES.t1_analyst); }); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts index 234370e4f104e..bba6ce1125c37 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts @@ -32,12 +32,10 @@ interface FinalizeResponse extends CreateResponse { export default ({ getService }: FtrProviderContext): void => { const es = getService('es'); const esArchiver = getService('esArchiver'); - const security = getService('security'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/90229 - describe.skip('deleting signals migrations', () => { + describe('deleting signals migrations', () => { let outdatedSignalsIndexName: string; let createdMigration: CreateResponse; let finalizedMigration: FinalizeResponse; @@ -105,7 +103,7 @@ export default ({ getService }: FtrProviderContext): void => { }); it('rejects the request if the user does not have sufficient privileges', async () => { - await createUserAndRole(security, ROLES.t1_analyst); + await createUserAndRole(getService, ROLES.t1_analyst); const { body } = await supertestWithoutAuth .delete(DETECTION_ENGINE_SIGNALS_MIGRATION_URL) @@ -119,7 +117,7 @@ export default ({ getService }: FtrProviderContext): void => { expect(deletedMigration.id).to.eql(createdMigration.migration_id); expect(deletedMigration.error).to.eql({ message: - 'security_exception: action [indices:admin/settings/update] is unauthorized for user [t1_analyst] on indices [], this action is granted by the privileges [manage,all]', + 'security_exception: action [indices:admin/settings/update] is unauthorized for user [t1_analyst] on indices [], this action is granted by the index privileges [manage,all]', status_code: 403, }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/finalize_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/finalize_signals_migrations.ts index 64c0c6666469a..0fd05904d5e33 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/finalize_signals_migrations.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/finalize_signals_migrations.ts @@ -21,7 +21,7 @@ import { getIndexNameFromLoad, waitFor, } from '../../utils'; -import { createUserAndRole } from '../roles_users_utils'; +import { createUserAndRole, deleteUserAndRole } from '../roles_users_utils'; interface StatusResponse { index: string; @@ -44,12 +44,10 @@ interface FinalizeResponse { export default ({ getService }: FtrProviderContext): void => { const esArchiver = getService('esArchiver'); const kbnClient = getService('kibanaServer'); - const security = getService('security'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/88302 - describe.skip('Finalizing signals migrations', () => { + describe('Finalizing signals migrations', () => { let legacySignalsIndexName: string; let outdatedSignalsIndexName: string; let createdMigrations: CreateResponse[]; @@ -234,7 +232,7 @@ export default ({ getService }: FtrProviderContext): void => { }); it('rejects the request if the user does not have sufficient privileges', async () => { - await createUserAndRole(security, ROLES.t1_analyst); + await createUserAndRole(getService, ROLES.t1_analyst); const { body } = await supertestWithoutAuth .post(DETECTION_ENGINE_SIGNALS_FINALIZE_MIGRATION_URL) @@ -249,9 +247,11 @@ export default ({ getService }: FtrProviderContext): void => { expect(finalizeResponse.completed).not.to.eql(true); expect(finalizeResponse.error).to.eql({ message: - 'security_exception: action [cluster:monitor/task/get] is unauthorized for user [t1_analyst]', + 'security_exception: action [cluster:monitor/task/get] is unauthorized for user [t1_analyst], this action is granted by the cluster privileges [monitor,manage,all]', status_code: 403, }); + + await deleteUserAndRole(getService, ROLES.t1_analyst); }); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_signals_migration_status.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_signals_migration_status.ts index 3b9ec8e0909dc..793dec9eaae4b 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_signals_migration_status.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_signals_migration_status.ts @@ -11,12 +11,11 @@ import { DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL } from '../../../../plugi import { ROLES } from '../../../../plugins/security_solution/common/test'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createSignalsIndex, deleteSignalsIndex, getIndexNameFromLoad } from '../../utils'; -import { createUserAndRole } from '../roles_users_utils'; +import { createUserAndRole, deleteUserAndRole } from '../roles_users_utils'; // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext): void => { const esArchiver = getService('esArchiver'); - const security = getService('security'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); @@ -99,7 +98,7 @@ export default ({ getService }: FtrProviderContext): void => { }); it('rejects the request if the user does not have sufficient privileges', async () => { - await createUserAndRole(security, ROLES.t1_analyst); + await createUserAndRole(getService, ROLES.t1_analyst); await supertestWithoutAuth .get(DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL) @@ -107,6 +106,8 @@ export default ({ getService }: FtrProviderContext): void => { .auth(ROLES.t1_analyst, 'changeme') .query({ from: '2020-10-10' }) .expect(403); + + await deleteUserAndRole(getService, ROLES.t1_analyst); }); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts index 973b643a7a425..36a05f0ae8c0e 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts @@ -27,7 +27,7 @@ import { waitForRuleSuccessOrStatus, getRuleForSignalTesting, } from '../../utils'; -import { createUserAndRole } from '../roles_users_utils'; +import { createUserAndRole, deleteUserAndRole } from '../roles_users_utils'; import { ROLES } from '../../../../plugins/security_solution/common/test'; // eslint-disable-next-line import/no-default-export @@ -35,7 +35,6 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - const securityService = getService('security'); describe('open_close_signals', () => { describe('validation checks', () => { @@ -172,7 +171,7 @@ export default ({ getService }: FtrProviderContext) => { const { id } = await createRule(supertest, rule); await waitForRuleSuccessOrStatus(supertest, id); await waitForSignalsToBePresent(supertest, 1, [id]); - await createUserAndRole(securityService, ROLES.t1_analyst); + await createUserAndRole(getService, ROLES.t1_analyst); const signalsOpen = await getSignalsByIds(supertest, [id]); const signalIds = signalsOpen.hits.hits.map((signal) => signal._id); @@ -203,6 +202,8 @@ export default ({ getService }: FtrProviderContext) => { }) => status === 'closed' ); expect(everySignalOpen).to.eql(true); + + await deleteUserAndRole(getService, ROLES.t1_analyst); }); it('should be able to close signals with soc_manager user', async () => { @@ -211,7 +212,7 @@ export default ({ getService }: FtrProviderContext) => { await waitForRuleSuccessOrStatus(supertest, id); await waitForSignalsToBePresent(supertest, 1, [id]); const userAndRole = ROLES.soc_manager; - await createUserAndRole(securityService, userAndRole); + await createUserAndRole(getService, userAndRole); const signalsOpen = await getSignalsByIds(supertest, [id]); const signalIds = signalsOpen.hits.hits.map((signal) => signal._id); @@ -240,6 +241,8 @@ export default ({ getService }: FtrProviderContext) => { }) => status === 'closed' ); expect(everySignalClosed).to.eql(true); + + await deleteUserAndRole(getService, userAndRole); }); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/read_privileges.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/read_privileges.ts index 614f08295b38f..f8949daea831e 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/read_privileges.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/read_privileges.ts @@ -10,14 +10,14 @@ import { DETECTION_ENGINE_PRIVILEGES_URL } from '../../../../plugins/security_so import { FtrProviderContext } from '../../common/ftr_provider_context'; import { ROLES } from '../../../../plugins/security_solution/common/test'; +import { createUserAndRole, deleteUserAndRole } from '../roles_users_utils'; // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/90229 - describe.skip('read_privileges', () => { + describe('read_privileges', () => { it('should return expected privileges for elastic admin', async () => { const { body } = await supertest.get(DETECTION_ENGINE_PRIVILEGES_URL).send().expect(200); expect(body).to.eql({ @@ -78,6 +78,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return expected privileges for a "reader" user', async () => { + await createUserAndRole(getService, ROLES.reader); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.reader, 'changeme') @@ -138,9 +139,11 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); + await deleteUserAndRole(getService, ROLES.reader); }); it('should return expected privileges for a "t1_analyst" user', async () => { + await createUserAndRole(getService, ROLES.t1_analyst); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.t1_analyst, 'changeme') @@ -201,9 +204,11 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); + await deleteUserAndRole(getService, ROLES.t1_analyst); }); it('should return expected privileges for a "t2_analyst" user', async () => { + await createUserAndRole(getService, ROLES.t2_analyst); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.t2_analyst, 'changeme') @@ -264,9 +269,11 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); + await deleteUserAndRole(getService, ROLES.t2_analyst); }); it('should return expected privileges for a "hunter" user', async () => { + await createUserAndRole(getService, ROLES.hunter); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.hunter, 'changeme') @@ -327,9 +334,11 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); + await deleteUserAndRole(getService, ROLES.hunter); }); it('should return expected privileges for a "rule_author" user', async () => { + await createUserAndRole(getService, ROLES.rule_author); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.rule_author, 'changeme') @@ -390,9 +399,11 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); + await deleteUserAndRole(getService, ROLES.rule_author); }); it('should return expected privileges for a "soc_manager" user', async () => { + await createUserAndRole(getService, ROLES.soc_manager); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.soc_manager, 'changeme') @@ -453,9 +464,11 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); + await deleteUserAndRole(getService, ROLES.soc_manager); }); it('should return expected privileges for a "platform_engineer" user', async () => { + await createUserAndRole(getService, ROLES.platform_engineer); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.platform_engineer, 'changeme') @@ -516,9 +529,11 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); + await deleteUserAndRole(getService, ROLES.platform_engineer); }); it('should return expected privileges for a "detections_admin" user', async () => { + await createUserAndRole(getService, ROLES.detections_admin); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.detections_admin, 'changeme') @@ -579,6 +594,7 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); + await deleteUserAndRole(getService, ROLES.detections_admin); }); }); }; diff --git a/x-pack/test/functional/apps/index_management/home_page.ts b/x-pack/test/functional/apps/index_management/home_page.ts index 9fbe5373dd3d4..f8f852b9667fb 100644 --- a/x-pack/test/functional/apps/index_management/home_page.ts +++ b/x-pack/test/functional/apps/index_management/home_page.ts @@ -13,6 +13,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects(['common', 'indexManagement', 'header']); const log = getService('log'); const browser = getService('browser'); + const retry = getService('retry'); describe('Home page', function () { before(async () => { @@ -49,8 +50,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(url).to.contain(`/data_streams`); // Verify content - const dataStreamList = await testSubjects.exists('dataStreamList'); - expect(dataStreamList).to.be(true); + await retry.waitFor('Wait until dataStream Table is visible.', async () => { + return await testSubjects.isDisplayed('dataStreamTable'); + }); }); }); diff --git a/x-pack/test/functional/apps/lens/drag_and_drop.ts b/x-pack/test/functional/apps/lens/drag_and_drop.ts index 5b3a984f00519..a272b67de1b0a 100644 --- a/x-pack/test/functional/apps/lens/drag_and_drop.ts +++ b/x-pack/test/functional/apps/lens/drag_and_drop.ts @@ -143,6 +143,7 @@ export default function ({ getPageObjects }: FtrProviderContext) { expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_xDimensionPanel')).to.eql( '@timestamp' ); + await PageObjects.lens.assertFocusedField('@timestamp'); }); it('should drop a field to empty dimension', async () => { await PageObjects.lens.dragFieldWithKeyboard('bytes', 4); @@ -154,12 +155,15 @@ export default function ({ getPageObjects }: FtrProviderContext) { expect( await PageObjects.lens.getDimensionTriggersTexts('lnsXY_splitDimensionPanel') ).to.eql(['Top values of @message.raw']); + await PageObjects.lens.assertFocusedField('@message.raw'); }); it('should drop a field to an existing dimension replacing the old one', async () => { await PageObjects.lens.dragFieldWithKeyboard('clientip', 1, true); expect( await PageObjects.lens.getDimensionTriggersTexts('lnsXY_splitDimensionPanel') ).to.eql(['Top values of clientip']); + + await PageObjects.lens.assertFocusedField('clientip'); }); it('should duplicate an element in a group', async () => { await PageObjects.lens.dimensionKeyboardDragDrop('lnsXY_yDimensionPanel', 0, 1); @@ -168,6 +172,8 @@ export default function ({ getPageObjects }: FtrProviderContext) { 'Average of bytes', 'Count of records [1]', ]); + + await PageObjects.lens.assertFocusedDimension('Count of records [1]'); }); it('should move dimension to compatible dimension', async () => { @@ -186,6 +192,7 @@ export default function ({ getPageObjects }: FtrProviderContext) { expect( await PageObjects.lens.getDimensionTriggersTexts('lnsXY_splitDimensionPanel') ).to.eql([]); + await PageObjects.lens.assertFocusedDimension('@timestamp'); }); it('should move dimension to incompatible dimension', async () => { await PageObjects.lens.dimensionKeyboardDragDrop('lnsXY_yDimensionPanel', 1, 2); @@ -198,6 +205,7 @@ export default function ({ getPageObjects }: FtrProviderContext) { 'Count of records', 'Unique count of @timestamp', ]); + await PageObjects.lens.assertFocusedDimension('Unique count of @timestamp'); }); it('should reorder elements with keyboard', async () => { await PageObjects.lens.dimensionKeyboardReorder('lnsXY_yDimensionPanel', 0, 1); @@ -205,6 +213,7 @@ export default function ({ getPageObjects }: FtrProviderContext) { 'Unique count of @timestamp', 'Count of records', ]); + await PageObjects.lens.assertFocusedDimension('Count of records'); }); }); diff --git a/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js b/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js index 4496b59393eec..0ce9b7022b38d 100644 --- a/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js +++ b/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js @@ -11,7 +11,6 @@ import uuid from 'uuid/v4'; export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['maps', 'common']); - const testSubjects = getService('testSubjects'); const log = getService('log'); const security = getService('security'); @@ -99,20 +98,6 @@ export default function ({ getService, getPageObjects }) { expect(newIndexedLayerExists).to.be(false); }); - it('should create a link to new index in management', async () => { - const indexName = await indexPoint(); - - const layerAddReady = await PageObjects.maps.importLayerReadyForAdd(); - expect(layerAddReady).to.be(true); - - const newIndexLinkExists = await testSubjects.exists('indexManagementNewIndexLink'); - expect(newIndexLinkExists).to.be(true); - - const indexLink = await testSubjects.getAttribute('indexManagementNewIndexLink', 'href'); - const linkDirectsToNewIndex = indexLink.endsWith(indexName); - expect(linkDirectsToNewIndex).to.be(true); - }); - const GEO_POINT = 'geo_point'; const pointGeojsonFiles = ['point.json', 'multi_point.json']; pointGeojsonFiles.forEach(async (pointFile) => { diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts index 72e81dad44629..04712fc0c1426 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts @@ -15,8 +15,7 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const ml = getService('ml'); - // Failing ES promotion, see https://github.com/elastic/kibana/issues/89980 - describe.skip('jobs cloning supported by UI form', function () { + describe('jobs cloning supported by UI form', function () { const testDataList: Array<{ suiteTitle: string; archive: string; diff --git a/x-pack/test/functional/apps/uptime/locations.ts b/x-pack/test/functional/apps/uptime/locations.ts index e3f1d04640754..15b4773373bf7 100644 --- a/x-pack/test/functional/apps/uptime/locations.ts +++ b/x-pack/test/functional/apps/uptime/locations.ts @@ -39,8 +39,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await makeChecksWithStatus(es, LessAvailMonitor, 5, 2, 10000, {}, 'down'); }; - // FLAKY: https://github.com/elastic/kibana/issues/85208 - describe.skip('Observer location', () => { + describe('Observer location', () => { const start = '~ 15 minutes ago'; const end = 'now'; diff --git a/x-pack/test/functional/apps/uptime/ping_redirects.ts b/x-pack/test/functional/apps/uptime/ping_redirects.ts index e0abee38f4195..9c39ed7017721 100644 --- a/x-pack/test/functional/apps/uptime/ping_redirects.ts +++ b/x-pack/test/functional/apps/uptime/ping_redirects.ts @@ -19,8 +19,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const monitor = () => uptime.monitor; - // FLAKY: https://github.com/elastic/kibana/issues/84992 - describe.skip('Ping redirects', () => { + describe('Ping redirects', () => { const start = '~ 15 minutes ago'; const end = 'now'; diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index aae161ef9fcf1..add6979c2dde1 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -707,5 +707,31 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont await this.saveAndReturn(); } }, + + /** + * Asserts that the focused element is a field with a specified text + * + * @param name - the element visible text + */ + async assertFocusedField(name: string) { + const input = await find.activeElement(); + const fieldAncestor = await input.findByXpath('./../../..'); + const focusedElementText = await fieldAncestor.getVisibleText(); + const dataTestSubj = await fieldAncestor.getAttribute('data-test-subj'); + expect(focusedElementText).to.eql(name); + expect(dataTestSubj).to.eql('lnsFieldListPanelField'); + }, + + /** + * Asserts that the focused element is a dimension with with a specified text + * + * @param name - the element visible text + */ + async assertFocusedDimension(name: string) { + const input = await find.activeElement(); + const fieldAncestor = await input.findByXpath('./../../..'); + const focusedElementText = await fieldAncestor.getVisibleText(); + expect(focusedElementText).to.eql(name); + }, }); } diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 7ba5c00a71b37..4cbec2da21807 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -82,9 +82,10 @@ { "path": "../plugins/ui_actions_enhanced/tsconfig.json" }, { "path": "../plugins/upgrade_assistant/tsconfig.json" }, { "path": "../plugins/watcher/tsconfig.json" }, - { "path": "../plugins/runtime_fields/tsconfig.json" }, - { "path": "../plugins/index_management/tsconfig.json" }, - { "path": "../plugins/watcher/tsconfig.json" }, + { "path": "../plugins/rollup/tsconfig.json" }, + { "path": "../plugins/remote_clusters/tsconfig.json" }, + { "path": "../plugins/cross_cluster_replication/tsconfig.json" }, + { "path": "../plugins/index_lifecycle_management/tsconfig.json"}, { "path": "../plugins/uptime/tsconfig.json" } ] } diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index 3afbb027e7fde..00286ac47da6e 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -27,7 +27,6 @@ "plugins/licensing/**/*", "plugins/lens/**/*", "plugins/maps/**/*", - "plugins/maps_file_upload/**/*", "plugins/maps_legacy_licensing/**/*", "plugins/ml/**/*", "plugins/observability/**/*", @@ -57,6 +56,10 @@ "plugins/index_management/**/*", "plugins/grokdebugger/**/*", "plugins/upgrade_assistant/**/*", + "plugins/rollup/**/*", + "plugins/remote_clusters/**/*", + "plugins/cross_cluster_replication/**/*", + "plugins/index_lifecycle_management/**/*", "plugins/uptime/**/*", "test/**/*" ], @@ -126,7 +129,6 @@ { "path": "./plugins/lens/tsconfig.json" }, { "path": "./plugins/license_management/tsconfig.json" }, { "path": "./plugins/licensing/tsconfig.json" }, - { "path": "./plugins/maps_file_upload/tsconfig.json" }, { "path": "./plugins/maps_legacy_licensing/tsconfig.json" }, { "path": "./plugins/maps/tsconfig.json" }, { "path": "./plugins/ml/tsconfig.json" }, @@ -148,6 +150,10 @@ { "path": "./plugins/runtime_fields/tsconfig.json" }, { "path": "./plugins/index_management/tsconfig.json" }, { "path": "./plugins/watcher/tsconfig.json" }, + { "path": "./plugins/rollup/tsconfig.json" }, + { "path": "./plugins/remote_clusters/tsconfig.json" }, + { "path": "./plugins/cross_cluster_replication/tsconfig.json"}, + { "path": "./plugins/index_lifecycle_management/tsconfig.json"}, { "path": "./plugins/uptime/tsconfig.json" } ] } diff --git a/x-pack/tsconfig.refs.json b/x-pack/tsconfig.refs.json deleted file mode 100644 index 54cee9b124237..0000000000000 --- a/x-pack/tsconfig.refs.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "include": [], - "references": [ - { "path": "./plugins/actions/tsconfig.json" }, - { "path": "./plugins/alerts/tsconfig.json" }, - { "path": "./plugins/beats_management/tsconfig.json" }, - { "path": "./plugins/canvas/tsconfig.json" }, - { "path": "./plugins/cloud/tsconfig.json" }, - { "path": "./plugins/code/tsconfig.json" }, - { "path": "./plugins/console_extensions/tsconfig.json" }, - { "path": "./plugins/dashboard_enhanced/tsconfig.json" }, - { "path": "./plugins/data_enhanced/tsconfig.json" }, - { "path": "./plugins/dashboard_mode/tsconfig.json" }, - { "path": "./plugins/discover_enhanced/tsconfig.json" }, - { "path": "./plugins/embeddable_enhanced/tsconfig.json" }, - { "path": "./plugins/encrypted_saved_objects/tsconfig.json" }, - { "path": "./plugins/enterprise_search/tsconfig.json" }, - { "path": "./plugins/event_log/tsconfig.json" }, - { "path": "./plugins/features/tsconfig.json" }, - { "path": "./plugins/file_upload/tsconfig.json" }, - { "path": "./plugins/fleet/tsconfig.json" }, - { "path": "./plugins/global_search_bar/tsconfig.json" }, - { "path": "./plugins/global_search_providers/tsconfig.json" }, - { "path": "./plugins/global_search/tsconfig.json" }, - { "path": "./plugins/graph/tsconfig.json" }, - { "path": "./plugins/grokdebugger/tsconfig.json" }, - { "path": "./plugins/infra/tsconfig.json" }, - { "path": "./plugins/ingest_pipelines/tsconfig.json" }, - { "path": "./plugins/lens/tsconfig.json" }, - { "path": "./plugins/license_management/tsconfig.json" }, - { "path": "./plugins/licensing/tsconfig.json" }, - { "path": "./plugins/maps_file_upload/tsconfig.json" }, - { "path": "./plugins/maps_legacy_licensing/tsconfig.json" }, - { "path": "./plugins/maps/tsconfig.json" }, - { "path": "./plugins/ml/tsconfig.json" }, - { "path": "./plugins/observability/tsconfig.json" }, - { "path": "./plugins/painless_lab/tsconfig.json" }, - { "path": "./plugins/reporting/tsconfig.json" }, - { "path": "./plugins/saved_objects_tagging/tsconfig.json" }, - { "path": "./plugins/searchprofiler/tsconfig.json" }, - { "path": "./plugins/security/tsconfig.json" }, - { "path": "./plugins/snapshot_restore/tsconfig.json" }, - { "path": "./plugins/spaces/tsconfig.json" }, - { "path": "./plugins/stack_alerts/tsconfig.json" }, - { "path": "./plugins/task_manager/tsconfig.json" }, - { "path": "./plugins/telemetry_collection_xpack/tsconfig.json" }, - { "path": "./plugins/transform/tsconfig.json" }, - { "path": "./plugins/translations/tsconfig.json" }, - { "path": "./plugins/triggers_actions_ui/tsconfig.json" }, - { "path": "./plugins/ui_actions_enhanced/tsconfig.json" }, - { "path": "./plugins/upgrade_assistant/tsconfig.json" }, - { "path": "./plugins/runtime_fields/tsconfig.json" }, - { "path": "./plugins/index_management/tsconfig.json" }, - { "path": "./plugins/watcher/tsconfig.json" }, - { "path": "./plugins/uptime/tsconfig.json" } - ] -} diff --git a/yarn.lock b/yarn.lock index ec6cf338a43da..c9f3186ffcba2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2187,10 +2187,10 @@ pump "^3.0.0" secure-json-parse "^2.1.0" -"@elastic/ems-client@7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-7.11.0.tgz#d2142d0ef5bd1aff7ae67b37c1394b73cdd48d8b" - integrity sha512-7+gDEkBr8nRS7X9i/UPg1WkS7bEBuNbBBjXCchQeYwqPRmw6vOb4wjlNzVwmOFsp2OH4lVFfZ+XU4pxTt32EXA== +"@elastic/ems-client@7.12.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-7.12.0.tgz#cf83f5ad76e26cedfa6f5b91277d2d919b9423d1" + integrity sha512-Svv3boWL1n14nIt6tL9gaA9Ym1B4AwWl6ISZT62+uKM2G+imZxWLkqpQc/HHcf7TfuAmleF2NFwnT5vw2vZTpA== dependencies: lodash "^4.17.15" semver "7.3.2"