diff --git a/.eslintignore b/.eslintignore
index 357d735e8044b..1f22b6074e76e 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -9,14 +9,14 @@ bower_components
/built_assets
/html_docs
/src/plugins/data/common/es_query/kuery/ast/_generated_/**
-/src/legacy/core_plugins/vis_type_timelion/public/_generated_/**
+/src/plugins/vis_type_timelion/public/_generated_/**
src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data
/src/legacy/ui/public/flot-charts
/test/fixtures/scenarios
/src/legacy/core_plugins/console/public/webpackShims
/src/legacy/core_plugins/console/public/tests/webpackShims
/src/legacy/ui/public/utils/decode_geo_hash.js
-/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.*
+/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.*
/src/core/lib/kbn_internal_native_observable
/packages/*/target
/packages/eslint-config-kibana
diff --git a/.eslintrc.js b/.eslintrc.js
index dc2eaa993ce8b..a2b8ae7622d0b 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -567,7 +567,7 @@ module.exports = {
},
{
// typescript only for front and back end
- files: ['x-pack/legacy/plugins/siem/**/*.{ts,tsx}'],
+ files: ['x-pack/{,legacy/}plugins/siem/**/*.{ts,tsx}'],
rules: {
// This will be turned on after bug fixes are complete
// '@typescript-eslint/explicit-member-accessibility': 'warn',
@@ -613,7 +613,7 @@ module.exports = {
// },
{
// typescript and javascript for front and back end
- files: ['x-pack/legacy/plugins/siem/**/*.{js,ts,tsx}'],
+ files: ['x-pack/{,legacy/}plugins/siem/**/*.{js,ts,tsx}'],
plugins: ['eslint-plugin-node', 'react'],
env: {
mocha: true,
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index b6c992a621b2b..ab05b32ab063e 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -14,7 +14,7 @@
/src/legacy/core_plugins/vis_type_vislib/ @elastic/kibana-app
/src/plugins/vis_type_xy/ @elastic/kibana-app
/src/plugins/kibana_legacy/ @elastic/kibana-app
-/src/plugins/timelion/ @elastic/kibana-app
+/src/plugins/vis_type_timelion/ @elastic/kibana-app
/src/plugins/dashboard/ @elastic/kibana-app
/src/plugins/discover/ @elastic/kibana-app
/src/plugins/visualize/ @elastic/kibana-app
@@ -209,9 +209,12 @@
# Endpoint
/x-pack/plugins/endpoint/ @elastic/endpoint-app-team
/x-pack/test/api_integration/apis/endpoint/ @elastic/endpoint-app-team
+/x-pack/test/endpoint_api_integration_no_ingest/ @elastic/endpoint-app-team
/x-pack/test/functional_endpoint/ @elastic/endpoint-app-team
/x-pack/test/functional_endpoint_ingest_failure/ @elastic/endpoint-app-team
/x-pack/test/functional/es_archives/endpoint/ @elastic/endpoint-app-team
+/x-pack/test/plugin_functional/plugins/resolver_test/ @elastic/endpoint-app-team
+/x-pack/test/plugin_functional/test_suites/resolver/ @elastic/endpoint-app-team
# SIEM
/x-pack/legacy/plugins/siem/ @elastic/siem
diff --git a/.i18nrc.json b/.i18nrc.json
index 70277112136a9..4a516f23ebf05 100644
--- a/.i18nrc.json
+++ b/.i18nrc.json
@@ -43,7 +43,7 @@
"src/plugins/telemetry_management_section"
],
"tileMap": "src/legacy/core_plugins/tile_map",
- "timelion": ["src/legacy/core_plugins/timelion", "src/legacy/core_plugins/vis_type_timelion", "src/plugins/timelion"],
+ "timelion": ["src/legacy/core_plugins/timelion", "src/plugins/vis_type_timelion"],
"uiActions": "src/plugins/ui_actions",
"visDefaultEditor": "src/plugins/vis_default_editor",
"visTypeMarkdown": "src/plugins/vis_type_markdown",
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5c745f1611cce..e4a9d87bc56fc 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -22,6 +22,7 @@ A high level overview of our contributing guidelines.
- [Setting Up SSL](#setting-up-ssl)
- [Linting](#linting)
- [Internationalization](#internationalization)
+ - [Localization](#localization)
- [Testing and Building](#testing-and-building)
- [Debugging server code](#debugging-server-code)
- [Instrumenting with Elastic APM](#instrumenting-with-elastic-apm)
@@ -408,6 +409,11 @@ ReactDOM.render(
There are a number of tools created to support internationalization in Kibana that would allow one to validate internationalized labels,
extract them to a `JSON` file or integrate translations back to Kibana. To know more, please read corresponding [readme](src/dev/i18n/README.md) file.
+### Localization
+
+We cannot support accepting contributions to the translations from any source other than the translators we have engaged to do the work.
+We are still to develop a proper process to accept any contributed translations. We certainly appreciate that people care enough about the localization effort to want to help improve the quality. We aim to build out a more comprehensive localization process for the future and will notify you once contributions can be supported, but for the time being, we are not able to incorporate suggestions.
+
### Testing and Building
To ensure that your changes will not break other functionality, please run the test suite and build process before submitting your Pull Request.
diff --git a/Jenkinsfile b/Jenkinsfile
index 79d3c93006cb6..6646ee15ba1c2 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -41,7 +41,7 @@ kibanaPipeline(timeoutMinutes: 135, checkPrChanges: true) {
'xpack-ciGroup10': kibanaPipeline.xpackCiGroupProcess(10),
'xpack-accessibility': kibanaPipeline.functionalTestProcess('xpack-accessibility', './test/scripts/jenkins_xpack_accessibility.sh'),
'xpack-siemCypress': { processNumber ->
- whenChanged(['x-pack/legacy/plugins/siem/', 'x-pack/test/siem_cypress/']) {
+ whenChanged(['x-pack/plugins/siem/', 'x-pack/legacy/plugins/siem/', 'x-pack/test/siem_cypress/']) {
kibanaPipeline.functionalTestProcess('xpack-siemCypress', './test/scripts/jenkins_siem_cypress.sh')(processNumber)
}
},
diff --git a/docs/api/saved-objects/create.asciidoc b/docs/api/saved-objects/create.asciidoc
index dc010c80fd012..571b57a5ef9c2 100644
--- a/docs/api/saved-objects/create.asciidoc
+++ b/docs/api/saved-objects/create.asciidoc
@@ -57,12 +57,12 @@ any data that you send to the API is properly formed.
[source,sh]
--------------------------------------------------
-$ curl -X POST "localhost:5601/api/saved_objects/index-pattern/my-pattern"
+$ curl -X POST "localhost:5601/api/saved_objects/index-pattern/my-pattern" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d '
{
"attributes": {
"title": "my-pattern-*"
}
-}
+}'
--------------------------------------------------
// KIBANA
diff --git a/docs/api/saved-objects/export.asciidoc b/docs/api/saved-objects/export.asciidoc
index e8c762b9543a1..a992d13ed9b9c 100644
--- a/docs/api/saved-objects/export.asciidoc
+++ b/docs/api/saved-objects/export.asciidoc
@@ -68,10 +68,10 @@ Export all index pattern saved objects:
[source,sh]
--------------------------------------------------
-$ curl -X POST "localhost:5601/api/saved_objects/_export"
+$ curl -X POST "localhost:5601/api/saved_objects/_export" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d '
{
"type": "index-pattern"
-}
+}'
--------------------------------------------------
// KIBANA
@@ -79,11 +79,11 @@ Export all index pattern saved objects and exclude the export summary from the s
[source,sh]
--------------------------------------------------
-$ curl -X POST "localhost:5601/api/saved_objects/_export"
+$ curl -X POST "localhost:5601/api/saved_objects/_export" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d '
{
"type": "index-pattern",
"excludeExportDetails": true
-}
+}'
--------------------------------------------------
// KIBANA
@@ -91,7 +91,7 @@ Export a specific saved object:
[source,sh]
--------------------------------------------------
-$ curl -X POST "localhost:5601/api/saved_objects/_export"
+$ curl -X POST "localhost:5601/api/saved_objects/_export" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d '
{
"objects": [
{
@@ -99,7 +99,7 @@ $ curl -X POST "localhost:5601/api/saved_objects/_export"
"id": "be3733a0-9efe-11e7-acb3-3dab96693fab"
}
]
-}
+}'
--------------------------------------------------
// KIBANA
@@ -107,7 +107,7 @@ Export a specific saved object and it's related objects :
[source,sh]
--------------------------------------------------
-$ curl -X POST "localhost:5601/api/saved_objects/_export"
+$ curl -X POST "localhost:5601/api/saved_objects/_export" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d '
{
"objects": [
{
@@ -116,6 +116,6 @@ $ curl -X POST "localhost:5601/api/saved_objects/_export"
}
],
"includeReferencesDeep": true
-}
+}'
--------------------------------------------------
// KIBANA
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
index fc0dab94a0f65..bf29c883e4eb9 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
@@ -88,7 +88,6 @@
| [SavedQuery](./kibana-plugin-plugins-data-public.savedquery.md) | |
| [SavedQueryService](./kibana-plugin-plugins-data-public.savedqueryservice.md) | |
| [SearchSourceFields](./kibana-plugin-plugins-data-public.searchsourcefields.md) | |
-| [SearchStrategyProvider](./kibana-plugin-plugins-data-public.searchstrategyprovider.md) | |
| [TabbedAggColumn](./kibana-plugin-plugins-data-public.tabbedaggcolumn.md) | \* |
| [TabbedTable](./kibana-plugin-plugins-data-public.tabbedtable.md) | \* |
| [TimeRange](./kibana-plugin-plugins-data-public.timerange.md) | |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.id.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.id.md
deleted file mode 100644
index d60ffba6a05ca..0000000000000
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.id.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchStrategyProvider](./kibana-plugin-plugins-data-public.searchstrategyprovider.md) > [id](./kibana-plugin-plugins-data-public.searchstrategyprovider.id.md)
-
-## SearchStrategyProvider.id property
-
-Signature:
-
-```typescript
-id: string;
-```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.isviable.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.isviable.md
deleted file mode 100644
index aa8ed49051ee9..0000000000000
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.isviable.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchStrategyProvider](./kibana-plugin-plugins-data-public.searchstrategyprovider.md) > [isViable](./kibana-plugin-plugins-data-public.searchstrategyprovider.isviable.md)
-
-## SearchStrategyProvider.isViable property
-
-Signature:
-
-```typescript
-isViable: (indexPattern: IndexPattern) => boolean;
-```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.md
deleted file mode 100644
index b271a921906a7..0000000000000
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchStrategyProvider](./kibana-plugin-plugins-data-public.searchstrategyprovider.md)
-
-## SearchStrategyProvider interface
-
-Signature:
-
-```typescript
-export interface SearchStrategyProvider
-```
-
-## Properties
-
-| Property | Type | Description |
-| --- | --- | --- |
-| [id](./kibana-plugin-plugins-data-public.searchstrategyprovider.id.md) | string | |
-| [isViable](./kibana-plugin-plugins-data-public.searchstrategyprovider.isviable.md) | (indexPattern: IndexPattern) => boolean | |
-| [search](./kibana-plugin-plugins-data-public.searchstrategyprovider.search.md) | (params: SearchStrategySearchParams) => SearchStrategyResponse | |
-
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.search.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.search.md
deleted file mode 100644
index 6e2561c3b0ad0..0000000000000
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchstrategyprovider.search.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchStrategyProvider](./kibana-plugin-plugins-data-public.searchstrategyprovider.md) > [search](./kibana-plugin-plugins-data-public.searchstrategyprovider.search.md)
-
-## SearchStrategyProvider.search property
-
-Signature:
-
-```typescript
-search: (params: SearchStrategySearchParams) => SearchStrategyResponse;
-```
diff --git a/docs/images/add_remote_cluster.png b/docs/images/add_remote_cluster.png
index 376b1d8392366..160d29b741c62 100755
Binary files a/docs/images/add_remote_cluster.png and b/docs/images/add_remote_cluster.png differ
diff --git a/docs/images/auto_follow_pattern.png b/docs/images/auto_follow_pattern.png
index 3bf86458eddd7..f80de9352280f 100755
Binary files a/docs/images/auto_follow_pattern.png and b/docs/images/auto_follow_pattern.png differ
diff --git a/docs/images/cross-cluster-replication-list-view.png b/docs/images/cross-cluster-replication-list-view.png
new file mode 100755
index 0000000000000..4c45174cff7f1
Binary files /dev/null and b/docs/images/cross-cluster-replication-list-view.png differ
diff --git a/docs/images/follower_indices.png b/docs/images/follower_indices.png
old mode 100644
new mode 100755
index f103bb3cf2acf..505adeb45ae23
Binary files a/docs/images/follower_indices.png and b/docs/images/follower_indices.png differ
diff --git a/docs/images/remote-clusters-list-view.png b/docs/images/remote-clusters-list-view.png
new file mode 100755
index 0000000000000..c28379863b74b
Binary files /dev/null and b/docs/images/remote-clusters-list-view.png differ
diff --git a/docs/ingest_manager/index-templates.asciidoc b/docs/ingest_manager/index-templates.asciidoc
new file mode 100644
index 0000000000000..e19af63c3116f
--- /dev/null
+++ b/docs/ingest_manager/index-templates.asciidoc
@@ -0,0 +1,7 @@
+# Elasticsearch Index Templates
+
+## Generation
+
+* Index templates are generated from `YAML` files contained in the package.
+* There is one index template per dataset.
+* For the generation of an index template, all `yml` files contained in the package subdirectory `dataset/DATASET_NAME/fields/` are used.
diff --git a/docs/ingest_manager/index.asciidoc b/docs/ingest_manager/index.asciidoc
index 22afa88c919e4..866935d1fa580 100644
--- a/docs/ingest_manager/index.asciidoc
+++ b/docs/ingest_manager/index.asciidoc
@@ -199,3 +199,10 @@ The new ingest pipeline is expected to still work with the data coming from olde
In case of a breaking change in the data structure, the new ingest pipeline is also expected to deal with this change. In case there are breaking changes which cannot be dealt with in an ingest pipeline, a new package has to be created.
Each package lists its minimal required agent version. In case there are agents enrolled with an older version, the user is notified to upgrade these agents as otherwise the new configs cannot be rolled out.
+
+=== Generated assets
+
+When a package is installed or upgraded, certain Kibana and Elasticsearch assets are generated from . These follow the naming conventions explained above (see "indexing strategy") and contain configuration for the elastic stack that makes ingesting and displaying data work with as little user interaction as possible.
+
+* link:index-templates.asciidoc[Elasticsearch Index Templates]
+* Kibana Index Patterns
diff --git a/docs/management/managing-ccr.asciidoc b/docs/management/managing-ccr.asciidoc
new file mode 100644
index 0000000000000..b2db5a80cfe7e
--- /dev/null
+++ b/docs/management/managing-ccr.asciidoc
@@ -0,0 +1,73 @@
+[role="xpack"]
+[[managing-cross-cluster-replication]]
+== Cross-Cluster Replication
+
+Use *Cross-Cluster Replication* to reproduce indices in
+remote clusters on a local cluster. {ref}/xpack-ccr.html[Cross-cluster replication]
+is commonly used to provide remote backups for disaster recovery and for
+geo-proximite copies of data.
+
+To get started, go to *Management > Cross-Cluster Replication*.
+
+[role="screenshot"]
+image::images/cross-cluster-replication-list-view.png[][Cross-cluster replication list view]
+
+[float]
+=== Prerequisites
+
+* You must have a {ref}/modules-remote-clusters.html[remote cluster].
+* Leader indices must meet {ref}/ccr-requirements.html[these requirements].
+* The Elasticsearch version of the local cluster must be the same as or newer than the remote cluster.
+Refer to {ref}/ccr-overview.html[this document] for more information.
+
+[float]
+[[configure-replication]]
+=== Configure replication
+
+Replication requires a leader index, the index being replicated, and a
+follower index, which will contain the leader index's replicated data.
+The follower index is passive in that it can read requests and searches,
+but cannot accept direct writes. Only the leader index is active for direct writes.
+
+You can configure follower indices in two ways:
+
+* Create specific follower indices
+* Create follower indices from an auto-follow pattern
+
+[float]
+==== Create specific follower indices
+
+To replicate data from existing indices, or set up local followers on a case-by-case basis,
+go to *Follower indices*. When you create the follower index, you must reference the
+remote cluster and the leader index that you created in the remote cluster.
+
+[role="screenshot"]
+image::images/follower_indices.png[][UI for adding follower indices]
+
+[float]
+==== Create follower indices from an auto-follow pattern
+
+To automatically detect and follow new indices when they are created on a remote cluster,
+go to *Auto-follow patterns*. Creating an auto-follow pattern is useful when you have
+time series data, like event logs, on the remote cluster that is created or rolled over on a daily basis.
+
+When creating the pattern, you must reference the remote cluster that you
+connected to your local cluster. You must also specify a collection of index patterns
+that match the indices you want to automatically follow.
+
+Once you configure an
+auto-follow pattern, any time a new index with a name that matches the pattern is
+created in the remote cluster, a follower index is automatically configured in the local cluster.
+
+[role="screenshot"]
+image::images/auto_follow_pattern.png[UI for adding an auto-follow pattern]
+
+[float]
+[[manage-replication]]
+=== Manage replication
+
+Use the list views in *Cross-Cluster Replication* to monitor whether the replication is active and
+pause and resume replication. You can also edit and remove the follower indices and auto-follow patterns.
+
+For an example of cross-cluster replication,
+refer to https://www.elastic.co/blog/bi-directional-replication-with-elasticsearch-cross-cluster-replication-ccr[Bi-directional replication with Elasticsearch cross-cluster replication].
diff --git a/docs/management/managing-remote-clusters.asciidoc b/docs/management/managing-remote-clusters.asciidoc
index 6b69cfef5b768..00ec5c7d2ddea 100644
--- a/docs/management/managing-remote-clusters.asciidoc
+++ b/docs/management/managing-remote-clusters.asciidoc
@@ -1,67 +1,39 @@
[[working-remote-clusters]]
== Remote Clusters
-{kib} *Management* provides user interfaces for working with data from remote
-clusters and managing the {ccr} process. You can replicate indices from a
-leader remote cluster to a follower index in a local cluster. The local follower indices
-can be used to provide remote backups for disaster recovery or for geo-proximite copies of data.
+Use *Remote Clusters* to establish a unidirectional
+connection from your cluster to other clusters. This functionality is
+required for {ref}/xpack-ccr.html[cross-cluster replication] and
+{ref}/modules-cross-cluster-search.html[cross-cluster search].
-Before using these features, you should be familiar with the following concepts:
+To get started, go to *Management > Remote Clusters*.
-* {ref}/xpack-ccr.html[{ccr-cap}]
-* {ref}/modules-cross-cluster-search.html[{ccs-cap}]
-* {ref}/cross-cluster-configuring.html[Cross-cluster security requirements]
+[role="screenshot"]
+image::images/remote-clusters-list-view.png[Remote Clusters list view, including Add a remote cluster button]
[float]
[[managing-remote-clusters]]
-== Managing remote clusters
-
-*Remote clusters* helps you manage remote clusters for use with
-{ccs} and {ccr}. You can add and remove remote clusters and check their connectivity.
+=== Add a remote cluster
-Before you use this feature, you should be familiar with the concept of
-{ref}/modules-remote-clusters.html[remote clusters].
+A {ref}/modules-remote-clusters.html[remote cluster] connection works by configuring a remote cluster and
+connecting to a limited number of nodes, called {ref}/modules-remote-clusters.html#sniff-mode[seed nodes],
+in that cluster.
+Alternatively, you can define a single proxy address for the remote cluster.
-Go to *Management > Elasticsearch > Remote clusters* to create or manage your remotes.
+By default, a cross-cluster request, such as a cross-cluster search or
+replication request, fails if any cluster in the request is unavailable.
+To skip a cluster when its unavailable,
+set *Skip if unavailable* to true.
-To set up a new remote, click *Add a remote cluster*. Give the cluster a unique name
-and define the seed nodes for cluster discovery. You can edit or remove your remote clusters
-from the *Remote clusters* list view.
+Once you add a remote cluster, you can configure <>
+to reproduce indices in the remote cluster on a local cluster.
[role="screenshot"]
image::images/add_remote_cluster.png[][UI for adding a remote cluster]
-Once a remote cluster is registered, you can use the tools under *{ccr-cap}*
-to add and manage follower indices on the local cluster, and replicate data from
-indices on the remote cluster based on an auto-follow index pattern.
-
[float]
-[[managing-cross-cluster-replication]]
-== [xpack]#Managing {ccr}#
-
-*{ccr-cap}* helps you create and manage the {ccr} process.
-If you want to replicate data from existing indices, or set up
-local followers on a case-by-case basis, go to *Follower indices*.
-If you want to automatically detect and follow new indices when they are created
-on a remote cluster, you can do so from *Auto-follow patterns*.
-
-Creating an auto-follow pattern is useful when you have time-series data, like a logs index, on the
-remote cluster that is created or rolled over on a daily basis. Once you have configured an
-auto-follow pattern, any time a new index with a name that matches the pattern is
-created in the remote cluster, a follower index is automatically configured in the local cluster.
-
-From the same view, you can also see a list of your saved auto-follow patterns for
-a given remote cluster, and monitor whether the replication is active.
+[[manage-remote-clusters]]
+=== Manage remote clusters
-Before you use these features, you should be familiar with the following concepts:
-
-* {ref}/ccr-requirements.html[Requirements for leader indices]
-* {ref}/ccr-auto-follow.html[Automatically following indices]
-
-To get started, go to *Management > Elasticsearch > {ccr-cap}*.
-
-[role="screenshot"]
-image::images/auto_follow_pattern.png[][UI for adding an auto-follow pattern]
-
-[role="screenshot"]
-image::images/follower_indices.png[][UI for adding follower indices]
+From the *Remote Clusters* list view, you can drill down into each cluster and
+view its status. You can also edit and delete a cluster.
diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc
index fd835bde83322..a5503969a3ec1 100644
--- a/docs/redirects.asciidoc
+++ b/docs/redirects.asciidoc
@@ -23,7 +23,7 @@ For more {kib} configuration settings, see <>.
[role="exclude",id="uptime-security"]
== Uptime security
-This page has moved. Please see the new section in the {uptime-guide}/uptime-security.html[Uptime Monitoring Guide].
+This page has moved. Please see the new section in the {heartbeat-ref}/securing-heartbeat.html[Uptime Monitoring Guide].
[role="exclude",id="infra-read-only-access"]
== Configure source read-only access
diff --git a/docs/uptime-guide/index.asciidoc b/docs/uptime-guide/index.asciidoc
index 7bbc01bb303f1..09763182fa88f 100644
--- a/docs/uptime-guide/index.asciidoc
+++ b/docs/uptime-guide/index.asciidoc
@@ -12,4 +12,3 @@ include::install.asciidoc[]
include::deployment-arch.asciidoc[]
-include::security.asciidoc[]
diff --git a/docs/uptime-guide/install.asciidoc b/docs/uptime-guide/install.asciidoc
index e7c50bb7604ce..0ed1270ca92ce 100644
--- a/docs/uptime-guide/install.asciidoc
+++ b/docs/uptime-guide/install.asciidoc
@@ -56,6 +56,11 @@ Additional information is available in {heartbeat-ref}/heartbeat-configuration.h
[role="screenshot"]
image::images/uptime-setup.png[Installation instructions on the Uptime page in Kibana]
+[[setup-security]]
+=== Step 4: Setup Security
+
+Secure your installation by following the {heartbeat-ref}/securing-heartbeat.html[Secure Heartbeat] documentation.
+
[float]
==== Important considerations
diff --git a/docs/uptime-guide/security.asciidoc b/docs/uptime-guide/security.asciidoc
deleted file mode 100644
index 0c6fa4c6c4f56..0000000000000
--- a/docs/uptime-guide/security.asciidoc
+++ /dev/null
@@ -1,60 +0,0 @@
-[[uptime-security]]
-== Elasticsearch Security
-
-If you use Elasticsearch security, you'll need to enable certain privileges for users
-that would like to access the Uptime app. For example, create user and support roles to implement the privileges:
-
-[float]
-=== Create a role
-
-You'll need a role that lets you access the Heartbeat indices, which by default are `heartbeat-*`.
-You can create this with the following request:
-
-["source","sh",subs="attributes,callouts"]
----------------------------------------------------------------
-PUT /_security/role/uptime
-{ "indices" : [
- {
- "names" : [
- "heartbeat-*"
- ],
- "privileges" : [
- "read",
- "view_index_metadata"
- ],
- "field_security" : {
- "grant" : [
- "*"
- ]
- },
- "allow_restricted_indices" : false
- }
- ],
- "transient_metadata" : {
- "enabled" : true
- }
-}
----------------------------------------------------------------
-// CONSOLE
-
-[float]
-=== Assign the role to a user
-
-Next, you'll need to create a user with both the `uptime` role, and another role with sufficient {kibana-ref}/kibana-privileges.html[Kibana privileges],
-such as the `kibana_admin` role.
-You can do this with the following request:
-
-["source","sh",subs="attributes,callouts"]
----------------------------------------------------------------
-PUT /_security/user/jacknich
-{
- "password" : "j@rV1s",
- "roles" : [ "uptime", "kibana_admin" ],
- "full_name" : "Jack Nicholson",
- "email" : "jacknich@example.com",
- "metadata" : {
- "intelligence" : 7
- }
-}
----------------------------------------------------------------
-// CONSOLE
diff --git a/docs/uptime/images/alert-flyout.png b/docs/uptime/images/alert-flyout.png
new file mode 100644
index 0000000000000..7fc1e3d9aefe2
Binary files /dev/null and b/docs/uptime/images/alert-flyout.png differ
diff --git a/docs/uptime/images/check-history.png b/docs/uptime/images/check-history.png
index 6418495eee9ed..91565bf59aa7f 100644
Binary files a/docs/uptime/images/check-history.png and b/docs/uptime/images/check-history.png differ
diff --git a/docs/uptime/images/error-list.png b/docs/uptime/images/error-list.png
deleted file mode 100644
index 99f017f2945a5..0000000000000
Binary files a/docs/uptime/images/error-list.png and /dev/null differ
diff --git a/docs/uptime/images/monitor-charts.png b/docs/uptime/images/monitor-charts.png
index dbfa43f47656e..522f34662657e 100644
Binary files a/docs/uptime/images/monitor-charts.png and b/docs/uptime/images/monitor-charts.png differ
diff --git a/docs/uptime/images/observability_integrations.png b/docs/uptime/images/observability_integrations.png
index d5c612c7589ca..6589c0c5565dd 100644
Binary files a/docs/uptime/images/observability_integrations.png and b/docs/uptime/images/observability_integrations.png differ
diff --git a/docs/uptime/images/settings.png b/docs/uptime/images/settings.png
new file mode 100644
index 0000000000000..dd36f0a6d702b
Binary files /dev/null and b/docs/uptime/images/settings.png differ
diff --git a/docs/uptime/images/snapshot-view.png b/docs/uptime/images/snapshot-view.png
index 020396d0f3e4c..1fce2e9592c14 100644
Binary files a/docs/uptime/images/snapshot-view.png and b/docs/uptime/images/snapshot-view.png differ
diff --git a/docs/uptime/images/status-bar.png b/docs/uptime/images/status-bar.png
index e0e9b27555900..8d242789cdccd 100644
Binary files a/docs/uptime/images/status-bar.png and b/docs/uptime/images/status-bar.png differ
diff --git a/docs/uptime/index.asciidoc b/docs/uptime/index.asciidoc
index 785b9f818f5bf..a355f8ecf4843 100644
--- a/docs/uptime/index.asciidoc
+++ b/docs/uptime/index.asciidoc
@@ -12,8 +12,10 @@ To get started with Elastic Uptime, refer to {uptime-guide}/install-uptime.html[
* <>
* <>
+* <>
--
include::overview.asciidoc[]
include::monitor.asciidoc[]
+include::settings.asciidoc[]
diff --git a/docs/uptime/monitor.asciidoc b/docs/uptime/monitor.asciidoc
index d54fd02c7c069..8a4be1f11a721 100644
--- a/docs/uptime/monitor.asciidoc
+++ b/docs/uptime/monitor.asciidoc
@@ -5,21 +5,24 @@
The Monitor page will help you get further insight into the performance
of a specific network endpoint. You'll see a detailed visualization of
the monitor's request duration over time, as well as the `up`/`down`
-status over time.
+status over time. You can also also detect anomalies in response time data
+by configuring Machine Learning jobs on this page.
[float]
-=== Status bar
+=== Status panel
[role="screenshot"]
image::uptime/images/status-bar.png[Status bar]
-The Status bar displays a quick summary of the latest information
+The Status panel displays a quick summary of the latest information
regarding your monitor. You can view its latest status, click a link to
visit the targeted URL, see its most recent request duration, and determine the
amount of time that has elapsed since the last check.
-You can use the Status bar to get a quick summary of current performance,
-beyond simply knowing if the monitor is `up` or `down`.
+When two Heartbeat instances are configured in different geographic locations
+the map will show each location as a pinpoint on the map, along with the
+amount of time elapsed since data was last received from that location.
+
[float]
=== Monitor charts
@@ -32,12 +35,14 @@ date range. These charts can help you gain insight into how quickly requests are
by the targeted endpoint, and give you a sense of how frequently a host or endpoint
was down in your selected timespan.
-The first chart displays request duration information for your monitor.
+The Monitor duration chart displays request duration information for your monitor.
The area surrounding the line is the range of request time for the corresponding
-bucket. The line is the average time.
+bucket. The line is the average time. Anomaly detection using Machine Learning
+can be configured in the upper right hand of this panel. When response times change
+in an unexpected way the time range in which they occurred will be given filled with a color.
-Next, is a graphical representation of the check statuses over time. Hover over
-the charts to display crosshairs with more specific numeric data.
+The pings over time chart is a graphical representation of the check statuses over time.
+Hover over the charts to display crosshairs with more specific numeric data.
[role="screenshot"]
image::uptime/images/crosshair-example.png[Chart crosshair]
@@ -49,6 +54,6 @@ image::uptime/images/crosshair-example.png[Chart crosshair]
image::uptime/images/check-history.png[Check history view]
The Check history displays the total count of this monitor's checks for the selected
-date range. You can additionally filter the checks by `status` to help find recent problems
+date range. You can additionally filter the checks by status and location to help find recent problems
on a per-check basis. This table can help you gain some insight into more granular details
about recent individual data points Heartbeat is logging about your host or endpoint.
diff --git a/docs/uptime/overview.asciidoc b/docs/uptime/overview.asciidoc
index 098ce12a56991..71c09c968e512 100644
--- a/docs/uptime/overview.asciidoc
+++ b/docs/uptime/overview.asciidoc
@@ -21,12 +21,12 @@ This control allows you to use automated filter options, as well as input custom
text to select specific monitors by field, URL, ID, and other attributes.
[float]
-=== Snapshot view
+=== Snapshot panel
[role="screenshot"]
image::uptime/images/snapshot-view.png[Snapshot view]
-This view is intended to quickly give you a sense of the overall
+This panel is intended to quickly give you a sense of the overall
status of the environment you're monitoring, or a subset of those monitors.
Here, you can see the total number of detected monitors within the selected
Uptime date range. In addition to the total, the counts for the number of monitors
@@ -49,6 +49,17 @@ way to navigate to a more in-depth visualization for interesting hosts or endpoi
This table includes information like the most recent status, when the monitor was last checked, its
ID and URL, its IP address, and a dedicated sparkline showing its check status over time.
+[float]
+=== Creating and managing alerts
+
+[role="screenshot"]
+image::uptime/images/alert-flyout.png[Create alert flyout]
+
+To receive alerts when a monitor goes down, use the alerting menu at the top of the
+overview page. Use a query in the alert flyout to determine which monitors to check
+with your alert. If you already have a query in the overview page search bar it will
+be carried over into this box.
+
[float]
=== Observability integrations
@@ -60,14 +71,3 @@ Docker related host information, it will provide links to open the Metrics app o
for this host. Additionally, this feature supplies links to simply filter the other views on the host's
IP address, to help you quickly determine if these other solutions contain data relevant to your current
interest.
-
-[float]
-=== Error list
-
-[role="screenshot"]
-image::uptime/images/error-list.png[Error list]
-
-The Error list displays aggregations of errors that Heartbeat has logged. Errors are
-displayed by Error type, monitor ID, and message. Clicking a monitor's ID will take you
-to the corresponding Monitor view, which can provide you richer information about the individual
-data points that are resulting in the displayed errors.
diff --git a/docs/uptime/settings.asciidoc b/docs/uptime/settings.asciidoc
new file mode 100644
index 0000000000000..55da6e802bec6
--- /dev/null
+++ b/docs/uptime/settings.asciidoc
@@ -0,0 +1,27 @@
+[role="xpack"]
+[[uptime-settings]]
+
+== Settings
+
+[role="screenshot"]
+image::uptime/images/settings.png[Filter bar]
+
+The Uptime settings page lets you change which Heartbeat indices are displayed
+by the uptime app. Users must have the 'all' permission to modify items on this page.
+Uptime settings apply to the current space only. Use different settings in different
+spaces to segment different uptime use cases and domains.
+
+As an example, imagine your organization has one team for internal IT services, and another
+for public services. Each team operates independently and is only responsible for its
+own services. In this scenario, you might set up separate Heartbeat instances for each team,
+writing out to index patterns named `it-heartbeat-\*`, and `external-heartbeat-\*`. You would
+create separate roles and users for each in Elasticsearch, each with access to their own spaces,
+named `it` and `external` respectively. Within each space you would navigate to the settings page
+and set the correct index pattern to match only the indices that space is allowed to access.
+
+Note that the pattern set here only restricts what the Uptime app shows. Users may still be able
+to manually query Elasticsearch for data outside this pattern!
+
+See the <>
+and {heartbeat-ref}/securing-heartbeat.html[Heartbeat security]
+docs for more information.
diff --git a/docs/user/alerting/action-types.asciidoc b/docs/user/alerting/action-types.asciidoc
index 2913bf28dd765..49e7bd1d77743 100644
--- a/docs/user/alerting/action-types.asciidoc
+++ b/docs/user/alerting/action-types.asciidoc
@@ -34,14 +34,23 @@ a| <>
[NOTE]
==============================================
-Some action types are paid commercial features, while others are free.
-For a comparison of the Elastic subscription levels,
-see https://www.elastic.co/subscriptions[the subscription page].
+Some action types are paid commercial features, while others are free.
+For a comparison of the Elastic subscription levels,
+see https://www.elastic.co/subscriptions[the subscription page].
==============================================
+[float]
+[[create-connectors]]
+=== Connectors
+
+You can create connectors for actions in <> or via the action API.
+For out-of-the-box and standardized connectors, you can <>
+before {kib} starts.
+
include::action-types/email.asciidoc[]
include::action-types/index.asciidoc[]
include::action-types/pagerduty.asciidoc[]
include::action-types/server-log.asciidoc[]
include::action-types/slack.asciidoc[]
include::action-types/webhook.asciidoc[]
+include::pre-configured-connectors.asciidoc[]
diff --git a/docs/user/alerting/images/alert-pre-configured-connectors-dropdown.png b/docs/user/alerting/images/alert-pre-configured-connectors-dropdown.png
new file mode 100644
index 0000000000000..4e6c713298626
Binary files /dev/null and b/docs/user/alerting/images/alert-pre-configured-connectors-dropdown.png differ
diff --git a/docs/user/alerting/images/alert-pre-configured-slack-connector.png b/docs/user/alerting/images/alert-pre-configured-slack-connector.png
new file mode 100644
index 0000000000000..de05e2074ddde
Binary files /dev/null and b/docs/user/alerting/images/alert-pre-configured-slack-connector.png differ
diff --git a/docs/user/alerting/images/pre-configured-connectors-managing.png b/docs/user/alerting/images/pre-configured-connectors-managing.png
new file mode 100644
index 0000000000000..f97e93175fa36
Binary files /dev/null and b/docs/user/alerting/images/pre-configured-connectors-managing.png differ
diff --git a/docs/user/alerting/images/pre-configured-connectors-view-screen.png b/docs/user/alerting/images/pre-configured-connectors-view-screen.png
new file mode 100644
index 0000000000000..43ac44e7536d8
Binary files /dev/null and b/docs/user/alerting/images/pre-configured-connectors-view-screen.png differ
diff --git a/docs/user/alerting/pre-configured-connectors.asciidoc b/docs/user/alerting/pre-configured-connectors.asciidoc
new file mode 100644
index 0000000000000..3db13acfb423e
--- /dev/null
+++ b/docs/user/alerting/pre-configured-connectors.asciidoc
@@ -0,0 +1,88 @@
+[role="xpack"]
+[[pre-configured-connectors]]
+
+== Preconfigured connectors
+
+You can preconfigure an action connector to have all the information it needs prior to startup
+by adding it to the `kibana.yml` file.
+Sensitive configuration information, such as credentials, can use the {kib} keystore.
+
+Preconfigured connectors offer the following capabilities:
+
+- Require no setup. Configuration and credentials needed to execute an
+action are predefined, including the connector name and ID.
+- Appear in all spaces because they are not saved objects.
+- Cannot be edited or deleted.
+
+[float]
+[[preconfigured-connector-example]]
+=== Example of a preconfigured connector
+
+The following example shows a valid configuration 2 out-of-the box connector.
+
+[source,console]
+------------------------
+ xpack.actions.preconfigured:
+ - id: 'my-slack1' <1>
+ actionTypeId: .slack <2>
+ name: 'Slack #xyz' <3>
+ config: <4>
+ webhookUrl: 'https://hooks.slack.com/services/abcd/efgh/ijklmnopqrstuvwxyz'
+ - id: 'webhook-service'
+ actionTypeId: .webhook
+ name: 'Email service'
+ config:
+ url: 'https://email-alert-service.elastic.co'
+ method: post
+ headers:
+ header1: value1
+ header2: value2
+ secrets: <5>
+ user: elastic
+ password: changeme
+------------------------
+
+<1> `id` is the action connector identifier.
+<2> `actionTypeId` is the action type identifier.
+<3> `name` is the name of the preconfigured connector.
+<4> `config` is the action type specific to the configuration.
+<5> `secrets` is sensitive configuration, such as username, password, and keys.
+
+[NOTE]
+==============================================
+Sensitive properties, such as passwords, can also be stored in the {kib} keystore.
+==============================================
+
+[float]
+[[pre-configured-connector-alert-form]]
+=== Creating an alert with a preconfigured connector
+
+When attaching an action to an alert,
+select from a list of available action types, and
+then select the Slack or Webhook type. Those action types were configured previously.
+The preconfigured connector is installed and is automatically selected.
+
+[role="screenshot"]
+image::images/alert-pre-configured-slack-connector.png[Create alert with selected Slack action type]
+
+The dropdown is populated with additional preconfigured Slack connectors.
+The `preconfigured` label distinguishes them from space-aware connectors that use saved objects.
+
+[role="screenshot"]
+image::images/alert-pre-configured-connectors-dropdown.png[Dropdown list with pre-cofigured connectors]
+
+[float]
+[[managing-pre-configured-connectors]]
+=== Managing preconfigured connectors
+
+Preconfigured connectors appear in the connector list, regardless of which space the user is in.
+They are tagged as “preconfigured” and cannot be deleted.
+
+[role="screenshot"]
+image::images/pre-configured-connectors-managing.png[Connectors managing tab with pre-cofigured]
+
+Clicking on a preconfigured connector shows the description, but not any of the configuration.
+A message indicates that this is a preconfigured connector.
+
+[role="screenshot"]
+image::images/pre-configured-connectors-view-screen.png[Pre-configured connector view details]
diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc
index fa34802abe2a9..a4ba320e826b1 100644
--- a/docs/user/management.asciidoc
+++ b/docs/user/management.asciidoc
@@ -13,7 +13,7 @@ indices, clusters, licenses, UI settings, index patterns, spaces, and more.
[cols="50, 50"]
|===
-a| <>
+a| <>
Replicate indices on a remote cluster and copy them to a follower index on a local cluster.
This is important for
@@ -85,7 +85,8 @@ set the timespan for notification messages, and much more.
| <>
-Centrally manage your alerts from across {kib}. Create and manage re-usable connectors for triggering actions.
+Centrally manage your alerts across {kib}. Create and manage reusable
+connectors for triggering actions.
| <>
@@ -125,6 +126,8 @@ include::{kib-repo-dir}/management/alerting/connector-management.asciidoc[]
include::{kib-repo-dir}/management/managing-beats.asciidoc[]
+include::{kib-repo-dir}/management/managing-ccr.asciidoc[]
+
include::{kib-repo-dir}/management/index-lifecycle-policies/intro-to-lifecycle-policies.asciidoc[]
include::{kib-repo-dir}/management/index-lifecycle-policies/create-policy.asciidoc[]
diff --git a/package.json b/package.json
index fe672ef130456..21e9f67e6206a 100644
--- a/package.json
+++ b/package.json
@@ -119,8 +119,8 @@
"dependencies": {
"@babel/core": "^7.9.0",
"@babel/register": "^7.9.0",
- "@elastic/apm-rum": "^4.6.0",
- "@elastic/charts": "18.2.2",
+ "@elastic/apm-rum": "^5.1.1",
+ "@elastic/charts": "18.3.0",
"@elastic/datemath": "5.0.3",
"@elastic/ems-client": "7.8.0",
"@elastic/eui": "21.0.1",
diff --git a/packages/kbn-config-schema/src/index.ts b/packages/kbn-config-schema/src/index.ts
index fc3e3c541846a..5d387f327e58f 100644
--- a/packages/kbn-config-schema/src/index.ts
+++ b/packages/kbn-config-schema/src/index.ts
@@ -60,6 +60,7 @@ import {
export { ObjectType, TypeOf, Type };
export { ByteSizeValue } from './byte_size_value';
export { SchemaTypeError, ValidationError } from './errors';
+export { isConfigSchema } from './typeguards';
function any(options?: TypeOptions) {
return new AnyType(options);
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/legacy_imports.ts b/packages/kbn-config-schema/src/typeguards/index.ts
similarity index 87%
rename from src/legacy/core_plugins/vis_type_timelion/public/legacy_imports.ts
rename to packages/kbn-config-schema/src/typeguards/index.ts
index e7612b288fb24..e724878eb33e9 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/legacy_imports.ts
+++ b/packages/kbn-config-schema/src/typeguards/index.ts
@@ -17,5 +17,4 @@
* under the License.
*/
-export { npSetup, npStart } from 'ui/new_platform';
-export { PluginsStart } from 'ui/new_platform/new_platform';
+export { isConfigSchema } from './is_config_schema';
diff --git a/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts b/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts
new file mode 100644
index 0000000000000..e0ef3835ca0a3
--- /dev/null
+++ b/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts
@@ -0,0 +1,56 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { schema } from '..';
+import { isConfigSchema } from './is_config_schema';
+
+describe('isConfigSchema', () => {
+ it('returns true for every sub classes of `Type`', () => {
+ expect(isConfigSchema(schema.any())).toBe(true);
+ expect(isConfigSchema(schema.arrayOf(schema.string()))).toBe(true);
+ expect(isConfigSchema(schema.boolean())).toBe(true);
+ expect(isConfigSchema(schema.buffer())).toBe(true);
+ expect(isConfigSchema(schema.byteSize())).toBe(true);
+ expect(isConfigSchema(schema.duration())).toBe(true);
+ expect(isConfigSchema(schema.literal(''))).toBe(true);
+ expect(isConfigSchema(schema.mapOf(schema.string(), schema.number()))).toBe(true);
+ expect(isConfigSchema(schema.nullable(schema.string()))).toBe(true);
+ expect(isConfigSchema(schema.number())).toBe(true);
+ expect(isConfigSchema(schema.object({}))).toBe(true);
+ expect(isConfigSchema(schema.oneOf([schema.string()]))).toBe(true);
+ expect(isConfigSchema(schema.recordOf(schema.string(), schema.object({})))).toBe(true);
+ expect(isConfigSchema(schema.string())).toBe(true);
+ expect(isConfigSchema(schema.stream())).toBe(true);
+ });
+
+ it('returns false for every javascript data type', () => {
+ expect(isConfigSchema('foo')).toBe(false);
+ expect(isConfigSchema(42)).toBe(false);
+ expect(isConfigSchema(new Date())).toBe(false);
+ expect(isConfigSchema(null)).toBe(false);
+ expect(isConfigSchema(undefined)).toBe(false);
+ expect(isConfigSchema([1, 2, 3])).toBe(false);
+ expect(isConfigSchema({ foo: 'bar' })).toBe(false);
+ expect(isConfigSchema(function() {})).toBe(false);
+ });
+
+ it('returns true as long as `__isKbnConfigSchemaType` is true', () => {
+ expect(isConfigSchema({ __isKbnConfigSchemaType: true })).toBe(true);
+ });
+});
diff --git a/src/plugins/data/public/search/search_strategy/index.ts b/packages/kbn-config-schema/src/typeguards/is_config_schema.ts
similarity index 79%
rename from src/plugins/data/public/search/search_strategy/index.ts
rename to packages/kbn-config-schema/src/typeguards/is_config_schema.ts
index e3de2ea46e3ec..20e68ab2ead25 100644
--- a/src/plugins/data/public/search/search_strategy/index.ts
+++ b/packages/kbn-config-schema/src/typeguards/is_config_schema.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-export { SearchError, getSearchErrorType } from './search_error';
+import { Type } from '../types';
-export { SearchStrategyProvider, SearchStrategySearchParams } from './types';
-
-export { defaultSearchStrategy } from './default_search_strategy';
+export function isConfigSchema(obj: any): obj is Type {
+ return obj ? obj.__isKbnConfigSchemaType === true : false;
+}
diff --git a/packages/kbn-config-schema/src/types/type.ts b/packages/kbn-config-schema/src/types/type.ts
index 6d5ddf6b24afb..5ca16c61399e7 100644
--- a/packages/kbn-config-schema/src/types/type.ts
+++ b/packages/kbn-config-schema/src/types/type.ts
@@ -32,6 +32,9 @@ export abstract class Type {
// sets the value to `null` while still keeping the type.
public readonly type: V = null! as V;
+ // used for the `isConfigSchema` typeguard
+ public readonly __isKbnConfigSchemaType = true;
+
/**
* Internal "schema" backed by Joi.
* @type {Schema}
diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts
index d67b957416753..cc564dd4a8387 100644
--- a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts
+++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts
@@ -146,6 +146,7 @@ describe('OptimizerConfig::parseOptions()', () => {
/x-pack/plugins,
/plugins,
/examples,
+ /x-pack/examples,
-extra,
],
"profileWebpack": false,
diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts
index 1c8ae265bf6bb..7e1514058446b 100644
--- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts
+++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts
@@ -91,14 +91,14 @@ export class OptimizerConfig {
/**
* BEWARE: this needs to stay roughly synchronized with
- * `src/core/server/config/env.ts` which determins which paths
+ * `src/core/server/config/env.ts` which determines which paths
* should be searched for plugins to load
*/
const pluginScanDirs = options.pluginScanDirs || [
Path.resolve(repoRoot, 'src/plugins'),
...(oss ? [] : [Path.resolve(repoRoot, 'x-pack/plugins')]),
Path.resolve(repoRoot, 'plugins'),
- ...(examples ? [Path.resolve('examples')] : []),
+ ...(examples ? [Path.resolve('examples'), Path.resolve('x-pack/examples')] : []),
Path.resolve(repoRoot, '../kibana-extra'),
];
if (!pluginScanDirs.every(p => Path.isAbsolute(p))) {
diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json
index 7c5d6a62a11ca..c8614b1df9d5d 100644
--- a/packages/kbn-ui-shared-deps/package.json
+++ b/packages/kbn-ui-shared-deps/package.json
@@ -9,7 +9,7 @@
"kbn:watch": "node scripts/build --watch"
},
"dependencies": {
- "@elastic/charts": "18.2.2",
+ "@elastic/charts": "18.3.0",
"@elastic/eui": "21.0.1",
"@kbn/i18n": "1.0.0",
"abortcontroller-polyfill": "^1.4.0",
diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts
index 44b6c39556afd..a87e2aa11f2c0 100644
--- a/src/cli/cluster/cluster_manager.ts
+++ b/src/cli/cluster/cluster_manager.ts
@@ -263,7 +263,7 @@ export class ClusterManager {
...pluginInternalDirsIgnore,
fromRoot('src/legacy/server/sass/__tmp__'),
fromRoot('x-pack/legacy/plugins/reporting/.chromium'),
- fromRoot('x-pack/legacy/plugins/siem/cypress'),
+ fromRoot('x-pack/plugins/siem/cypress'),
fromRoot('x-pack/legacy/plugins/apm/e2e'),
fromRoot('x-pack/legacy/plugins/apm/scripts'),
fromRoot('x-pack/legacy/plugins/canvas/canvas_plugin_src'), // prevents server from restarting twice for Canvas plugin changes,
diff --git a/src/core/server/config/env.test.ts b/src/core/server/config/env.test.ts
index c244012e34469..0fffcc44781d9 100644
--- a/src/core/server/config/env.test.ts
+++ b/src/core/server/config/env.test.ts
@@ -164,6 +164,17 @@ test('pluginSearchPaths contains examples plugins path if --run-examples flag is
expect(env.pluginSearchPaths).toContain('/some/home/dir/examples');
});
+test('pluginSearchPaths contains x-pack/examples plugins path if --run-examples flag is true', () => {
+ const env = new Env(
+ '/some/home/dir',
+ getEnvOptions({
+ cliArgs: { runExamples: true },
+ })
+ );
+
+ expect(env.pluginSearchPaths).toContain('/some/home/dir/x-pack/examples');
+});
+
test('pluginSearchPaths does not contains examples plugins path if --run-examples flag is false', () => {
const env = new Env(
'/some/home/dir',
@@ -174,3 +185,14 @@ test('pluginSearchPaths does not contains examples plugins path if --run-example
expect(env.pluginSearchPaths).not.toContain('/some/home/dir/examples');
});
+
+test('pluginSearchPaths does not contains x-pack/examples plugins path if --run-examples flag is false', () => {
+ const env = new Env(
+ '/some/home/dir',
+ getEnvOptions({
+ cliArgs: { runExamples: false },
+ })
+ );
+
+ expect(env.pluginSearchPaths).not.toContain('/some/home/dir/x-pack/examples');
+});
diff --git a/src/core/server/config/env.ts b/src/core/server/config/env.ts
index 05a8f40a09a88..d8068c5b383fa 100644
--- a/src/core/server/config/env.ts
+++ b/src/core/server/config/env.ts
@@ -109,7 +109,9 @@ export class Env {
resolve(this.homeDir, 'src', 'plugins'),
...(options.cliArgs.oss ? [] : [resolve(this.homeDir, 'x-pack', 'plugins')]),
resolve(this.homeDir, 'plugins'),
- ...(options.cliArgs.runExamples ? [resolve(this.homeDir, 'examples')] : []),
+ ...(options.cliArgs.runExamples
+ ? [resolve(this.homeDir, 'examples'), resolve(this.homeDir, 'x-pack', 'examples')]
+ : []),
resolve(this.homeDir, '..', 'kibana-extra'),
];
diff --git a/src/core/server/http/router/router.ts b/src/core/server/http/router/router.ts
index b4e7fc2a989b6..69402a74eda5f 100644
--- a/src/core/server/http/router/router.ts
+++ b/src/core/server/http/router/router.ts
@@ -20,7 +20,7 @@
import { Request, ResponseObject, ResponseToolkit } from 'hapi';
import Boom from 'boom';
-import { Type } from '@kbn/config-schema';
+import { isConfigSchema } from '@kbn/config-schema';
import { Logger } from '../../logging';
import { KibanaRequest } from './request';
import { KibanaResponseFactory, kibanaResponseFactory, IKibanaResponse } from './response';
@@ -139,7 +139,7 @@ function routeSchemasFromRouteConfig
(
if (route.validate !== false) {
Object.entries(route.validate).forEach(([key, schema]) => {
- if (!(schema instanceof Type || typeof schema === 'function')) {
+ if (!(isConfigSchema(schema) || typeof schema === 'function')) {
throw new Error(
`Expected a valid validation logic declared with '@kbn/config-schema' package or a RouteValidationFunction at key: [${key}].`
);
diff --git a/src/core/server/http/router/validator/validator.ts b/src/core/server/http/router/validator/validator.ts
index 97dd2bc894f81..6c766e69f0f37 100644
--- a/src/core/server/http/router/validator/validator.ts
+++ b/src/core/server/http/router/validator/validator.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { ValidationError, Type, schema, ObjectType } from '@kbn/config-schema';
+import { ValidationError, Type, schema, ObjectType, isConfigSchema } from '@kbn/config-schema';
import { Stream } from 'stream';
import { RouteValidationError } from './validator_error';
@@ -236,7 +236,7 @@ export class RouteValidator
{
data?: unknown,
namespace?: string
): RouteValidationResultType {
- if (validationRule instanceof Type) {
+ if (isConfigSchema(validationRule)) {
return validationRule.validate(data, {}, namespace);
} else if (typeof validationRule === 'function') {
return this.validateFunction(validationRule, data, namespace);
diff --git a/src/core/server/legacy/legacy_service.test.mocks.ts b/src/core/server/legacy/legacy_service.test.mocks.ts
index 451a75ced7ae2..9ad554d63add0 100644
--- a/src/core/server/legacy/legacy_service.test.mocks.ts
+++ b/src/core/server/legacy/legacy_service.test.mocks.ts
@@ -30,6 +30,11 @@ export const findLegacyPluginSpecsMock = jest.fn().mockImplementation((settings:
uiExports: {},
navLinks: [],
}));
-jest.doMock('./plugins/find_legacy_plugin_specs.ts', () => ({
+jest.doMock('./plugins/find_legacy_plugin_specs', () => ({
findLegacyPluginSpecs: findLegacyPluginSpecsMock,
}));
+
+export const logLegacyThirdPartyPluginDeprecationWarningMock = jest.fn();
+jest.doMock('./plugins/log_legacy_plugins_warning', () => ({
+ logLegacyThirdPartyPluginDeprecationWarning: logLegacyThirdPartyPluginDeprecationWarningMock,
+}));
diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts
index 0c4e58f6a8da1..a75f7dda302c2 100644
--- a/src/core/server/legacy/legacy_service.test.ts
+++ b/src/core/server/legacy/legacy_service.test.ts
@@ -22,7 +22,10 @@ jest.mock('../../../cli/cluster/cluster_manager');
jest.mock('./config/legacy_deprecation_adapters', () => ({
convertLegacyDeprecationProvider: (provider: any) => Promise.resolve(provider),
}));
-import { findLegacyPluginSpecsMock } from './legacy_service.test.mocks';
+import {
+ findLegacyPluginSpecsMock,
+ logLegacyThirdPartyPluginDeprecationWarningMock,
+} from './legacy_service.test.mocks';
import { BehaviorSubject, throwError } from 'rxjs';
@@ -476,6 +479,38 @@ describe('#discoverPlugins()', () => {
expect(configService.addDeprecationProvider).toHaveBeenCalledWith('', 'providerA');
expect(configService.addDeprecationProvider).toHaveBeenCalledWith('', 'providerB');
});
+
+ it(`logs deprecations for legacy third party plugins`, async () => {
+ const pluginSpecs = [
+ { getId: () => 'pluginA', getDeprecationsProvider: () => undefined },
+ { getId: () => 'pluginB', getDeprecationsProvider: () => undefined },
+ ];
+ findLegacyPluginSpecsMock.mockImplementation(
+ settings =>
+ Promise.resolve({
+ pluginSpecs,
+ pluginExtendedConfig: settings,
+ disabledPluginSpecs: [],
+ uiExports: {},
+ navLinks: [],
+ }) as any
+ );
+
+ const legacyService = new LegacyService({
+ coreId,
+ env,
+ logger,
+ configService: configService as any,
+ });
+
+ await legacyService.discoverPlugins();
+
+ expect(logLegacyThirdPartyPluginDeprecationWarningMock).toHaveBeenCalledTimes(1);
+ expect(logLegacyThirdPartyPluginDeprecationWarningMock).toHaveBeenCalledWith({
+ specs: pluginSpecs,
+ log: expect.any(Object),
+ });
+ });
});
test('Sets the server.uuid property on the legacy configuration', async () => {
diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts
index fd3ebfe120599..b95362e1ea26e 100644
--- a/src/core/server/legacy/legacy_service.ts
+++ b/src/core/server/legacy/legacy_service.ts
@@ -28,7 +28,7 @@ import { DevConfig, DevConfigType, config as devConfig } from '../dev';
import { BasePathProxyServer, HttpConfig, HttpConfigType, config as httpConfig } from '../http';
import { Logger } from '../logging';
import { PathConfigType } from '../path';
-import { findLegacyPluginSpecs } from './plugins';
+import { findLegacyPluginSpecs, logLegacyThirdPartyPluginDeprecationWarning } from './plugins';
import { convertLegacyDeprecationProvider } from './config';
import {
ILegacyInternals,
@@ -133,6 +133,11 @@ export class LegacyService implements CoreService {
this.coreContext.env.packageInfo
);
+ logLegacyThirdPartyPluginDeprecationWarning({
+ specs: pluginSpecs,
+ log: this.log,
+ });
+
this.legacyPlugins = {
pluginSpecs,
disabledPluginSpecs,
diff --git a/src/core/server/legacy/plugins/index.ts b/src/core/server/legacy/plugins/index.ts
index a6d55e1da7839..7ec5dbc1983ab 100644
--- a/src/core/server/legacy/plugins/index.ts
+++ b/src/core/server/legacy/plugins/index.ts
@@ -18,3 +18,4 @@
*/
export { findLegacyPluginSpecs } from './find_legacy_plugin_specs';
+export { logLegacyThirdPartyPluginDeprecationWarning } from './log_legacy_plugins_warning';
diff --git a/src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts b/src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts
new file mode 100644
index 0000000000000..1790b096a71ae
--- /dev/null
+++ b/src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts
@@ -0,0 +1,90 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { loggerMock } from '../../logging/logger.mock';
+import { logLegacyThirdPartyPluginDeprecationWarning } from './log_legacy_plugins_warning';
+import { LegacyPluginSpec } from '../types';
+
+const createPluginSpec = ({ id, path }: { id: string; path: string }): LegacyPluginSpec => {
+ return {
+ getId: () => id,
+ getExpectedKibanaVersion: () => 'kibana',
+ getConfigPrefix: () => 'plugin.config',
+ getDeprecationsProvider: () => undefined,
+ getPack: () => ({
+ getPath: () => path,
+ }),
+ };
+};
+
+describe('logLegacyThirdPartyPluginDeprecationWarning', () => {
+ let log: ReturnType;
+
+ beforeEach(() => {
+ log = loggerMock.create();
+ });
+
+ it('logs warning for third party plugins', () => {
+ logLegacyThirdPartyPluginDeprecationWarning({
+ specs: [createPluginSpec({ id: 'plugin', path: '/some-external-path' })],
+ log,
+ });
+ expect(log.warn).toHaveBeenCalledTimes(1);
+ expect(log.warn.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ "Some installed third party plugin(s) [plugin] are using the legacy plugin format and will no longer work in a future Kibana release. Please refer to https://www.elastic.co/guide/en/kibana/master/breaking-changes-8.0.html for a list of breaking changes and https://github.com/elastic/kibana/blob/master/src/core/MIGRATION.md for documentation on how to migrate legacy plugins.",
+ ]
+ `);
+ });
+
+ it('lists all the deprecated plugins and only log once', () => {
+ logLegacyThirdPartyPluginDeprecationWarning({
+ specs: [
+ createPluginSpec({ id: 'pluginA', path: '/abs/path/to/pluginA' }),
+ createPluginSpec({ id: 'pluginB', path: '/abs/path/to/pluginB' }),
+ createPluginSpec({ id: 'pluginC', path: '/abs/path/to/pluginC' }),
+ ],
+ log,
+ });
+ expect(log.warn).toHaveBeenCalledTimes(1);
+ expect(log.warn.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ "Some installed third party plugin(s) [pluginA, pluginB, pluginC] are using the legacy plugin format and will no longer work in a future Kibana release. Please refer to https://www.elastic.co/guide/en/kibana/master/breaking-changes-8.0.html for a list of breaking changes and https://github.com/elastic/kibana/blob/master/src/core/MIGRATION.md for documentation on how to migrate legacy plugins.",
+ ]
+ `);
+ });
+
+ it('does not log warning for internal legacy plugins', () => {
+ logLegacyThirdPartyPluginDeprecationWarning({
+ specs: [
+ createPluginSpec({
+ id: 'plugin',
+ path: '/absolute/path/to/kibana/src/legacy/core_plugins',
+ }),
+ createPluginSpec({
+ id: 'plugin',
+ path: '/absolute/path/to/kibana/x-pack',
+ }),
+ ],
+ log,
+ });
+
+ expect(log.warn).not.toHaveBeenCalled();
+ });
+});
diff --git a/src/core/server/legacy/plugins/log_legacy_plugins_warning.ts b/src/core/server/legacy/plugins/log_legacy_plugins_warning.ts
new file mode 100644
index 0000000000000..f9c3dcbf554cb
--- /dev/null
+++ b/src/core/server/legacy/plugins/log_legacy_plugins_warning.ts
@@ -0,0 +1,52 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Logger } from '../../logging';
+import { LegacyPluginSpec } from '../types';
+
+const internalPaths = ['/src/legacy/core_plugins', '/x-pack'];
+
+const breakingChangesUrl =
+ 'https://www.elastic.co/guide/en/kibana/master/breaking-changes-8.0.html';
+const migrationGuideUrl = 'https://github.com/elastic/kibana/blob/master/src/core/MIGRATION.md';
+
+export const logLegacyThirdPartyPluginDeprecationWarning = ({
+ specs,
+ log,
+}: {
+ specs: LegacyPluginSpec[];
+ log: Logger;
+}) => {
+ const thirdPartySpecs = specs.filter(isThirdPartyPluginSpec);
+ if (thirdPartySpecs.length > 0) {
+ const pluginIds = thirdPartySpecs.map(spec => spec.getId());
+ log.warn(
+ `Some installed third party plugin(s) [${pluginIds.join(
+ ', '
+ )}] are using the legacy plugin format and will no longer work in a future Kibana release. ` +
+ `Please refer to ${breakingChangesUrl} for a list of breaking changes ` +
+ `and ${migrationGuideUrl} for documentation on how to migrate legacy plugins.`
+ );
+ }
+};
+
+const isThirdPartyPluginSpec = (spec: LegacyPluginSpec): boolean => {
+ const pluginPath = spec.getPack().getPath();
+ return !internalPaths.some(internalPath => pluginPath.indexOf(internalPath) > -1);
+};
diff --git a/src/core/server/legacy/types.ts b/src/core/server/legacy/types.ts
index 38cb9e6835ce9..2567ca790e04f 100644
--- a/src/core/server/legacy/types.ts
+++ b/src/core/server/legacy/types.ts
@@ -98,6 +98,7 @@ export interface LegacyPluginSpec {
getExpectedKibanaVersion: () => string;
getConfigPrefix: () => string;
getDeprecationsProvider: () => LegacyConfigDeprecationProvider | undefined;
+ getPack: () => LegacyPluginPack;
}
/**
diff --git a/src/core/server/plugins/plugin.ts b/src/core/server/plugins/plugin.ts
index 7c67ab7a48df1..d7cfaa14d2343 100644
--- a/src/core/server/plugins/plugin.ts
+++ b/src/core/server/plugins/plugin.ts
@@ -21,7 +21,7 @@ import { join } from 'path';
import typeDetect from 'type-detect';
import { Subject } from 'rxjs';
import { first } from 'rxjs/operators';
-import { Type } from '@kbn/config-schema';
+import { isConfigSchema } from '@kbn/config-schema';
import { Logger } from '../logging';
import {
@@ -150,7 +150,7 @@ export class PluginWrapper<
}
const configDescriptor = pluginDefinition.config;
- if (!(configDescriptor.schema instanceof Type)) {
+ if (!isConfigSchema(configDescriptor.schema)) {
throw new Error('Configuration schema expected to be an instance of Type');
}
return configDescriptor;
diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md
index dd08df06c73d2..7ca5c75f19e8f 100644
--- a/src/core/server/server.api.md
+++ b/src/core/server/server.api.md
@@ -2468,11 +2468,11 @@ export const validBodyOutput: readonly ["data", "stream"];
// Warnings were encountered during analysis:
//
// src/core/server/http/router/response.ts:316:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:162:3 - (ae-forgotten-export) The symbol "VarsProvider" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:163:3 - (ae-forgotten-export) The symbol "VarsReplacer" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:164:3 - (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:165:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:166:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
+// src/core/server/legacy/types.ts:163:3 - (ae-forgotten-export) The symbol "VarsProvider" needs to be exported by the entry point index.d.ts
+// src/core/server/legacy/types.ts:164:3 - (ae-forgotten-export) The symbol "VarsReplacer" needs to be exported by the entry point index.d.ts
+// src/core/server/legacy/types.ts:165:3 - (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts
+// src/core/server/legacy/types.ts:166:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts
+// src/core/server/legacy/types.ts:167:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:232:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts
diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts
index 8ed64f004c9be..43114b2edccfc 100644
--- a/src/dev/storybook/aliases.ts
+++ b/src/dev/storybook/aliases.ts
@@ -24,6 +24,6 @@ export const storybookAliases = {
drilldowns: 'x-pack/plugins/drilldowns/scripts/storybook.js',
embeddable: 'src/plugins/embeddable/scripts/storybook.js',
infra: 'x-pack/legacy/plugins/infra/scripts/storybook.js',
- siem: 'x-pack/legacy/plugins/siem/scripts/storybook.js',
+ siem: 'x-pack/plugins/siem/scripts/storybook.js',
ui_actions: 'x-pack/plugins/advanced_ui_actions/scripts/storybook.js',
};
diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts
index 34756912fc247..01d8a30b598c1 100644
--- a/src/dev/typescript/projects.ts
+++ b/src/dev/typescript/projects.ts
@@ -27,7 +27,7 @@ export const PROJECTS = [
new Project(resolve(REPO_ROOT, 'test/tsconfig.json'), { name: 'kibana/test' }),
new Project(resolve(REPO_ROOT, 'x-pack/tsconfig.json')),
new Project(resolve(REPO_ROOT, 'x-pack/test/tsconfig.json'), { name: 'x-pack/test' }),
- new Project(resolve(REPO_ROOT, 'x-pack/legacy/plugins/siem/cypress/tsconfig.json'), {
+ new Project(resolve(REPO_ROOT, 'x-pack/plugins/siem/cypress/tsconfig.json'), {
name: 'siem/cypress',
}),
new Project(resolve(REPO_ROOT, 'x-pack/legacy/plugins/apm/e2e/tsconfig.json'), {
@@ -44,6 +44,9 @@ export const PROJECTS = [
...glob
.sync('examples/*/tsconfig.json', { cwd: REPO_ROOT })
.map(path => new Project(resolve(REPO_ROOT, path))),
+ ...glob
+ .sync('x-pack/examples/*/tsconfig.json', { cwd: REPO_ROOT })
+ .map(path => new Project(resolve(REPO_ROOT, path))),
...glob
.sync('test/plugin_functional/plugins/*/tsconfig.json', { cwd: REPO_ROOT })
.map(path => new Project(resolve(REPO_ROOT, path))),
diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js
index 20c46765dcb30..ea0d5ad3790b1 100644
--- a/src/legacy/core_plugins/kibana/public/kibana.js
+++ b/src/legacy/core_plugins/kibana/public/kibana.js
@@ -49,8 +49,9 @@ import { showAppRedirectNotification } from '../../../../plugins/kibana_legacy/p
import 'leaflet';
import { localApplicationService } from './local_application_service';
-npSetup.plugins.kibanaLegacy.forwardApp('doc', 'discover', { keepPrefix: true });
-npSetup.plugins.kibanaLegacy.forwardApp('context', 'discover', { keepPrefix: true });
+npSetup.plugins.kibanaLegacy.registerLegacyAppAlias('doc', 'discover', { keepPrefix: true });
+npSetup.plugins.kibanaLegacy.registerLegacyAppAlias('context', 'discover', { keepPrefix: true });
+
localApplicationService.attachToAngular(routes);
routes.enable();
diff --git a/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts b/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts
index 14564cfd9ee78..f38c410e6832f 100644
--- a/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts
+++ b/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts
@@ -98,14 +98,29 @@ export class LocalApplicationService {
}
});
- npStart.plugins.kibanaLegacy.getForwards().forEach(({ legacyAppId, newAppId, keepPrefix }) => {
- angularRouteManager.when(matchAllWithPrefix(legacyAppId), {
- resolveRedirectTo: ($location: ILocationService) => {
- const url = $location.url();
- return `/${newAppId}${keepPrefix ? url : url.replace(legacyAppId, '')}`;
+ npStart.plugins.kibanaLegacy.getForwards().forEach(forwardDefinition => {
+ angularRouteManager.when(matchAllWithPrefix(forwardDefinition.legacyAppId), {
+ outerAngularWrapperRoute: true,
+ reloadOnSearch: false,
+ reloadOnUrl: false,
+ template: '',
+ controller($location: ILocationService) {
+ const newPath = forwardDefinition.rewritePath($location.url());
+ npStart.core.application.navigateToApp(forwardDefinition.newAppId, { path: newPath });
},
});
});
+
+ npStart.plugins.kibanaLegacy
+ .getLegacyAppAliases()
+ .forEach(({ legacyAppId, newAppId, keepPrefix }) => {
+ angularRouteManager.when(matchAllWithPrefix(legacyAppId), {
+ resolveRedirectTo: ($location: ILocationService) => {
+ const url = $location.url();
+ return `/${newAppId}${keepPrefix ? url : url.replace(legacyAppId, '')}`;
+ },
+ });
+ });
}
}
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.js.snap
deleted file mode 100644
index 59b275c7708a4..0000000000000
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.js.snap
+++ /dev/null
@@ -1,205 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`CreateIndexPatternWizard defaults to the loading state 1`] = `
-
-
-
-
-
-
-
-`;
-
-exports[`CreateIndexPatternWizard renders index pattern step when there are indices 1`] = `
-
-
-
-
-
-
-
-`;
-
-exports[`CreateIndexPatternWizard renders the empty state when there are no indices 1`] = `
-
-
-
-
-
-
-
-`;
-
-exports[`CreateIndexPatternWizard renders time field step when step is set to 2 1`] = `
-
-
-
-
-
-
-
-`;
-
-exports[`CreateIndexPatternWizard renders when there are no indices but there are remote clusters 1`] = `
-
-
-
-
-
-
-
-`;
-
-exports[`CreateIndexPatternWizard shows system indices even if there are no other indices if the include system indices is toggled 1`] = `
-
-
-
-
-
-
-
-`;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap
new file mode 100644
index 0000000000000..09a06bd8827ce
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap
@@ -0,0 +1,312 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`CreateIndexPatternWizard defaults to the loading state 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`CreateIndexPatternWizard renders index pattern step when there are indices 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`CreateIndexPatternWizard renders the empty state when there are no indices 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`CreateIndexPatternWizard renders time field step when step is set to 2 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`CreateIndexPatternWizard renders when there are no indices but there are remote clusters 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`CreateIndexPatternWizard shows system indices even if there are no other indices if the include system indices is toggled 1`] = `
+
+
+
+
+
+
+
+`;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx
index 648bf7f8f9738..d8f677b7f6089 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx
@@ -48,7 +48,7 @@ interface StepIndexPatternProps {
esService: DataPublicPluginStart['search']['__LEGACY']['esClient'];
savedObjectsClient: SavedObjectsClient;
indexPatternCreationType: IndexPatternCreationConfig;
- goToNextStep: () => void;
+ goToNextStep: (query: string) => void;
initialQuery?: string;
uiSettings: IUiSettingsClient;
}
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx
similarity index 55%
rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.js
rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx
index 941f87d4d9fd2..45af98661eda3 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx
@@ -21,17 +21,12 @@ import React from 'react';
import { shallow } from 'enzyme';
import { CreateIndexPatternWizard } from './create_index_pattern_wizard';
-const mockIndexPatternCreationType = {
- getIndexPatternType: () => 'default',
- getIndexPatternName: () => 'name',
- getIsBeta: () => false,
- checkIndicesForErrors: () => false,
- getShowSystemIndices: () => false,
- renderPrompt: () => {},
- getIndexPatternMappings: () => {
- return {};
- },
-};
+import { coreMock } from '../../../../../../../../core/public/mocks';
+import { dataPluginMock } from '../../../../../../../../plugins/data/public/mocks';
+import { IndexPatternCreationConfig } from '../../../../../../../../plugins/index_pattern_management/public';
+import { IndexPattern } from '../../../../../../../../plugins/data/public';
+import { SavedObjectsClient } from '../../../../../../../../core/public';
+
jest.mock('./components/step_index_pattern', () => ({ StepIndexPattern: 'StepIndexPattern' }));
jest.mock('./components/step_time_field', () => ({ StepTimeField: 'StepTimeField' }));
jest.mock('./components/header', () => ({ Header: 'Header' }));
@@ -46,39 +41,36 @@ jest.mock('ui/chrome', () => ({
addBasePath: () => {},
}));
-const loadingDataDocUrl = '';
+const { savedObjects, overlays, uiSettings } = coreMock.createStart();
+const { indexPatterns, search } = dataPluginMock.createStartContract();
+const mockIndexPatternCreationType = new IndexPatternCreationConfig({
+ type: 'default',
+ name: 'name',
+});
+
const initialQuery = '';
const services = {
- es: {},
- indexPatterns: {},
- savedObjectsClient: {},
- config: {},
- changeUrl: () => {},
- scopeApply: () => {},
-
+ es: search.__LEGACY.esClient,
+ indexPatterns,
+ savedObjectsClient: savedObjects.client as SavedObjectsClient,
+ uiSettings,
+ changeUrl: jest.fn(),
+ openConfirm: overlays.openConfirm,
indexPatternCreationType: mockIndexPatternCreationType,
};
describe('CreateIndexPatternWizard', () => {
- it(`defaults to the loading state`, async () => {
+ test(`defaults to the loading state`, () => {
const component = shallow(
-
+
);
expect(component).toMatchSnapshot();
});
- it('renders the empty state when there are no indices', async () => {
+ test('renders the empty state when there are no indices', async () => {
const component = shallow(
-
+
);
component.setState({
@@ -91,13 +83,9 @@ describe('CreateIndexPatternWizard', () => {
expect(component).toMatchSnapshot();
});
- it('renders when there are no indices but there are remote clusters', async () => {
+ test('renders when there are no indices but there are remote clusters', async () => {
const component = shallow(
-
+
);
component.setState({
@@ -110,13 +98,9 @@ describe('CreateIndexPatternWizard', () => {
expect(component).toMatchSnapshot();
});
- it('shows system indices even if there are no other indices if the include system indices is toggled', async () => {
+ test('shows system indices even if there are no other indices if the include system indices is toggled', async () => {
const component = shallow(
-
+
);
component.setState({
@@ -129,13 +113,9 @@ describe('CreateIndexPatternWizard', () => {
expect(component).toMatchSnapshot();
});
- it('renders index pattern step when there are indices', async () => {
+ test('renders index pattern step when there are indices', async () => {
const component = shallow(
-
+
);
component.setState({
@@ -147,13 +127,9 @@ describe('CreateIndexPatternWizard', () => {
expect(component).toMatchSnapshot();
});
- it('renders time field step when step is set to 2', async () => {
+ test('renders time field step when step is set to 2', async () => {
const component = shallow(
-
+
);
component.setState({
@@ -166,37 +142,30 @@ describe('CreateIndexPatternWizard', () => {
expect(component).toMatchSnapshot();
});
- it('invokes the provided services when creating an index pattern', async () => {
- const get = jest.fn();
- const set = jest.fn();
+ test('invokes the provided services when creating an index pattern', async () => {
const create = jest.fn().mockImplementation(() => 'id');
const clear = jest.fn();
- const changeUrl = jest.fn();
-
- const component = shallow(
- ({
- create,
- }),
- clearCache: clear,
- },
- changeUrl,
- indexPatternCreationType: mockIndexPatternCreationType,
- }}
- />
+ services.indexPatterns.clearCache = clear;
+ const indexPattern = ({
+ id: '1',
+ title: 'my-fake-index-pattern',
+ timeFieldName: 'timestamp',
+ fields: [],
+ create,
+ } as unknown) as IndexPattern;
+ services.indexPatterns.make = async () => {
+ return indexPattern;
+ };
+
+ const component = shallow(
+
);
component.setState({ indexPattern: 'foo' });
- await component.instance().createIndexPattern(null, 'id');
- expect(get).toBeCalled();
+ await component.instance().createIndexPattern(undefined, 'id');
+ expect(services.uiSettings.get).toBeCalled();
expect(create).toBeCalled();
expect(clear).toBeCalledWith('id');
- expect(changeUrl).toBeCalledWith(`/management/kibana/index_patterns/id`);
+ expect(services.changeUrl).toBeCalledWith(`/management/kibana/index_patterns/id`);
});
});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.tsx
similarity index 63%
rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.js
rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.tsx
index 1a93188edd6cc..4166d48349d35 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.tsx
@@ -17,11 +17,11 @@
* under the License.
*/
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
+import React, { ReactElement, Component } from 'react';
-import { EuiGlobalToastList } from '@elastic/eui';
+import { EuiGlobalToastList, EuiGlobalToastListToast } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@kbn/i18n';
import { StepIndexPattern } from './components/step_index_pattern';
import { StepTimeField } from './components/step_time_field';
@@ -31,41 +31,61 @@ import { EmptyState } from './components/empty_state';
import { MAX_SEARCH_SIZE } from './constants';
import { ensureMinimumTime, getIndices } from './lib';
-import { i18n } from '@kbn/i18n';
-
-export class CreateIndexPatternWizard extends Component {
- static propTypes = {
- initialQuery: PropTypes.string,
- services: PropTypes.shape({
- es: PropTypes.object.isRequired,
- indexPatterns: PropTypes.object.isRequired,
- savedObjectsClient: PropTypes.object.isRequired,
- indexPatternCreationType: PropTypes.object.isRequired,
- config: PropTypes.object.isRequired,
- changeUrl: PropTypes.func.isRequired,
- openConfirm: PropTypes.func.isRequired,
- }).isRequired,
+import {
+ SavedObjectsClient,
+ IUiSettingsClient,
+ OverlayStart,
+} from '../../../../../../../../core/public';
+import { DataPublicPluginStart } from '../../../../../../../../plugins/data/public';
+import { IndexPatternCreationConfig } from '../../../../../../../../plugins/index_pattern_management/public';
+import { MatchedIndex } from './types';
+
+interface CreateIndexPatternWizardProps {
+ initialQuery: string;
+ services: {
+ indexPatternCreationType: IndexPatternCreationConfig;
+ es: DataPublicPluginStart['search']['__LEGACY']['esClient'];
+ indexPatterns: DataPublicPluginStart['indexPatterns'];
+ savedObjectsClient: SavedObjectsClient;
+ uiSettings: IUiSettingsClient;
+ changeUrl: (url: string) => void;
+ openConfirm: OverlayStart['openConfirm'];
};
+}
- constructor(props) {
- super(props);
- this.indexPatternCreationType = this.props.services.indexPatternCreationType;
- this.state = {
- step: 1,
- indexPattern: '',
- allIndices: [],
- remoteClustersExist: false,
- isInitiallyLoadingIndices: true,
- isIncludingSystemIndices: false,
- toasts: [],
- };
- }
+interface CreateIndexPatternWizardState {
+ step: number;
+ indexPattern: string;
+ allIndices: MatchedIndex[];
+ remoteClustersExist: boolean;
+ isInitiallyLoadingIndices: boolean;
+ isIncludingSystemIndices: boolean;
+ toasts: EuiGlobalToastListToast[];
+}
+
+export class CreateIndexPatternWizard extends Component<
+ CreateIndexPatternWizardProps,
+ CreateIndexPatternWizardState
+> {
+ state = {
+ step: 1,
+ indexPattern: '',
+ allIndices: [],
+ remoteClustersExist: false,
+ isInitiallyLoadingIndices: true,
+ isIncludingSystemIndices: false,
+ toasts: [],
+ };
async UNSAFE_componentWillMount() {
this.fetchData();
}
- catchAndWarn = async (asyncFn, errorValue, errorMsg) => {
+ catchAndWarn = async (
+ asyncFn: Promise,
+ errorValue: [] | string[],
+ errorMsg: ReactElement
+ ) => {
try {
return await asyncFn;
} catch (errors) {
@@ -109,22 +129,26 @@ export class CreateIndexPatternWizard extends Component {
// query local and remote indices, updating state independently
ensureMinimumTime(
this.catchAndWarn(
- getIndices(services.es, this.indexPatternCreationType, `*`, MAX_SEARCH_SIZE),
+ getIndices(services.es, services.indexPatternCreationType, `*`, MAX_SEARCH_SIZE),
[],
indicesFailMsg
)
- ).then(allIndices => this.setState({ allIndices, isInitiallyLoadingIndices: false }));
+ ).then((allIndices: MatchedIndex[]) =>
+ this.setState({ allIndices, isInitiallyLoadingIndices: false })
+ );
this.catchAndWarn(
// if we get an error from remote cluster query, supply fallback value that allows user entry.
// ['a'] is fallback value
- getIndices(services.es, this.indexPatternCreationType, `*:*`, 1),
+ getIndices(services.es, services.indexPatternCreationType, `*:*`, 1),
['a'],
clustersFailMsg
- ).then(remoteIndices => this.setState({ remoteClustersExist: !!remoteIndices.length }));
+ ).then((remoteIndices: string[] | MatchedIndex[]) =>
+ this.setState({ remoteClustersExist: !!remoteIndices.length })
+ );
};
- createIndexPattern = async (timeFieldName, indexPatternId) => {
+ createIndexPattern = async (timeFieldName: string | undefined, indexPatternId: string) => {
const { services } = this.props;
const { indexPattern } = this.state;
@@ -134,13 +158,13 @@ export class CreateIndexPatternWizard extends Component {
id: indexPatternId,
title: indexPattern,
timeFieldName,
- ...this.indexPatternCreationType.getIndexPatternMappings(),
+ ...services.indexPatternCreationType.getIndexPatternMappings(),
});
const createdId = await emptyPattern.create();
if (!createdId) {
const confirmMessage = i18n.translate('kbn.management.indexPattern.titleExistsLabel', {
- values: { title: this.title },
+ values: { title: emptyPattern.title },
defaultMessage: "An index pattern with the title '{title}' already exists.",
});
@@ -157,15 +181,15 @@ export class CreateIndexPatternWizard extends Component {
}
}
- if (!services.config.get('defaultIndex')) {
- await services.config.set('defaultIndex', createdId);
+ if (!services.uiSettings.get('defaultIndex')) {
+ await services.uiSettings.set('defaultIndex', createdId);
}
services.indexPatterns.clearCache(createdId);
services.changeUrl(`/management/kibana/index_patterns/${createdId}`);
};
- goToTimeFieldStep = indexPattern => {
+ goToTimeFieldStep = (indexPattern: string) => {
this.setState({ step: 2, indexPattern });
};
@@ -174,22 +198,23 @@ export class CreateIndexPatternWizard extends Component {
};
onChangeIncludingSystemIndices = () => {
- this.setState(state => ({
- isIncludingSystemIndices: !state.isIncludingSystemIndices,
+ this.setState(prevState => ({
+ isIncludingSystemIndices: !prevState.isIncludingSystemIndices,
}));
};
renderHeader() {
const { isIncludingSystemIndices } = this.state;
+ const { services } = this.props;
return (
);
}
@@ -208,7 +233,7 @@ export class CreateIndexPatternWizard extends Component {
return ;
}
- const hasDataIndices = allIndices.some(({ name }) => !name.startsWith('.'));
+ const hasDataIndices = allIndices.some(({ name }: MatchedIndex) => !name.startsWith('.'));
if (!hasDataIndices && !isIncludingSystemIndices && !remoteClustersExist) {
return ;
}
@@ -222,7 +247,7 @@ export class CreateIndexPatternWizard extends Component {
isIncludingSystemIndices={isIncludingSystemIndices}
esService={services.es}
savedObjectsClient={services.savedObjectsClient}
- indexPatternCreationType={this.indexPatternCreationType}
+ indexPatternCreationType={services.indexPatternCreationType}
goToNextStep={this.goToTimeFieldStep}
uiSettings={services.uiSettings}
/>
@@ -237,7 +262,7 @@ export class CreateIndexPatternWizard extends Component {
indexPatternsService={services.indexPatterns}
goToPreviousStep={this.goToIndexPatternStep}
createIndexPattern={this.createIndexPattern}
- indexPatternCreationType={this.indexPatternCreationType}
+ indexPatternCreationType={services.indexPatternCreationType}
/>
);
}
@@ -245,9 +270,9 @@ export class CreateIndexPatternWizard extends Component {
return null;
}
- removeToast = removedToast => {
+ removeToast = (id: string) => {
this.setState(prevState => ({
- toasts: prevState.toasts.filter(toast => toast.id !== removedToast.id),
+ toasts: prevState.toasts.filter(toast => toast.id !== id),
}));
};
@@ -263,7 +288,9 @@ export class CreateIndexPatternWizard extends Component {
{
+ this.removeToast(id);
+ }}
toastLifeTimeMs={6000}
/>
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js
index 47cb773258cb4..ed1fc026c560c 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js
@@ -36,17 +36,15 @@ uiRoutes.when('/management/kibana/index_pattern', {
$routeParams.type
);
const services = {
- config: npStart.core.uiSettings,
+ uiSettings: npStart.core.uiSettings,
es: npStart.plugins.data.search.__LEGACY.esClient,
indexPatterns: npStart.plugins.data.indexPatterns,
- $http: npStart.core.http,
savedObjectsClient: npStart.core.savedObjects.client,
indexPatternCreationType,
changeUrl: url => {
$scope.$evalAsync(() => kbnUrl.changePath(url));
},
openConfirm: npStart.core.overlays.openConfirm,
- uiSettings: npStart.core.uiSettings,
};
const initialQuery = $routeParams.id ? decodeURIComponent($routeParams.id) : undefined;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.test.ts b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.test.ts
index 40583af7177fe..b1500f8303b66 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.test.ts
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/lib/get_indices.test.ts
@@ -20,7 +20,7 @@
import { getIndices } from './get_indices';
import { IndexPatternCreationConfig } from '../../../../../../../../../plugins/index_pattern_management/public';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { LegacyApiCaller } from '../../../../../../../../../plugins/data/public/search';
+import { LegacyApiCaller } from '../../../../../../../../../plugins/data/public/search/legacy';
export const successfulResponse = {
hits: {
diff --git a/src/legacy/core_plugins/timelion/public/app.js b/src/legacy/core_plugins/timelion/public/app.js
index c15318d29e761..7f5c7d4664af8 100644
--- a/src/legacy/core_plugins/timelion/public/app.js
+++ b/src/legacy/core_plugins/timelion/public/app.js
@@ -27,10 +27,11 @@ import { fatalError, toastNotifications } from 'ui/notify';
import { timefilter } from 'ui/timefilter';
import { npStart } from 'ui/new_platform';
import { getSavedSheetBreadcrumbs, getCreateBreadcrumbs } from './breadcrumbs';
-import { getTimezone } from '../../vis_type_timelion/public';
+import { getTimezone } from '../../../../plugins/vis_type_timelion/public';
import 'uiExports/savedObjectTypes';
+require('ui/i18n');
require('ui/autoload/all');
// TODO: remove ui imports completely (move to plugins)
@@ -57,7 +58,7 @@ require('plugins/timelion/directives/timelion_options_sheet');
document.title = 'Timelion - Kibana';
-const app = require('ui/modules').get('apps/timelion', []);
+const app = require('ui/modules').get('apps/timelion', ['i18n', 'ngSanitize']);
require('ui/routes').enable();
diff --git a/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js b/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js
index 57262fda55e48..35ac883e5d99c 100644
--- a/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js
+++ b/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js
@@ -43,7 +43,7 @@
import _ from 'lodash';
import $ from 'jquery';
import PEG from 'pegjs';
-import grammar from 'raw-loader!../../../../../plugins/timelion/common/chain.peg';
+import grammar from 'raw-loader!../../../../../plugins/vis_type_timelion/common/chain.peg';
import timelionExpressionInputTemplate from './timelion_expression_input.html';
import {
SUGGESTION_TYPE,
@@ -52,7 +52,7 @@ import {
insertAtLocation,
} from './timelion_expression_input_helpers';
import { comboBoxKeyCodes } from '@elastic/eui';
-import { getArgValueSuggestions } from '../../../vis_type_timelion/public/helpers/arg_value_suggestions';
+import { npStart } from 'ui/new_platform';
const Parser = PEG.generate(grammar);
@@ -68,7 +68,7 @@ export function TimelionExpInput($http, $timeout) {
replace: true,
template: timelionExpressionInputTemplate,
link: function(scope, elem) {
- const argValueSuggestions = getArgValueSuggestions();
+ const argValueSuggestions = npStart.plugins.visTypeTimelion.getArgValueSuggestions();
const expressionInput = elem.find('[data-expression-input]');
const functionReference = {};
let suggestibleFunctionLocation = {};
diff --git a/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts b/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts
index cd40cbfa89ffe..34b389f5ff4ce 100644
--- a/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts
+++ b/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts
@@ -17,7 +17,8 @@
* under the License.
*/
-import '../../../../vis_type_timelion/public/flot';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import '../../../../../../plugins/vis_type_timelion/public/flot';
import _ from 'lodash';
import $ from 'jquery';
import moment from 'moment-timezone';
@@ -28,11 +29,14 @@ import {
calculateInterval,
DEFAULT_TIME_FORMAT,
// @ts-ignore
-} from '../../../../../../plugins/timelion/common/lib';
-import { tickFormatters } from '../../../../vis_type_timelion/public/helpers/tick_formatters';
+} from '../../../../../../plugins/vis_type_timelion/common/lib';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { tickFormatters } from '../../../../../../plugins/vis_type_timelion/public/helpers/tick_formatters';
import { TimelionVisualizationDependencies } from '../../plugin';
-import { xaxisFormatterProvider } from '../../../../vis_type_timelion/public/helpers/xaxis_formatter';
-import { generateTicksProvider } from '../../../../vis_type_timelion/public/helpers/tick_generator';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { xaxisFormatterProvider } from '../../../../../../plugins/vis_type_timelion/public/helpers/xaxis_formatter';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { generateTicksProvider } from '../../../../../../plugins/vis_type_timelion/public/helpers/tick_generator';
const DEBOUNCE_DELAY = 50;
diff --git a/src/legacy/core_plugins/vis_type_timelion/index.ts b/src/legacy/core_plugins/vis_type_timelion/index.ts
deleted file mode 100644
index 7bca5154c84fd..0000000000000
--- a/src/legacy/core_plugins/vis_type_timelion/index.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { resolve } from 'path';
-import { Legacy } from 'kibana';
-
-import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy/types';
-
-const timelionVisPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) =>
- new Plugin({
- id: 'timelion_vis',
- require: ['kibana', 'elasticsearch'],
- publicDir: resolve(__dirname, 'public'),
- uiExports: {
- styleSheetPaths: resolve(__dirname, 'public/index.scss'),
- hacks: [resolve(__dirname, 'public/legacy')],
- injectDefaultVars: server => ({}),
- },
- init: (server: Legacy.Server) => ({}),
- config(Joi: any) {
- return Joi.object({
- enabled: Joi.boolean().default(true),
- }).default();
- },
- });
-
-// eslint-disable-next-line import/no-default-export
-export default timelionVisPluginInitializer;
diff --git a/src/legacy/core_plugins/vis_type_timelion/package.json b/src/legacy/core_plugins/vis_type_timelion/package.json
deleted file mode 100644
index 9b09f98ce6caf..0000000000000
--- a/src/legacy/core_plugins/vis_type_timelion/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "timelion_vis",
- "version": "kibana"
-}
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/_index.scss b/src/legacy/core_plugins/vis_type_timelion/public/components/_index.scss
deleted file mode 100644
index 1d887f43ff9a1..0000000000000
--- a/src/legacy/core_plugins/vis_type_timelion/public/components/_index.scss
+++ /dev/null
@@ -1,2 +0,0 @@
-@import './panel';
-@import './timelion_expression_input';
diff --git a/src/legacy/server/logging/log_reporter.js b/src/legacy/server/logging/log_reporter.js
index 6e62a5ee284e3..b784d03a5b86e 100644
--- a/src/legacy/server/logging/log_reporter.js
+++ b/src/legacy/server/logging/log_reporter.js
@@ -30,7 +30,7 @@ import { LogInterceptor } from './log_interceptor';
// thrown every time we start the server.
// In order to keep using the legacy logger until we remove it I'm just adding
// a new hard limit here.
-process.stdout.setMaxListeners(15);
+process.stdout.setMaxListeners(25);
export function getLoggerStream({ events, config }) {
const squeeze = new Squeeze(events);
diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js
index f577a29ce90b9..f14f26613ef01 100644
--- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js
+++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js
@@ -242,6 +242,7 @@ export const npSetup = {
},
kibanaLegacy: {
registerLegacyApp: () => {},
+ registerLegacyAppAlias: () => {},
forwardApp: () => {},
config: {
defaultAppId: 'home',
@@ -362,6 +363,7 @@ export const npStart = {
kibanaLegacy: {
getApps: () => [],
getForwards: () => [],
+ getLegacyAppAliases: () => [],
config: {
defaultAppId: 'home',
},
diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts
index 80fb837258d4c..5ae2e2348aaa1 100644
--- a/src/legacy/ui/public/new_platform/new_platform.ts
+++ b/src/legacy/ui/public/new_platform/new_platform.ts
@@ -69,6 +69,7 @@ import {
VisualizationsSetup,
VisualizationsStart,
} from '../../../../plugins/visualizations/public';
+import { VisTypeTimelionPluginStart } from '../../../../plugins/vis_type_timelion/public';
import { MapsLegacyPluginSetup } from '../../../../plugins/maps_legacy/public';
export interface PluginsSetup {
@@ -116,6 +117,7 @@ export interface PluginsStart {
telemetry?: TelemetryPluginStart;
dashboard: DashboardStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
+ visTypeTimelion: VisTypeTimelionPluginStart;
indexPatternManagement: IndexPatternManagementStart;
}
diff --git a/src/plugins/console/server/__tests__/proxy_route/proxy_fallback.test.ts b/src/plugins/console/server/__tests__/proxy_route/proxy_fallback.test.ts
new file mode 100644
index 0000000000000..b226bad11a01a
--- /dev/null
+++ b/src/plugins/console/server/__tests__/proxy_route/proxy_fallback.test.ts
@@ -0,0 +1,64 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { duration } from 'moment';
+import { getProxyRouteHandlerDeps } from './mocks';
+
+import { kibanaResponseFactory } from '../../../../../core/server';
+import { createHandler } from '../../routes/api/console/proxy/create_handler';
+import * as requestModule from '../../lib/proxy_request';
+
+describe('Console Proxy Route', () => {
+ afterEach(async () => {
+ jest.resetAllMocks();
+ });
+
+ describe('fallback behaviour', () => {
+ it('falls back to all configured endpoints regardless of error', async () => {
+ // Describe a situation where all three configured nodes reject
+ (requestModule.proxyRequest as jest.Mock).mockRejectedValueOnce(new Error('ECONNREFUSED'));
+ (requestModule.proxyRequest as jest.Mock).mockRejectedValueOnce(new Error('EHOSTUNREACH'));
+ (requestModule.proxyRequest as jest.Mock).mockRejectedValueOnce(new Error('ESOCKETTIMEDOUT'));
+
+ const handler = createHandler(
+ getProxyRouteHandlerDeps({
+ readLegacyESConfig: () => ({
+ requestTimeout: duration(30000),
+ customHeaders: {},
+ requestHeadersWhitelist: [],
+ hosts: ['http://localhost:9201', 'http://localhost:9202', 'http://localhost:9203'],
+ }),
+ })
+ );
+
+ const response = await handler(
+ {} as any,
+ {
+ headers: {},
+ query: { method: 'get', path: 'test' },
+ } as any,
+ kibanaResponseFactory
+ );
+
+ expect(response.status).toBe(502);
+ // Return the message from the ES node we attempted last.
+ expect(response.payload.message).toBe('ESOCKETTIMEDOUT');
+ });
+ });
+});
diff --git a/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json
index 408b01c4cb8f5..0da2c130b47cf 100644
--- a/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json
+++ b/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json
@@ -59,7 +59,61 @@
}
},
"transient": {
- "__scope_link": ".persistent"
+ "cluster": {
+ "routing": {
+ "allocation.enable": {
+ "__one_of": ["all", "primaries", "new_primaries", "none"]
+ },
+ "allocation.disk.threshold_enabled": { "__one_of": [false, true] },
+ "allocation.disk.watermark.low": "85%",
+ "allocation.disk.watermark.high": "90%",
+ "allocation.disk.reroute_interval": "60s",
+ "allocation.exclude": {
+ "_ip": "",
+ "_name": "",
+ "_host": "",
+ "_id": ""
+ },
+ "allocation.include": {
+ "_ip": "",
+ "_name": "",
+ "_host": "",
+ "_id": ""
+ },
+ "allocation.require": {
+ "_ip": "",
+ "_name": "",
+ "_host": "",
+ "_id": ""
+ },
+ "allocation.awareness.attributes": [],
+ "allocation.awareness.force": {
+ "*": {
+ "values": []
+ }
+ },
+ "allocation.allow_rebalance": {
+ "__one_of": [
+ "always",
+ "indices_primaries_active",
+ "indices_all_active"
+ ]
+ },
+ "allocation.cluster_concurrent_rebalance": 2,
+ "allocation.node_initial_primaries_recoveries": 4,
+ "allocation.node_concurrent_recoveries": 2,
+ "allocation.same_shard.host": { "__one_of": [false, true] }
+ }
+ },
+ "indices": {
+ "breaker": {
+ "total.limit": "70%",
+ "fielddata.limit": "60%",
+ "fielddata.overhead": 1.03,
+ "request.limit": "40%",
+ "request.overhead": 1.0
+ }
+ }
}
}
}
diff --git a/src/plugins/console/server/routes/api/console/proxy/create_handler.ts b/src/plugins/console/server/routes/api/console/proxy/create_handler.ts
index 50a9fcf03c209..9446289ff03ea 100644
--- a/src/plugins/console/server/routes/api/console/proxy/create_handler.ts
+++ b/src/plugins/console/server/routes/api/console/proxy/create_handler.ts
@@ -175,10 +175,9 @@ export const createHandler = ({
break;
} catch (e) {
+ // If we reached here it means we hit a lower level network issue than just, for e.g., a 500.
+ // We try contacting another node in that case.
log.error(e);
- if (e.code !== 'ECONNREFUSED') {
- return response.internalError(e);
- }
if (idx === hosts.length - 1) {
log.warn(`Could not connect to any configured ES node [${hosts.join(', ')}]`);
return response.customError({
diff --git a/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx b/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx
new file mode 100644
index 0000000000000..17943333d25b0
--- /dev/null
+++ b/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx
@@ -0,0 +1,155 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { isErrorEmbeddable, IContainer } from '../../embeddable_plugin';
+import { DashboardContainer, DashboardPanelState } from '../embeddable';
+import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helpers';
+import {
+ CONTACT_CARD_EMBEDDABLE,
+ ContactCardEmbeddableFactory,
+ ContactCardEmbeddable,
+ ContactCardEmbeddableInput,
+ ContactCardEmbeddableOutput,
+} from '../../embeddable_plugin_test_samples';
+import { coreMock } from '../../../../../core/public/mocks';
+import { CoreStart } from 'kibana/public';
+import { ClonePanelAction } from '.';
+
+// eslint-disable-next-line
+import { embeddablePluginMock } from 'src/plugins/embeddable/public/mocks';
+
+const { setup, doStart } = embeddablePluginMock.createInstance();
+setup.registerEmbeddableFactory(
+ CONTACT_CARD_EMBEDDABLE,
+ new ContactCardEmbeddableFactory((() => null) as any, {} as any)
+);
+const start = doStart();
+
+let container: DashboardContainer;
+let embeddable: ContactCardEmbeddable;
+let coreStart: CoreStart;
+beforeEach(async () => {
+ coreStart = coreMock.createStart();
+ coreStart.savedObjects.client = {
+ ...coreStart.savedObjects.client,
+ get: jest.fn().mockImplementation(() => ({ attributes: { title: 'Holy moly' } })),
+ find: jest.fn().mockImplementation(() => ({ total: 15 })),
+ create: jest.fn().mockImplementation(() => ({ id: 'brandNewSavedObject' })),
+ };
+
+ const options = {
+ ExitFullScreenButton: () => null,
+ SavedObjectFinder: () => null,
+ application: {} as any,
+ embeddable: start,
+ inspector: {} as any,
+ notifications: {} as any,
+ overlays: coreStart.overlays,
+ savedObjectMetaData: {} as any,
+ uiActions: {} as any,
+ };
+ const input = getSampleDashboardInput({
+ panels: {
+ '123': getSampleDashboardPanel({
+ explicitInput: { firstName: 'Kibanana', id: '123' },
+ type: CONTACT_CARD_EMBEDDABLE,
+ }),
+ },
+ });
+ container = new DashboardContainer(input, options);
+
+ const contactCardEmbeddable = await container.addNewEmbeddable<
+ ContactCardEmbeddableInput,
+ ContactCardEmbeddableOutput,
+ ContactCardEmbeddable
+ >(CONTACT_CARD_EMBEDDABLE, {
+ firstName: 'Kibana',
+ });
+
+ if (isErrorEmbeddable(contactCardEmbeddable)) {
+ throw new Error('Failed to create embeddable');
+ } else {
+ embeddable = contactCardEmbeddable;
+ }
+});
+
+test('Clone adds a new embeddable', async () => {
+ const dashboard = embeddable.getRoot() as IContainer;
+ const originalPanelCount = Object.keys(dashboard.getInput().panels).length;
+ const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels));
+ const action = new ClonePanelAction(coreStart);
+ await action.execute({ embeddable });
+ expect(Object.keys(container.getInput().panels).length).toEqual(originalPanelCount + 1);
+ const newPanelId = Object.keys(container.getInput().panels).find(
+ key => !originalPanelKeySet.has(key)
+ );
+ expect(newPanelId).toBeDefined();
+ const newPanel = container.getInput().panels[newPanelId!];
+ expect(newPanel.type).toEqual(embeddable.type);
+});
+
+test('Clones an embeddable without a saved object ID', async () => {
+ const dashboard = embeddable.getRoot() as IContainer;
+ const panel = dashboard.getInput().panels[embeddable.id] as DashboardPanelState;
+ const action = new ClonePanelAction(coreStart);
+ // @ts-ignore
+ const newPanel = await action.cloneEmbeddable(panel, embeddable.type);
+ expect(newPanel.type).toEqual(embeddable.type);
+});
+
+test('Clones an embeddable with a saved object ID', async () => {
+ const dashboard = embeddable.getRoot() as IContainer;
+ const panel = dashboard.getInput().panels[embeddable.id] as DashboardPanelState;
+ panel.explicitInput.savedObjectId = 'holySavedObjectBatman';
+ const action = new ClonePanelAction(coreStart);
+ // @ts-ignore
+ const newPanel = await action.cloneEmbeddable(panel, embeddable.type);
+ expect(coreStart.savedObjects.client.get).toHaveBeenCalledTimes(1);
+ expect(coreStart.savedObjects.client.find).toHaveBeenCalledTimes(1);
+ expect(coreStart.savedObjects.client.create).toHaveBeenCalledTimes(1);
+ expect(newPanel.type).toEqual(embeddable.type);
+});
+
+test('Gets a unique title ', async () => {
+ coreStart.savedObjects.client.find = jest.fn().mockImplementation(({ search }) => {
+ if (search === '"testFirstTitle"') return { total: 1 };
+ else if (search === '"testSecondTitle"') return { total: 41 };
+ else if (search === '"testThirdTitle"') return { total: 90 };
+ });
+ const action = new ClonePanelAction(coreStart);
+ // @ts-ignore
+ expect(await action.getUniqueTitle('testFirstTitle', embeddable.type)).toEqual(
+ 'testFirstTitle (copy)'
+ );
+ // @ts-ignore
+ expect(await action.getUniqueTitle('testSecondTitle (copy 39)', embeddable.type)).toEqual(
+ 'testSecondTitle (copy 40)'
+ );
+ // @ts-ignore
+ expect(await action.getUniqueTitle('testSecondTitle (copy 20)', embeddable.type)).toEqual(
+ 'testSecondTitle (copy 40)'
+ );
+ // @ts-ignore
+ expect(await action.getUniqueTitle('testThirdTitle', embeddable.type)).toEqual(
+ 'testThirdTitle (copy 89)'
+ );
+ // @ts-ignore
+ expect(await action.getUniqueTitle('testThirdTitle (copy 10000)', embeddable.type)).toEqual(
+ 'testThirdTitle (copy 89)'
+ );
+});
diff --git a/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx b/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx
new file mode 100644
index 0000000000000..4d15e7e899fa8
--- /dev/null
+++ b/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx
@@ -0,0 +1,158 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { CoreStart } from 'src/core/public';
+import uuid from 'uuid';
+import { ActionByType, IncompatibleActionError } from '../../ui_actions_plugin';
+import { ViewMode, PanelState, IEmbeddable } from '../../embeddable_plugin';
+import { SavedObject } from '../../../../saved_objects/public';
+import { PanelNotFoundError, EmbeddableInput } from '../../../../embeddable/public';
+import {
+ placePanelBeside,
+ IPanelPlacementBesideArgs,
+} from '../embeddable/panel/dashboard_panel_placement';
+import { DashboardPanelState, DASHBOARD_CONTAINER_TYPE, DashboardContainer } from '..';
+
+export const ACTION_CLONE_PANEL = 'clonePanel';
+
+export interface ClonePanelActionContext {
+ embeddable: IEmbeddable;
+}
+
+export class ClonePanelAction implements ActionByType {
+ public readonly type = ACTION_CLONE_PANEL;
+ public readonly id = ACTION_CLONE_PANEL;
+ public order = 11;
+
+ constructor(private core: CoreStart) {}
+
+ public getDisplayName({ embeddable }: ClonePanelActionContext) {
+ if (!embeddable.getRoot() || !embeddable.getRoot().isContainer) {
+ throw new IncompatibleActionError();
+ }
+ return i18n.translate('dashboard.panel.clonePanel', {
+ defaultMessage: 'Clone panel',
+ });
+ }
+
+ public getIconType({ embeddable }: ClonePanelActionContext) {
+ if (!embeddable.getRoot() || !embeddable.getRoot().isContainer) {
+ throw new IncompatibleActionError();
+ }
+ return 'copy';
+ }
+
+ public async isCompatible({ embeddable }: ClonePanelActionContext) {
+ return Boolean(
+ embeddable.getInput()?.viewMode !== ViewMode.VIEW &&
+ embeddable.getRoot() &&
+ embeddable.getRoot().isContainer &&
+ embeddable.getRoot().type === DASHBOARD_CONTAINER_TYPE
+ );
+ }
+
+ public async execute({ embeddable }: ClonePanelActionContext) {
+ if (!embeddable.getRoot() || !embeddable.getRoot().isContainer) {
+ throw new IncompatibleActionError();
+ }
+
+ const dashboard = embeddable.getRoot() as DashboardContainer;
+ const panelToClone = dashboard.getInput().panels[embeddable.id] as DashboardPanelState;
+ if (!panelToClone) {
+ throw new PanelNotFoundError();
+ }
+
+ dashboard.showPlaceholderUntil(
+ this.cloneEmbeddable(panelToClone, embeddable.type),
+ placePanelBeside,
+ {
+ width: panelToClone.gridData.w,
+ height: panelToClone.gridData.h,
+ currentPanels: dashboard.getInput().panels,
+ placeBesideId: panelToClone.explicitInput.id,
+ } as IPanelPlacementBesideArgs
+ );
+ }
+
+ private async getUniqueTitle(rawTitle: string, embeddableType: string): Promise {
+ const clonedTag = i18n.translate('dashboard.panel.title.clonedTag', {
+ defaultMessage: 'copy',
+ });
+ const cloneRegex = new RegExp(`\\(${clonedTag}\\)`, 'g');
+ const cloneNumberRegex = new RegExp(`\\(${clonedTag} [0-9]+\\)`, 'g');
+ const baseTitle = rawTitle
+ .replace(cloneNumberRegex, '')
+ .replace(cloneRegex, '')
+ .trim();
+
+ const similarSavedObjects = await this.core.savedObjects.client.find({
+ type: embeddableType,
+ perPage: 0,
+ fields: ['title'],
+ searchFields: ['title'],
+ search: `"${baseTitle}"`,
+ });
+ const similarBaseTitlesCount: number = similarSavedObjects.total - 1;
+
+ return similarBaseTitlesCount <= 0
+ ? baseTitle + ` (${clonedTag})`
+ : baseTitle + ` (${clonedTag} ${similarBaseTitlesCount})`;
+ }
+
+ private async cloneEmbeddable(
+ panelToClone: DashboardPanelState,
+ embeddableType: string
+ ): Promise> {
+ const panelState: PanelState = {
+ type: embeddableType,
+ explicitInput: {
+ ...panelToClone.explicitInput,
+ id: uuid.v4(),
+ },
+ };
+ let newTitle: string = '';
+ if (panelToClone.explicitInput.savedObjectId) {
+ // Fetch existing saved object
+ const savedObjectToClone = await this.core.savedObjects.client.get(
+ embeddableType,
+ panelToClone.explicitInput.savedObjectId
+ );
+
+ // Clone the saved object
+ newTitle = await this.getUniqueTitle(savedObjectToClone.attributes.title, embeddableType);
+ const clonedSavedObject = await this.core.savedObjects.client.create(
+ embeddableType,
+ {
+ ..._.cloneDeep(savedObjectToClone.attributes),
+ title: newTitle,
+ },
+ { references: _.cloneDeep(savedObjectToClone.references) }
+ );
+ panelState.explicitInput.savedObjectId = clonedSavedObject.id;
+ }
+ this.core.notifications.toasts.addSuccess({
+ title: i18n.translate('dashboard.panel.clonedToast', {
+ defaultMessage: 'Cloned panel',
+ }),
+ 'data-test-subj': 'addObjectToContainerSuccess',
+ });
+ return panelState;
+ }
+}
diff --git a/src/plugins/dashboard/public/application/actions/index.ts b/src/plugins/dashboard/public/application/actions/index.ts
index 23c26dbd280f8..d7a84fb79f6af 100644
--- a/src/plugins/dashboard/public/application/actions/index.ts
+++ b/src/plugins/dashboard/public/application/actions/index.ts
@@ -27,3 +27,8 @@ export {
ReplacePanelActionContext,
ACTION_REPLACE_PANEL,
} from './replace_panel_action';
+export {
+ ClonePanelAction,
+ ClonePanelActionContext,
+ ACTION_CLONE_PANEL,
+} from './clone_panel_action';
diff --git a/src/plugins/dashboard/public/application/dashboard_state_manager.ts b/src/plugins/dashboard/public/application/dashboard_state_manager.ts
index 13ba3c6d0b60d..b03ea95069a3d 100644
--- a/src/plugins/dashboard/public/application/dashboard_state_manager.ts
+++ b/src/plugins/dashboard/public/application/dashboard_state_manager.ts
@@ -34,6 +34,7 @@ import { FilterUtils } from './lib/filter_utils';
import {
DashboardAppState,
DashboardAppStateDefaults,
+ DashboardAppStateInUrl,
DashboardAppStateTransitions,
SavedDashboardPanel,
} from '../types';
@@ -165,11 +166,12 @@ export class DashboardStateManager {
});
// setup state syncing utils. state container will be synced with url into `this.STATE_STORAGE_KEY` query param
- this.stateSyncRef = syncState({
+ this.stateSyncRef = syncState({
storageKey: this.STATE_STORAGE_KEY,
stateContainer: {
...this.stateContainer,
- set: (state: DashboardAppState | null) => {
+ get: () => this.toUrlState(this.stateContainer.get()),
+ set: (state: DashboardAppStateInUrl | null) => {
// sync state required state container to be able to handle null
// overriding set() so it could handle null coming from url
if (state) {
@@ -558,9 +560,9 @@ export class DashboardStateManager {
*/
private saveState({ replace }: { replace: boolean }): boolean {
// schedules setting current state to url
- this.kbnUrlStateStorage.set(
+ this.kbnUrlStateStorage.set(
this.STATE_STORAGE_KEY,
- this.stateContainer.get()
+ this.toUrlState(this.stateContainer.get())
);
// immediately forces scheduled updates and changes location
return this.kbnUrlStateStorage.flush({ replace });
@@ -620,4 +622,13 @@ export class DashboardStateManager {
const current = _.omit(this.stateContainer.get(), propsToIgnore);
return !_.isEqual(initial, current);
}
+
+ private toUrlState(state: DashboardAppState): DashboardAppStateInUrl {
+ if (state.viewMode === ViewMode.VIEW) {
+ const { panels, ...stateWithoutPanels } = state;
+ return stateWithoutPanels;
+ }
+
+ return state;
+ }
}
diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
index 50089f1f061f4..8346fd900caef 100644
--- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
@@ -23,6 +23,7 @@ import { I18nProvider } from '@kbn/i18n/react';
import { RefreshInterval, TimeRange, Query, Filter } from 'src/plugins/data/public';
import { CoreStart } from 'src/core/public';
import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
+import uuid from 'uuid';
import { UiActionsStart } from '../../ui_actions_plugin';
import {
Container,
@@ -32,6 +33,7 @@ import {
EmbeddableFactory,
IEmbeddable,
EmbeddableStart,
+ PanelState,
} from '../../embeddable_plugin';
import { DASHBOARD_CONTAINER_TYPE } from './dashboard_constants';
import { createPanelState } from './panel';
@@ -42,6 +44,8 @@ import {
KibanaReactContext,
KibanaReactContextValue,
} from '../../../../kibana_react/public';
+import { PLACEHOLDER_EMBEDDABLE } from './placeholder';
+import { PanelPlacementMethod, IPanelPlacementArgs } from './panel/dashboard_panel_placement';
export interface DashboardContainerInput extends ContainerInput {
viewMode: ViewMode;
@@ -120,7 +124,61 @@ export class DashboardContainer extends Container = {}
): DashboardPanelState {
const panelState = super.createNewPanelState(factory, partial);
- return createPanelState(panelState, Object.values(this.input.panels));
+ return createPanelState(panelState, this.input.panels);
+ }
+
+ public showPlaceholderUntil(
+ newStateComplete: Promise>,
+ placementMethod?: PanelPlacementMethod,
+ placementArgs?: TPlacementMethodArgs
+ ): void {
+ const originalPanelState = {
+ type: PLACEHOLDER_EMBEDDABLE,
+ explicitInput: {
+ id: uuid.v4(),
+ disabledActions: [
+ 'ACTION_CUSTOMIZE_PANEL',
+ 'CUSTOM_TIME_RANGE',
+ 'clonePanel',
+ 'replacePanel',
+ 'togglePanel',
+ ],
+ },
+ } as PanelState;
+ const placeholderPanelState = createPanelState(
+ originalPanelState,
+ this.input.panels,
+ placementMethod,
+ placementArgs
+ );
+ this.updateInput({
+ panels: {
+ ...this.input.panels,
+ [placeholderPanelState.explicitInput.id]: placeholderPanelState,
+ },
+ });
+ newStateComplete.then((newPanelState: Partial) => {
+ const finalPanels = { ...this.input.panels };
+ delete finalPanels[placeholderPanelState.explicitInput.id];
+ const newPanelId = newPanelState.explicitInput?.id
+ ? newPanelState.explicitInput.id
+ : uuid.v4();
+ finalPanels[newPanelId] = {
+ ...placeholderPanelState,
+ ...newPanelState,
+ gridData: {
+ ...placeholderPanelState.gridData,
+ i: newPanelId,
+ },
+ explicitInput: {
+ ...newPanelState.explicitInput,
+ id: newPanelId,
+ },
+ };
+ this.updateInput({
+ panels: finalPanels,
+ });
+ });
}
public render(dom: HTMLElement) {
diff --git a/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.test.ts b/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.test.ts
index 409cae8b49a53..7c11ac8a5031b 100644
--- a/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.test.ts
+++ b/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.test.ts
@@ -26,7 +26,7 @@ import { CONTACT_CARD_EMBEDDABLE } from '../../../embeddable_plugin_test_samples
interface TestInput extends EmbeddableInput {
test: string;
}
-const panels: DashboardPanelState[] = [];
+const panels: { [key: string]: DashboardPanelState } = {};
test('createPanelState adds a new panel state in 0,0 position', () => {
const panelState = createPanelState(
@@ -34,7 +34,7 @@ test('createPanelState adds a new panel state in 0,0 position', () => {
type: CONTACT_CARD_EMBEDDABLE,
explicitInput: { test: 'hi', id: '123' },
},
- []
+ panels
);
expect(panelState.explicitInput.test).toBe('hi');
expect(panelState.type).toBe(CONTACT_CARD_EMBEDDABLE);
@@ -44,7 +44,7 @@ test('createPanelState adds a new panel state in 0,0 position', () => {
expect(panelState.gridData.h).toBe(DEFAULT_PANEL_HEIGHT);
expect(panelState.gridData.w).toBe(DEFAULT_PANEL_WIDTH);
- panels.push(panelState);
+ panels[panelState.explicitInput.id] = panelState;
});
test('createPanelState adds a second new panel state', () => {
@@ -58,7 +58,7 @@ test('createPanelState adds a second new panel state', () => {
expect(panelState.gridData.h).toBe(DEFAULT_PANEL_HEIGHT);
expect(panelState.gridData.w).toBe(DEFAULT_PANEL_WIDTH);
- panels.push(panelState);
+ panels[panelState.explicitInput.id] = panelState;
});
test('createPanelState adds a third new panel state', () => {
@@ -74,17 +74,17 @@ test('createPanelState adds a third new panel state', () => {
expect(panelState.gridData.h).toBe(DEFAULT_PANEL_HEIGHT);
expect(panelState.gridData.w).toBe(DEFAULT_PANEL_WIDTH);
- panels.push(panelState);
+ panels[panelState.explicitInput.id] = panelState;
});
test('createPanelState adds a new panel state in the top most position', () => {
- const panelsWithEmptySpace = panels.filter(panel => panel.gridData.x === 0);
+ delete panels['456'];
const panelState = createPanelState(
{
type: CONTACT_CARD_EMBEDDABLE,
explicitInput: { test: 'bye', id: '987' },
},
- panelsWithEmptySpace
+ panels
);
expect(panelState.gridData.x).toBe(DEFAULT_PANEL_WIDTH);
expect(panelState.gridData.y).toBe(0);
diff --git a/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.ts b/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.ts
index f3a48368fe1b3..79116a57869d3 100644
--- a/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.ts
+++ b/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.ts
@@ -19,98 +19,45 @@
import _ from 'lodash';
import { PanelState, EmbeddableInput } from '../../../embeddable_plugin';
-import {
- DASHBOARD_GRID_COLUMN_COUNT,
- DEFAULT_PANEL_HEIGHT,
- DEFAULT_PANEL_WIDTH,
-} from '../dashboard_constants';
+import { DEFAULT_PANEL_HEIGHT, DEFAULT_PANEL_WIDTH } from '../dashboard_constants';
import { DashboardPanelState } from '../types';
-
-// Look for the smallest y and x value where the default panel will fit.
-function findTopLeftMostOpenSpace(
- width: number,
- height: number,
- currentPanels: DashboardPanelState[]
-) {
- let maxY = -1;
-
- currentPanels.forEach(panel => {
- maxY = Math.max(panel.gridData.y + panel.gridData.h, maxY);
- });
-
- // Handle case of empty grid.
- if (maxY < 0) {
- return { x: 0, y: 0 };
- }
-
- const grid = new Array(maxY);
- for (let y = 0; y < maxY; y++) {
- grid[y] = new Array(DASHBOARD_GRID_COLUMN_COUNT).fill(0);
- }
-
- currentPanels.forEach(panel => {
- for (let x = panel.gridData.x; x < panel.gridData.x + panel.gridData.w; x++) {
- for (let y = panel.gridData.y; y < panel.gridData.y + panel.gridData.h; y++) {
- const row = grid[y];
- if (row === undefined) {
- throw new Error(
- `Attempted to access a row that doesn't exist at ${y} for panel ${JSON.stringify(
- panel
- )}`
- );
- }
- grid[y][x] = 1;
- }
- }
- });
-
- for (let y = 0; y < maxY; y++) {
- for (let x = 0; x < DASHBOARD_GRID_COLUMN_COUNT; x++) {
- if (grid[y][x] === 1) {
- // Space is filled
- continue;
- } else {
- for (let h = y; h < Math.min(y + height, maxY); h++) {
- for (let w = x; w < Math.min(x + width, DASHBOARD_GRID_COLUMN_COUNT); w++) {
- const spaceIsEmpty = grid[h][w] === 0;
- const fitsPanelWidth = w === x + width - 1;
- // If the panel is taller than any other panel in the current grid, it can still fit in the space, hence
- // we check the minimum of maxY and the panel height.
- const fitsPanelHeight = h === Math.min(y + height - 1, maxY - 1);
-
- if (spaceIsEmpty && fitsPanelWidth && fitsPanelHeight) {
- // Found space
- return { x, y };
- } else if (grid[h][w] === 1) {
- // x, y spot doesn't work, break.
- break;
- }
- }
- }
- }
- }
- }
- return { x: 0, y: maxY };
-}
+import {
+ IPanelPlacementArgs,
+ findTopLeftMostOpenSpace,
+ PanelPlacementMethod,
+} from './dashboard_panel_placement';
/**
* Creates and initializes a basic panel state.
*/
-export function createPanelState(
+export function createPanelState<
+ TEmbeddableInput extends EmbeddableInput,
+ TPlacementMethodArgs extends IPanelPlacementArgs = IPanelPlacementArgs
+>(
panelState: PanelState,
- currentPanels: DashboardPanelState[]
+ currentPanels: { [key: string]: DashboardPanelState },
+ placementMethod?: PanelPlacementMethod,
+ placementArgs?: TPlacementMethodArgs
): DashboardPanelState {
- const { x, y } = findTopLeftMostOpenSpace(
- DEFAULT_PANEL_WIDTH,
- DEFAULT_PANEL_HEIGHT,
- currentPanels
- );
+ const defaultPlacementArgs = {
+ width: DEFAULT_PANEL_WIDTH,
+ height: DEFAULT_PANEL_HEIGHT,
+ currentPanels,
+ };
+ const finalPlacementArgs = placementArgs
+ ? {
+ ...defaultPlacementArgs,
+ ...placementArgs,
+ }
+ : defaultPlacementArgs;
+
+ const gridDataLocation = placementMethod
+ ? placementMethod(finalPlacementArgs as TPlacementMethodArgs)
+ : findTopLeftMostOpenSpace(defaultPlacementArgs);
+
return {
gridData: {
- w: DEFAULT_PANEL_WIDTH,
- h: DEFAULT_PANEL_HEIGHT,
- x,
- y,
+ ...gridDataLocation,
i: panelState.explicitInput.id,
},
...panelState,
diff --git a/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts b/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts
new file mode 100644
index 0000000000000..70a6c83418587
--- /dev/null
+++ b/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts
@@ -0,0 +1,167 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { PanelNotFoundError } from '../../../embeddable_plugin';
+import { DashboardPanelState, GridData, DASHBOARD_GRID_COLUMN_COUNT } from '..';
+
+export type PanelPlacementMethod = (
+ args: PlacementArgs
+) => Omit;
+
+export interface IPanelPlacementArgs {
+ width: number;
+ height: number;
+ currentPanels: { [key: string]: DashboardPanelState };
+}
+
+export interface IPanelPlacementBesideArgs extends IPanelPlacementArgs {
+ placeBesideId: string;
+}
+
+// Look for the smallest y and x value where the default panel will fit.
+export function findTopLeftMostOpenSpace({
+ width,
+ height,
+ currentPanels,
+}: IPanelPlacementArgs): Omit {
+ let maxY = -1;
+
+ const currentPanelsArray = Object.values(currentPanels);
+ currentPanelsArray.forEach(panel => {
+ maxY = Math.max(panel.gridData.y + panel.gridData.h, maxY);
+ });
+
+ // Handle case of empty grid.
+ if (maxY < 0) {
+ return { x: 0, y: 0, w: width, h: height };
+ }
+
+ const grid = new Array(maxY);
+ for (let y = 0; y < maxY; y++) {
+ grid[y] = new Array(DASHBOARD_GRID_COLUMN_COUNT).fill(0);
+ }
+
+ currentPanelsArray.forEach(panel => {
+ for (let x = panel.gridData.x; x < panel.gridData.x + panel.gridData.w; x++) {
+ for (let y = panel.gridData.y; y < panel.gridData.y + panel.gridData.h; y++) {
+ const row = grid[y];
+ if (row === undefined) {
+ throw new Error(
+ `Attempted to access a row that doesn't exist at ${y} for panel ${JSON.stringify(
+ panel
+ )}`
+ );
+ }
+ grid[y][x] = 1;
+ }
+ }
+ });
+
+ for (let y = 0; y < maxY; y++) {
+ for (let x = 0; x < DASHBOARD_GRID_COLUMN_COUNT; x++) {
+ if (grid[y][x] === 1) {
+ // Space is filled
+ continue;
+ } else {
+ for (let h = y; h < Math.min(y + height, maxY); h++) {
+ for (let w = x; w < Math.min(x + width, DASHBOARD_GRID_COLUMN_COUNT); w++) {
+ const spaceIsEmpty = grid[h][w] === 0;
+ const fitsPanelWidth = w === x + width - 1;
+ // If the panel is taller than any other panel in the current grid, it can still fit in the space, hence
+ // we check the minimum of maxY and the panel height.
+ const fitsPanelHeight = h === Math.min(y + height - 1, maxY - 1);
+
+ if (spaceIsEmpty && fitsPanelWidth && fitsPanelHeight) {
+ // Found space
+ return { x, y, w: width, h: height };
+ } else if (grid[h][w] === 1) {
+ // x, y spot doesn't work, break.
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return { x: 0, y: maxY, w: width, h: height };
+}
+
+interface IplacementDirection {
+ grid: Omit;
+ fits: boolean;
+}
+
+export function placePanelBeside({
+ width,
+ height,
+ currentPanels,
+ placeBesideId,
+}: IPanelPlacementBesideArgs): Omit {
+ // const clonedPanels = _.cloneDeep(currentPanels);
+ if (!placeBesideId) {
+ throw new Error('Place beside method called without placeBesideId');
+ }
+ const panelToPlaceBeside = currentPanels[placeBesideId];
+ if (!panelToPlaceBeside) {
+ throw new PanelNotFoundError();
+ }
+ const beside = panelToPlaceBeside.gridData;
+ const otherPanels: GridData[] = [];
+ _.forOwn(currentPanels, (panel: DashboardPanelState, key: string | undefined) => {
+ otherPanels.push(panel.gridData);
+ });
+
+ const possiblePlacementDirections: IplacementDirection[] = [
+ { grid: { x: beside.x + beside.w, y: beside.y, w: width, h: height }, fits: true }, // right
+ { grid: { x: beside.x - width, y: beside.y, w: width, h: height }, fits: true }, // left
+ { grid: { x: beside.x, y: beside.y + beside.h, w: width, h: height }, fits: true }, // bottom
+ ];
+
+ for (const direction of possiblePlacementDirections) {
+ if (
+ direction.grid.x >= 0 &&
+ direction.grid.x + direction.grid.w <= DASHBOARD_GRID_COLUMN_COUNT &&
+ direction.grid.y >= 0
+ ) {
+ const intersection = otherPanels.some((currentPanelGrid: GridData) => {
+ return (
+ direction.grid.x + direction.grid.w > currentPanelGrid.x &&
+ direction.grid.x < currentPanelGrid.x + currentPanelGrid.w &&
+ direction.grid.y < currentPanelGrid.y + currentPanelGrid.h &&
+ direction.grid.y + direction.grid.h > currentPanelGrid.y
+ );
+ });
+ if (!intersection) {
+ return direction.grid;
+ }
+ } else {
+ direction.fits = false;
+ }
+ }
+ // if we get here that means there is no blank space around the panel we are placing beside. This means it's time to mess up the dashboard's groove. Fun!
+ const [, , bottomPlacement] = possiblePlacementDirections;
+ for (const currentPanelGrid of otherPanels) {
+ if (bottomPlacement.grid.y <= currentPanelGrid.y) {
+ const movedPanel = _.cloneDeep(currentPanels[currentPanelGrid.i]);
+ movedPanel.gridData.y = movedPanel.gridData.y + bottomPlacement.grid.h;
+ currentPanels[currentPanelGrid.i] = movedPanel;
+ }
+ }
+ return bottomPlacement.grid;
+}
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/flot.js b/src/plugins/dashboard/public/application/embeddable/placeholder/index.ts
similarity index 78%
rename from src/legacy/core_plugins/vis_type_timelion/public/flot.js
rename to src/plugins/dashboard/public/application/embeddable/placeholder/index.ts
index d6ca6d96c34ef..7c65d50ce3fea 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/flot.js
+++ b/src/plugins/dashboard/public/application/embeddable/placeholder/index.ts
@@ -17,10 +17,5 @@
* under the License.
*/
-require('jquery.flot');
-require('jquery.flot.time');
-require('jquery.flot.symbol');
-require('jquery.flot.crosshair');
-require('jquery.flot.selection');
-require('jquery.flot.stack');
-require('jquery.flot.axislabels');
+export * from './placeholder_embeddable';
+export * from './placeholder_embeddable_factory';
diff --git a/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable.tsx b/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable.tsx
new file mode 100644
index 0000000000000..1a5c3386bdeda
--- /dev/null
+++ b/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable.tsx
@@ -0,0 +1,52 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { EuiLoadingChart } from '@elastic/eui';
+import classNames from 'classnames';
+import { Embeddable, EmbeddableInput, IContainer } from '../../../embeddable_plugin';
+
+export const PLACEHOLDER_EMBEDDABLE = 'placeholder';
+
+export class PlaceholderEmbeddable extends Embeddable {
+ public readonly type = PLACEHOLDER_EMBEDDABLE;
+ private node?: HTMLElement;
+
+ constructor(initialInput: EmbeddableInput, parent?: IContainer) {
+ super(initialInput, {}, parent);
+ this.input = initialInput;
+ }
+ public render(node: HTMLElement) {
+ if (this.node) {
+ ReactDOM.unmountComponentAtNode(this.node);
+ }
+ this.node = node;
+
+ const classes = classNames('embPanel', 'embPanel-isLoading');
+ ReactDOM.render(
+
+
+
,
+ node
+ );
+ }
+
+ public reload() {}
+}
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/legacy.ts b/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable_factory.ts
similarity index 53%
rename from src/legacy/core_plugins/vis_type_timelion/public/legacy.ts
rename to src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable_factory.ts
index f8de9f94dcedf..30a93989649a7 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/legacy.ts
+++ b/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable_factory.ts
@@ -17,19 +17,29 @@
* under the License.
*/
-import { PluginInitializerContext } from 'kibana/public';
+import { i18n } from '@kbn/i18n';
-import { npSetup, npStart } from './legacy_imports';
-import { TimelionVisSetupDependencies } from './plugin';
-import { plugin } from '.';
+import {
+ EmbeddableFactoryDefinition,
+ EmbeddableInput,
+ IContainer,
+} from '../../../embeddable_plugin';
+import { PlaceholderEmbeddable, PLACEHOLDER_EMBEDDABLE } from './placeholder_embeddable';
-const setupPlugins: Readonly = {
- expressions: npSetup.plugins.expressions,
- data: npSetup.plugins.data,
- visualizations: npSetup.plugins.visualizations,
-};
+export class PlaceholderEmbeddableFactory implements EmbeddableFactoryDefinition {
+ public readonly type = PLACEHOLDER_EMBEDDABLE;
-const pluginInstance = plugin({} as PluginInitializerContext);
+ public async isEditable() {
+ return false;
+ }
-export const setup = pluginInstance.setup(npSetup.core, setupPlugins);
-export const start = pluginInstance.start(npStart.core, npStart.plugins);
+ public async create(initialInput: EmbeddableInput, parent?: IContainer) {
+ return new PlaceholderEmbeddable(initialInput, parent);
+ }
+
+ public getDisplayName() {
+ return i18n.translate('dashboard.placeholder.factory.displayName', {
+ defaultMessage: 'placeholder',
+ });
+ }
+}
diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx
index 322d734d9f39f..203c784d9df4e 100644
--- a/src/plugins/dashboard/public/plugin.tsx
+++ b/src/plugins/dashboard/public/plugin.tsx
@@ -67,9 +67,12 @@ import {
ExpandPanelActionContext,
ReplacePanelAction,
ReplacePanelActionContext,
+ ClonePanelAction,
+ ClonePanelActionContext,
ACTION_EXPAND_PANEL,
ACTION_REPLACE_PANEL,
RenderDeps,
+ ACTION_CLONE_PANEL,
} from './application';
import {
DashboardAppLinkGeneratorState,
@@ -78,6 +81,7 @@ import {
} from './url_generator';
import { createSavedDashboardLoader } from './saved_dashboards';
import { DashboardConstants } from './dashboard_constants';
+import { PlaceholderEmbeddableFactory } from './application/embeddable/placeholder';
declare module '../../share/public' {
export interface UrlGeneratorStateMapping {
@@ -115,6 +119,7 @@ declare module '../../../plugins/ui_actions/public' {
export interface ActionContextMapping {
[ACTION_EXPAND_PANEL]: ExpandPanelActionContext;
[ACTION_REPLACE_PANEL]: ReplacePanelActionContext;
+ [ACTION_CLONE_PANEL]: ClonePanelActionContext;
}
}
@@ -173,6 +178,9 @@ export class DashboardPlugin
const factory = new DashboardContainerFactory(getStartServices);
embeddable.registerEmbeddableFactory(factory.type, factory);
+ const placeholderFactory = new PlaceholderEmbeddableFactory();
+ embeddable.registerEmbeddableFactory(placeholderFactory.type, placeholderFactory);
+
const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({
baseUrl: core.http.basePath.prepend('/app/kibana'),
defaultSubUrl: `#${DashboardConstants.LANDING_PAGE_PATH}`,
@@ -297,6 +305,11 @@ export class DashboardPlugin
);
uiActions.registerAction(changeViewAction);
uiActions.attachAction(CONTEXT_MENU_TRIGGER, changeViewAction);
+
+ const clonePanelAction = new ClonePanelAction(core);
+ uiActions.registerAction(clonePanelAction);
+ uiActions.attachAction(CONTEXT_MENU_TRIGGER, clonePanelAction);
+
const savedDashboardLoader = createSavedDashboardLoader({
savedObjectsClient: core.savedObjects.client,
indexPatterns,
diff --git a/src/plugins/dashboard/public/types.ts b/src/plugins/dashboard/public/types.ts
index 7bccd3de6eca8..d96d2cdf75626 100644
--- a/src/plugins/dashboard/public/types.ts
+++ b/src/plugins/dashboard/public/types.ts
@@ -152,6 +152,14 @@ export type DashboardAppStateDefaults = DashboardAppState & {
description?: string;
};
+/**
+ * In URL panels are optional,
+ * Panels are not added to the URL when in "view" mode
+ */
+export type DashboardAppStateInUrl = Omit & {
+ panels?: SavedDashboardPanel[];
+};
+
export interface DashboardAppStateTransitions {
set: (
state: DashboardAppState
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 06a46065baa84..b62b728beca35 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -363,7 +363,6 @@ export {
SearchRequest,
SearchResponse,
SearchError,
- SearchStrategyProvider,
ISearchSource,
SearchSource,
createSearchSource,
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index 6e06d063e7ebe..427c4f7864554 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -1724,21 +1724,6 @@ export interface SearchSourceFields {
version?: boolean;
}
-// Warning: (ae-missing-release-tag) "SearchStrategyProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export interface SearchStrategyProvider {
- // (undocumented)
- id: string;
- // (undocumented)
- isViable: (indexPattern: IndexPattern) => boolean;
- // Warning: (ae-forgotten-export) The symbol "SearchStrategySearchParams" needs to be exported by the entry point index.d.ts
- // Warning: (ae-forgotten-export) The symbol "SearchStrategyResponse" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
- search: (params: SearchStrategySearchParams) => SearchStrategyResponse;
-}
-
// Warning: (ae-missing-release-tag) "SortDirection" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -1889,21 +1874,21 @@ export type TSearchStrategyProvider = (context: ISearc
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "getRoutes" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:391:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:387:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:404:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:408:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:33:33 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:37:1 - (ae-forgotten-export) The symbol "QueryStateChange" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromEvent" needs to be exported by the entry point index.d.ts
diff --git a/src/plugins/data/public/search/aggs/test_helpers/mock_data_services.ts b/src/plugins/data/public/search/aggs/test_helpers/mock_data_services.ts
index d1d591771743c..e807e084c683a 100644
--- a/src/plugins/data/public/search/aggs/test_helpers/mock_data_services.ts
+++ b/src/plugins/data/public/search/aggs/test_helpers/mock_data_services.ts
@@ -18,8 +18,8 @@
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { coreMock } from '../../../../../../../src/core/public/mocks';
-import { dataPluginMock } from '../../../../public/mocks';
+import { coreMock } from '../../../../../../core/public/mocks';
+import { dataPluginMock } from '../../../mocks';
import {
setFieldFormats,
setIndexPatterns,
@@ -29,7 +29,7 @@ import {
setQueryService,
setSearchService,
setUiSettings,
-} from '../../../../public/services';
+} from '../../../services';
/**
* Testing helper which calls all of the service setters used in the
@@ -49,4 +49,9 @@ export function mockDataServices() {
setQueryService(data.query);
setSearchService(data.search);
setUiSettings(core.uiSettings);
+
+ return {
+ core,
+ data,
+ };
}
diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/fetch/get_search_params.test.ts
new file mode 100644
index 0000000000000..edf18405e8ff7
--- /dev/null
+++ b/src/plugins/data/public/search/fetch/get_search_params.test.ts
@@ -0,0 +1,70 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { getSearchParams } from './get_search_params';
+import { IUiSettingsClient } from 'kibana/public';
+
+function getConfigStub(config: any = {}) {
+ return {
+ get: key => config[key],
+ } as IUiSettingsClient;
+}
+
+describe('getSearchParams', () => {
+ test('includes rest_total_hits_as_int', () => {
+ const config = getConfigStub();
+ const searchParams = getSearchParams(config);
+ expect(searchParams.rest_total_hits_as_int).toBe(true);
+ });
+
+ test('includes ignore_unavailable', () => {
+ const config = getConfigStub();
+ const searchParams = getSearchParams(config);
+ expect(searchParams.ignore_unavailable).toBe(true);
+ });
+
+ test('includes ignore_throttled according to search:includeFrozen', () => {
+ let config = getConfigStub({ 'search:includeFrozen': true });
+ let searchParams = getSearchParams(config);
+ expect(searchParams.ignore_throttled).toBe(false);
+
+ config = getConfigStub({ 'search:includeFrozen': false });
+ searchParams = getSearchParams(config);
+ expect(searchParams.ignore_throttled).toBe(true);
+ });
+
+ test('includes max_concurrent_shard_requests according to courier:maxConcurrentShardRequests', () => {
+ let config = getConfigStub({ 'courier:maxConcurrentShardRequests': 0 });
+ let searchParams = getSearchParams(config);
+ expect(searchParams.max_concurrent_shard_requests).toBe(undefined);
+
+ config = getConfigStub({ 'courier:maxConcurrentShardRequests': 5 });
+ searchParams = getSearchParams(config);
+ expect(searchParams.max_concurrent_shard_requests).toBe(5);
+ });
+
+ test('includes timeout according to esShardTimeout if greater than 0', () => {
+ const config = getConfigStub();
+ let searchParams = getSearchParams(config, 0);
+ expect(searchParams.timeout).toBe(undefined);
+
+ searchParams = getSearchParams(config, 100);
+ expect(searchParams.timeout).toBe('100ms');
+ });
+});
diff --git a/src/plugins/data/public/search/search_strategy/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts
similarity index 81%
rename from src/plugins/data/public/search/search_strategy/get_search_params.ts
rename to src/plugins/data/public/search/fetch/get_search_params.ts
index 9fb8f2c728c6f..f0c43bd2e74cd 100644
--- a/src/plugins/data/public/search/search_strategy/get_search_params.ts
+++ b/src/plugins/data/public/search/fetch/get_search_params.ts
@@ -17,18 +17,10 @@
* under the License.
*/
-import { IUiSettingsClient } from '../../../../../core/public';
+import { IUiSettingsClient } from 'kibana/public';
const sessionId = Date.now();
-export function getMSearchParams(config: IUiSettingsClient) {
- return {
- rest_total_hits_as_int: true,
- ignore_throttled: getIgnoreThrottled(config),
- max_concurrent_shard_requests: getMaxConcurrentShardRequests(config),
- };
-}
-
export function getSearchParams(config: IUiSettingsClient, esShardTimeout: number = 0) {
return {
rest_total_hits_as_int: true,
@@ -40,11 +32,11 @@ export function getSearchParams(config: IUiSettingsClient, esShardTimeout: numbe
};
}
-function getIgnoreThrottled(config: IUiSettingsClient) {
+export function getIgnoreThrottled(config: IUiSettingsClient) {
return !config.get('search:includeFrozen');
}
-function getMaxConcurrentShardRequests(config: IUiSettingsClient) {
+export function getMaxConcurrentShardRequests(config: IUiSettingsClient) {
const maxConcurrentShardRequests = config.get('courier:maxConcurrentShardRequests');
return maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined;
}
diff --git a/src/plugins/data/public/search/fetch/index.ts b/src/plugins/data/public/search/fetch/index.ts
index 8a80b716add32..39845ec31bfaa 100644
--- a/src/plugins/data/public/search/fetch/index.ts
+++ b/src/plugins/data/public/search/fetch/index.ts
@@ -18,5 +18,14 @@
*/
export * from './types';
-export { fetchSoon } from './fetch_soon';
-export { RequestFailure } from './errors';
+export {
+ getSearchParams,
+ getPreference,
+ getTimeout,
+ getIgnoreThrottled,
+ getMaxConcurrentShardRequests,
+} from './get_search_params';
+
+export { SearchError, getSearchErrorType } from './search_error';
+export { RequestFailure } from './request_error';
+export { handleResponse } from './handle_response';
diff --git a/src/plugins/data/public/search/fetch/errors.ts b/src/plugins/data/public/search/fetch/request_error.ts
similarity index 100%
rename from src/plugins/data/public/search/fetch/errors.ts
rename to src/plugins/data/public/search/fetch/request_error.ts
diff --git a/src/plugins/data/public/search/search_strategy/search_error.ts b/src/plugins/data/public/search/fetch/search_error.ts
similarity index 100%
rename from src/plugins/data/public/search/search_strategy/search_error.ts
rename to src/plugins/data/public/search/fetch/search_error.ts
diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts
index e8de0576b8a72..475b2abbc019f 100644
--- a/src/plugins/data/public/search/fetch/types.ts
+++ b/src/plugins/data/public/search/fetch/types.ts
@@ -20,6 +20,9 @@
import { IUiSettingsClient } from '../../../../../core/public';
import { ISearchStart } from '../types';
+export type SearchRequest = any;
+export type SearchResponse = any;
+
export interface FetchOptions {
abortSignal?: AbortSignal;
searchStrategyId?: string;
diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts
index cce973d632f41..75c0eb8b6f022 100644
--- a/src/plugins/data/public/search/index.ts
+++ b/src/plugins/data/public/search/index.ts
@@ -44,9 +44,13 @@ export { esSearchStrategyProvider, getEsPreference } from './es_search';
export { IKibanaSearchResponse, IKibanaSearchRequest } from '../../common/search';
-export { LegacyApiCaller, SearchRequest, SearchResponse } from './es_client';
-
-export { SearchError, SearchStrategyProvider, getSearchErrorType } from './search_strategy';
+export {
+ SearchError,
+ FetchOptions,
+ SearchRequest,
+ SearchResponse,
+ getSearchErrorType,
+} from './fetch';
export {
ISearchSource,
@@ -59,5 +63,3 @@ export {
export { SearchInterceptor } from './search_interceptor';
export { RequestTimeoutError } from './request_timeout_error';
-
-export { FetchOptions } from './fetch';
diff --git a/src/plugins/data/public/search/fetch/call_client.test.ts b/src/plugins/data/public/search/legacy/call_client.test.ts
similarity index 91%
rename from src/plugins/data/public/search/fetch/call_client.test.ts
rename to src/plugins/data/public/search/legacy/call_client.test.ts
index 7a99b7c064515..f919187d46784 100644
--- a/src/plugins/data/public/search/fetch/call_client.test.ts
+++ b/src/plugins/data/public/search/legacy/call_client.test.ts
@@ -18,16 +18,17 @@
*/
import { callClient } from './call_client';
-import { handleResponse } from './handle_response';
-import { FetchHandlers } from './types';
-import { SearchStrategySearchParams, defaultSearchStrategy } from '../search_strategy';
+import { SearchStrategySearchParams } from './types';
+import { defaultSearchStrategy } from './default_search_strategy';
+import { FetchHandlers } from '../fetch';
+import { handleResponse } from '../fetch/handle_response';
const mockAbortFn = jest.fn();
-jest.mock('./handle_response', () => ({
+jest.mock('../fetch/handle_response', () => ({
handleResponse: jest.fn((request, response) => response),
}));
-jest.mock('../search_strategy', () => {
+jest.mock('./default_search_strategy', () => {
return {
defaultSearchStrategy: {
search: jest.fn(({ searchRequests }: SearchStrategySearchParams) => {
diff --git a/src/plugins/data/public/search/fetch/call_client.ts b/src/plugins/data/public/search/legacy/call_client.ts
similarity index 89%
rename from src/plugins/data/public/search/fetch/call_client.ts
rename to src/plugins/data/public/search/legacy/call_client.ts
index b3c4c682fa60c..c484c46aa4879 100644
--- a/src/plugins/data/public/search/fetch/call_client.ts
+++ b/src/plugins/data/public/search/legacy/call_client.ts
@@ -17,10 +17,9 @@
* under the License.
*/
-import { handleResponse } from './handle_response';
-import { FetchOptions, FetchHandlers } from './types';
-import { defaultSearchStrategy } from '../search_strategy';
-import { SearchRequest } from '..';
+import { FetchOptions, FetchHandlers, handleResponse } from '../fetch';
+import { defaultSearchStrategy } from './default_search_strategy';
+import { SearchRequest } from '../index';
export function callClient(
searchRequests: SearchRequest[],
diff --git a/src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts
similarity index 83%
rename from src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts
rename to src/plugins/data/public/search/legacy/default_search_strategy.test.ts
index 210a0e5fd1ac7..835b02b3cd5c7 100644
--- a/src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts
+++ b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts
@@ -17,10 +17,10 @@
* under the License.
*/
-import { IUiSettingsClient } from '../../../../../core/public';
-import { SearchStrategySearchParams } from './types';
+import { IUiSettingsClient } from 'kibana/public';
import { defaultSearchStrategy } from './default_search_strategy';
import { searchStartMock } from '../mocks';
+import { SearchStrategySearchParams } from './types';
const { search } = defaultSearchStrategy;
@@ -38,12 +38,6 @@ const searchMockResponse: any = Promise.resolve([]);
searchMockResponse.abort = jest.fn();
const searchMock = jest.fn().mockReturnValue(searchMockResponse);
-const newSearchMockResponse: any = Promise.resolve([]);
-newSearchMockResponse.abort = jest.fn();
-const newSearchMock = jest.fn().mockReturnValue({
- toPromise: () => searchMockResponse,
-});
-
describe('defaultSearchStrategy', function() {
describe('search', function() {
let searchArgs: MockedKeys>;
@@ -58,7 +52,6 @@ describe('defaultSearchStrategy', function() {
const searchService = searchStartMock;
searchService.aggs.calculateAutoTimeExpression = jest.fn().mockReturnValue('1d');
- searchService.search = newSearchMock;
searchService.__LEGACY.esClient.search = searchMock;
searchService.__LEGACY.esClient.msearch = msearchMock;
@@ -112,18 +105,5 @@ describe('defaultSearchStrategy', function() {
search({ ...searchArgs, config }).abort();
expect(msearchMockResponse.abort).toHaveBeenCalled();
});
-
- test('should call new search service', () => {
- const config = getConfigStub();
- search({ ...searchArgs, config });
- expect(newSearchMock).toHaveBeenCalledTimes(1);
- });
-
- test('should properly abort with new search service', async () => {
- const abortSpy = jest.spyOn(AbortController.prototype, 'abort');
- const config = getConfigStub({});
- search({ ...searchArgs, config }).abort();
- expect(abortSpy).toHaveBeenCalled();
- });
});
});
diff --git a/src/plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/plugins/data/public/search/legacy/default_search_strategy.ts
similarity index 64%
rename from src/plugins/data/public/search/search_strategy/default_search_strategy.ts
rename to src/plugins/data/public/search/legacy/default_search_strategy.ts
index 2bd88f51587a8..1552410f9090c 100644
--- a/src/plugins/data/public/search/search_strategy/default_search_strategy.ts
+++ b/src/plugins/data/public/search/legacy/default_search_strategy.ts
@@ -17,23 +17,19 @@
* under the License.
*/
+import { getPreference, getTimeout } from '../fetch';
+import { getMSearchParams } from './get_msearch_params';
import { SearchStrategyProvider, SearchStrategySearchParams } from './types';
-import { isDefault } from '../../index_patterns';
-import { getSearchParams, getMSearchParams, getPreference, getTimeout } from './get_search_params';
+// @deprecated
export const defaultSearchStrategy: SearchStrategyProvider = {
id: 'default',
search: params => {
- return params.config.get('courier:batchSearches') ? msearch(params) : search(params);
- },
-
- isViable: indexPattern => {
- return indexPattern && isDefault(indexPattern);
+ return msearch(params);
},
};
-// @deprecated
function msearch({
searchRequests,
searchService,
@@ -65,29 +61,3 @@ function msearch({
abort: searching.abort,
};
}
-
-function search({
- searchRequests,
- searchService,
- config,
- esShardTimeout,
-}: SearchStrategySearchParams) {
- const abortController = new AbortController();
- const searchParams = getSearchParams(config, esShardTimeout);
- const promises = searchRequests.map(({ index, indexType, body }) => {
- const params = {
- index: index.title || index,
- body,
- ...searchParams,
- };
- const { signal } = abortController;
- return searchService
- .search({ params, indexType }, { signal })
- .toPromise()
- .then(({ rawResponse }) => rawResponse);
- });
- return {
- searching: Promise.all(promises),
- abort: () => abortController.abort(),
- };
-}
diff --git a/src/plugins/data/public/search/es_client/get_es_client.ts b/src/plugins/data/public/search/legacy/es_client/get_es_client.ts
similarity index 100%
rename from src/plugins/data/public/search/es_client/get_es_client.ts
rename to src/plugins/data/public/search/legacy/es_client/get_es_client.ts
diff --git a/src/plugins/data/public/search/es_client/index.ts b/src/plugins/data/public/search/legacy/es_client/index.ts
similarity index 91%
rename from src/plugins/data/public/search/es_client/index.ts
rename to src/plugins/data/public/search/legacy/es_client/index.ts
index b1e0ce3116824..78ac83af642d8 100644
--- a/src/plugins/data/public/search/es_client/index.ts
+++ b/src/plugins/data/public/search/legacy/es_client/index.ts
@@ -18,4 +18,4 @@
*/
export { getEsClient } from './get_es_client';
-export { SearchRequest, SearchResponse, LegacyApiCaller } from './types';
+export { LegacyApiCaller } from './types';
diff --git a/src/plugins/data/public/search/es_client/types.ts b/src/plugins/data/public/search/legacy/es_client/types.ts
similarity index 94%
rename from src/plugins/data/public/search/es_client/types.ts
rename to src/plugins/data/public/search/legacy/es_client/types.ts
index 3ca0513a14238..7a56b9b0cb00a 100644
--- a/src/plugins/data/public/search/es_client/types.ts
+++ b/src/plugins/data/public/search/legacy/es_client/types.ts
@@ -17,8 +17,7 @@
* under the License.
*/
-export type SearchRequest = any;
-export type SearchResponse = any;
+import { SearchRequest, SearchResponse } from '../../fetch';
export interface LegacyApiCaller {
search: (searchRequest: SearchRequest) => LegacyApiCallerResponse;
diff --git a/src/plugins/data/public/search/fetch/fetch_soon.test.ts b/src/plugins/data/public/search/legacy/fetch_soon.test.ts
similarity index 96%
rename from src/plugins/data/public/search/fetch/fetch_soon.test.ts
rename to src/plugins/data/public/search/legacy/fetch_soon.test.ts
index a8d593c8501f6..b2e17798ccc9f 100644
--- a/src/plugins/data/public/search/fetch/fetch_soon.test.ts
+++ b/src/plugins/data/public/search/legacy/fetch_soon.test.ts
@@ -19,9 +19,9 @@
import { fetchSoon } from './fetch_soon';
import { callClient } from './call_client';
-import { IUiSettingsClient } from '../../../../../core/public';
-import { FetchHandlers, FetchOptions } from './types';
-import { SearchRequest, SearchResponse } from '..';
+import { IUiSettingsClient } from 'kibana/public';
+import { FetchHandlers, FetchOptions } from '../fetch/types';
+import { SearchRequest, SearchResponse } from '../index';
function getConfigStub(config: any = {}) {
return {
diff --git a/src/plugins/data/public/search/fetch/fetch_soon.ts b/src/plugins/data/public/search/legacy/fetch_soon.ts
similarity index 95%
rename from src/plugins/data/public/search/fetch/fetch_soon.ts
rename to src/plugins/data/public/search/legacy/fetch_soon.ts
index b1405747426ee..18fa410a5bef0 100644
--- a/src/plugins/data/public/search/fetch/fetch_soon.ts
+++ b/src/plugins/data/public/search/legacy/fetch_soon.ts
@@ -18,8 +18,8 @@
*/
import { callClient } from './call_client';
-import { FetchHandlers, FetchOptions } from './types';
-import { SearchRequest, SearchResponse } from '..';
+import { FetchHandlers, FetchOptions } from '../fetch/types';
+import { SearchRequest, SearchResponse } from '../index';
/**
* This function introduces a slight delay in the request process to allow multiple requests to queue
diff --git a/src/plugins/data/public/search/search_strategy/get_search_params.test.ts b/src/plugins/data/public/search/legacy/get_msearch_params.test.ts
similarity index 60%
rename from src/plugins/data/public/search/search_strategy/get_search_params.test.ts
rename to src/plugins/data/public/search/legacy/get_msearch_params.test.ts
index 76f3105d7f942..9f16d5b408178 100644
--- a/src/plugins/data/public/search/search_strategy/get_search_params.test.ts
+++ b/src/plugins/data/public/search/legacy/get_msearch_params.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { getMSearchParams, getSearchParams } from './get_search_params';
+import { getMSearchParams } from './get_msearch_params';
import { IUiSettingsClient } from '../../../../../core/public';
function getConfigStub(config: any = {}) {
@@ -64,46 +64,3 @@ describe('getMSearchParams', () => {
expect(msearchParams.hasOwnProperty('timeout')).toBe(false);
});
});
-
-describe('getSearchParams', () => {
- test('includes rest_total_hits_as_int', () => {
- const config = getConfigStub();
- const searchParams = getSearchParams(config);
- expect(searchParams.rest_total_hits_as_int).toBe(true);
- });
-
- test('includes ignore_unavailable', () => {
- const config = getConfigStub();
- const searchParams = getSearchParams(config);
- expect(searchParams.ignore_unavailable).toBe(true);
- });
-
- test('includes ignore_throttled according to search:includeFrozen', () => {
- let config = getConfigStub({ 'search:includeFrozen': true });
- let searchParams = getSearchParams(config);
- expect(searchParams.ignore_throttled).toBe(false);
-
- config = getConfigStub({ 'search:includeFrozen': false });
- searchParams = getSearchParams(config);
- expect(searchParams.ignore_throttled).toBe(true);
- });
-
- test('includes max_concurrent_shard_requests according to courier:maxConcurrentShardRequests', () => {
- let config = getConfigStub({ 'courier:maxConcurrentShardRequests': 0 });
- let searchParams = getSearchParams(config);
- expect(searchParams.max_concurrent_shard_requests).toBe(undefined);
-
- config = getConfigStub({ 'courier:maxConcurrentShardRequests': 5 });
- searchParams = getSearchParams(config);
- expect(searchParams.max_concurrent_shard_requests).toBe(5);
- });
-
- test('includes timeout according to esShardTimeout if greater than 0', () => {
- const config = getConfigStub();
- let searchParams = getSearchParams(config, 0);
- expect(searchParams.timeout).toBe(undefined);
-
- searchParams = getSearchParams(config, 100);
- expect(searchParams.timeout).toBe('100ms');
- });
-});
diff --git a/src/plugins/data/public/search/legacy/get_msearch_params.ts b/src/plugins/data/public/search/legacy/get_msearch_params.ts
new file mode 100644
index 0000000000000..48d13903c972f
--- /dev/null
+++ b/src/plugins/data/public/search/legacy/get_msearch_params.ts
@@ -0,0 +1,29 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { IUiSettingsClient } from 'kibana/public';
+import { getIgnoreThrottled, getMaxConcurrentShardRequests } from '../fetch';
+
+export function getMSearchParams(config: IUiSettingsClient) {
+ return {
+ rest_total_hits_as_int: true,
+ ignore_throttled: getIgnoreThrottled(config),
+ max_concurrent_shard_requests: getMaxConcurrentShardRequests(config),
+ };
+}
diff --git a/src/plugins/data/public/search/legacy/index.ts b/src/plugins/data/public/search/legacy/index.ts
new file mode 100644
index 0000000000000..e2ae72824f3f4
--- /dev/null
+++ b/src/plugins/data/public/search/legacy/index.ts
@@ -0,0 +1,21 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export { fetchSoon } from './fetch_soon';
+export { getEsClient, LegacyApiCaller } from './es_client';
diff --git a/src/plugins/data/public/search/search_strategy/types.ts b/src/plugins/data/public/search/legacy/types.ts
similarity index 89%
rename from src/plugins/data/public/search/search_strategy/types.ts
rename to src/plugins/data/public/search/legacy/types.ts
index 764370d8ff649..3812cec7a2aa2 100644
--- a/src/plugins/data/public/search/search_strategy/types.ts
+++ b/src/plugins/data/public/search/legacy/types.ts
@@ -17,21 +17,20 @@
* under the License.
*/
-import { IndexPattern } from '../..';
-import { FetchHandlers } from '../fetch/types';
+import { FetchHandlers } from '../fetch';
import { SearchRequest, SearchResponse } from '..';
+export interface SearchStrategySearchParams extends FetchHandlers {
+ searchRequests: SearchRequest[];
+}
+
+// @deprecated
export interface SearchStrategyProvider {
id: string;
search: (params: SearchStrategySearchParams) => SearchStrategyResponse;
- isViable: (indexPattern: IndexPattern) => boolean;
}
export interface SearchStrategyResponse {
searching: Promise;
abort: () => void;
}
-
-export interface SearchStrategySearchParams extends FetchHandlers {
- searchRequests: SearchRequest[];
-}
diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts
index a539736991adb..916278a96659b 100644
--- a/src/plugins/data/public/search/search_service.ts
+++ b/src/plugins/data/public/search/search_service.ts
@@ -22,12 +22,12 @@ import { Plugin, CoreSetup, CoreStart, PackageInfo } from '../../../../core/publ
import { SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider } from './sync_search_strategy';
import { ISearchSetup, ISearchStart, TSearchStrategyProvider, TSearchStrategiesMap } from './types';
import { TStrategyTypes } from './strategy_types';
-import { getEsClient, LegacyApiCaller } from './es_client';
+import { getEsClient, LegacyApiCaller } from './legacy';
import { ES_SEARCH_STRATEGY, DEFAULT_SEARCH_STRATEGY } from '../../common/search';
-import { esSearchStrategyProvider } from './es_search/es_search_strategy';
+import { esSearchStrategyProvider } from './es_search';
import { IndexPatternsContract } from '../index_patterns/index_patterns';
import { createSearchSource } from './search_source';
-import { QuerySetup } from '../query/query_service';
+import { QuerySetup } from '../query';
import { GetInternalStartServicesFn } from '../types';
import { SearchInterceptor } from './search_interceptor';
import {
diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts
index 6bad093d31402..6e878844664ad 100644
--- a/src/plugins/data/public/search/search_source/search_source.test.ts
+++ b/src/plugins/data/public/search/search_source/search_source.test.ts
@@ -20,8 +20,26 @@
import { SearchSource } from './search_source';
import { IndexPattern, SortDirection } from '../..';
import { mockDataServices } from '../aggs/test_helpers';
+import { setSearchService } from '../../services';
+import { searchStartMock } from '../mocks';
+import { fetchSoon } from '../legacy';
+import { CoreStart } from 'kibana/public';
+import { Observable } from 'rxjs';
-jest.mock('../fetch', () => ({
+// Setup search service mock
+searchStartMock.search = jest.fn(() => {
+ return new Observable(subscriber => {
+ setTimeout(() => {
+ subscriber.next({
+ rawResponse: '',
+ });
+ subscriber.complete();
+ }, 100);
+ });
+}) as any;
+setSearchService(searchStartMock);
+
+jest.mock('../legacy', () => ({
fetchSoon: jest.fn().mockResolvedValue({}),
}));
@@ -44,8 +62,11 @@ const indexPattern2 = ({
} as unknown) as IndexPattern;
describe('SearchSource', function() {
+ let uiSettingsMock: jest.Mocked;
beforeEach(() => {
- mockDataServices();
+ const { core } = mockDataServices();
+ uiSettingsMock = core.uiSettings;
+ jest.clearAllMocks();
});
describe('#setField()', function() {
@@ -151,6 +172,36 @@ describe('SearchSource', function() {
});
});
+ describe('#legacy fetch()', () => {
+ beforeEach(() => {
+ uiSettingsMock.get.mockImplementation(() => {
+ return true; // batchSearches = true
+ });
+ });
+
+ afterEach(() => {
+ uiSettingsMock.get.mockImplementation(() => {
+ return false; // batchSearches = false
+ });
+ });
+
+ it('should call msearch', async () => {
+ const searchSource = new SearchSource({ index: indexPattern });
+ const options = {};
+ await searchSource.fetch(options);
+ expect(fetchSoon).toBeCalledTimes(1);
+ });
+ });
+
+ describe('#search service fetch()', () => {
+ it('should call msearch', async () => {
+ const searchSource = new SearchSource({ index: indexPattern });
+ const options = {};
+ await searchSource.fetch(options);
+ expect(searchStartMock.search).toBeCalledTimes(1);
+ });
+ });
+
describe('#serialize', function() {
it('should reference index patterns', () => {
const indexPattern123 = { id: '123' } as IndexPattern;
diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts
index c70db7bb82ef7..9d2bb889953cf 100644
--- a/src/plugins/data/public/search/search_source/search_source.ts
+++ b/src/plugins/data/public/search/search_source/search_source.ts
@@ -70,17 +70,19 @@
*/
import _ from 'lodash';
+import { map } from 'rxjs/operators';
import { SavedObjectReference } from 'kibana/public';
import { normalizeSortRequest } from './normalize_sort_request';
import { filterDocvalueFields } from './filter_docvalue_fields';
import { fieldWildcardFilter } from '../../../../kibana_utils/public';
import { IIndexPattern, SearchRequest } from '../..';
import { SearchSourceOptions, SearchSourceFields } from './types';
-import { fetchSoon, FetchOptions, RequestFailure } from '../fetch';
+import { FetchOptions, RequestFailure, getSearchParams, handleResponse } from '../fetch';
import { getSearchService, getUiSettings, getInjectedMetadata } from '../../services';
import { getEsQueryConfig, buildEsQuery, Filter } from '../../../common';
import { getHighlightRequest } from '../../../common/field_formats';
+import { fetchSoon } from '../legacy';
export type ISearchSource = Pick;
@@ -185,18 +187,29 @@ export class SearchSource {
}
/**
- * Fetch this source and reject the returned Promise on error
- *
- * @async
+ * Run a search using the search service
+ * @return {Observable>}
*/
- async fetch(options: FetchOptions = {}) {
- await this.requestIsStarting(options);
-
- const searchRequest = await this.flatten();
- this.history = [searchRequest];
+ private fetch$(searchRequest: SearchRequest, signal?: AbortSignal) {
+ const esShardTimeout = getInjectedMetadata().getInjectedVar('esShardTimeout') as number;
+ const searchParams = getSearchParams(getUiSettings(), esShardTimeout);
+ const params = {
+ index: searchRequest.index.title || searchRequest.index,
+ body: searchRequest.body,
+ ...searchParams,
+ };
+ return getSearchService()
+ .search({ params, indexType: searchRequest.indexType }, { signal })
+ .pipe(map(({ rawResponse }) => handleResponse(searchRequest, rawResponse)));
+ }
+ /**
+ * Run a search using the search service
+ * @return {Promise>}
+ */
+ private async legacyFetch(searchRequest: SearchRequest, options: FetchOptions) {
const esShardTimeout = getInjectedMetadata().getInjectedVar('esShardTimeout') as number;
- const response = await fetchSoon(
+ return await fetchSoon(
searchRequest,
{
...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }),
@@ -208,6 +221,24 @@ export class SearchSource {
esShardTimeout,
}
);
+ }
+ /**
+ * Fetch this source and reject the returned Promise on error
+ *
+ * @async
+ */
+ async fetch(options: FetchOptions = {}) {
+ await this.requestIsStarting(options);
+
+ const searchRequest = await this.flatten();
+ this.history = [searchRequest];
+
+ let response;
+ if (getUiSettings().get('courier:batchSearches')) {
+ response = await this.legacyFetch(searchRequest, options);
+ } else {
+ response = this.fetch$(searchRequest, options.abortSignal).toPromise();
+ }
if (response.error) {
throw new RequestFailure(null, response);
@@ -246,7 +277,6 @@ export class SearchSource {
/**
* Called by requests of this search source when they are started
- * @param {Courier.Request} request
* @param options
* @return {Promise}
*/
@@ -430,7 +460,6 @@ export class SearchSource {
* and `kibanaSavedObjectMeta.searchSourceJSON.filter[].meta.index`.
*
* Using `createSearchSource`, the instance can be re-created.
- * @param searchSource The search source to serialize
* @public */
public serialize() {
const references: SavedObjectReference[] = [];
diff --git a/src/plugins/data/public/search/search_strategy/no_op_search_strategy.ts b/src/plugins/data/public/search/search_strategy/no_op_search_strategy.ts
deleted file mode 100644
index dc7331e614a0e..0000000000000
--- a/src/plugins/data/public/search/search_strategy/no_op_search_strategy.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { i18n } from '@kbn/i18n';
-import { SearchError } from './search_error';
-import { SearchStrategyProvider } from './types';
-
-export const noOpSearchStrategy: SearchStrategyProvider = {
- id: 'noOp',
-
- search: () => {
- const searchError = new SearchError({
- status: '418', // "I'm a teapot" error
- title: i18n.translate(
- 'data.search.searchSource.noSearchStrategyRegisteredErrorMessageTitle',
- {
- defaultMessage: 'No search strategy registered',
- }
- ),
- message: i18n.translate(
- 'data.search.searchSource.noSearchStrategyRegisteredErrorMessageDescription',
- {
- defaultMessage: `Couldn't find a search strategy for the search request`,
- }
- ),
- type: 'NO_OP_SEARCH_STRATEGY',
- path: '',
- });
-
- return {
- searching: Promise.reject(searchError),
- abort: () => {},
- };
- },
-
- isViable: () => {
- return true;
- },
-};
diff --git a/src/plugins/data/public/search/types.ts b/src/plugins/data/public/search/types.ts
index ba6e44f47b75e..2122e4e82ec1d 100644
--- a/src/plugins/data/public/search/types.ts
+++ b/src/plugins/data/public/search/types.ts
@@ -22,7 +22,7 @@ import { createSearchSource } from './search_source';
import { SearchAggsSetup, SearchAggsStart, SearchAggsStartLegacy } from './aggs';
import { ISearch, ISearchGeneric } from './i_search';
import { TStrategyTypes } from './strategy_types';
-import { LegacyApiCaller } from './es_client';
+import { LegacyApiCaller } from './legacy/es_client';
import { SearchInterceptor } from './search_interceptor';
export interface ISearchContext {
@@ -38,15 +38,6 @@ export interface ISearchStrategy {
search: ISearch;
}
-/**
- * Search strategy provider creates an instance of a search strategy with the request
- * handler context bound to it. This way every search strategy can use
- * whatever information they require from the request context.
- */
-export type TSearchStrategyProviderEnhanced = (
- search: ISearchGeneric
-) => Promise>;
-
export type TSearchStrategiesMap = {
[K in TStrategyTypes]?: TSearchStrategyProvider;
};
diff --git a/src/plugins/expressions/kibana.json b/src/plugins/expressions/kibana.json
index cba693dd4bc20..5d2112103e94d 100644
--- a/src/plugins/expressions/kibana.json
+++ b/src/plugins/expressions/kibana.json
@@ -4,7 +4,6 @@
"server": true,
"ui": true,
"requiredPlugins": [
- "bfetch",
- "inspector"
+ "bfetch"
]
}
diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts
index fbe2f37c648d6..418ff6fdf8614 100644
--- a/src/plugins/expressions/public/loader.ts
+++ b/src/plugins/expressions/public/loader.ts
@@ -19,13 +19,14 @@
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
-import { Adapters, InspectorSession } from '../../inspector/public';
-import { ExpressionRenderHandler } from './render';
+import { Adapters } from '../../inspector/public';
import { IExpressionLoaderParams } from './types';
import { ExpressionAstExpression } from '../common';
-import { getInspector, getExpressionsService } from './services';
import { ExecutionContract } from '../common/execution/execution_contract';
+import { ExpressionRenderHandler } from './render';
+import { getExpressionsService } from './services';
+
type Data = any;
export class ExpressionLoader {
@@ -120,15 +121,6 @@ export class ExpressionLoader {
return this.renderHandler.getElement();
}
- openInspector(title: string): InspectorSession | undefined {
- const inspector = this.inspect();
- if (inspector) {
- return getInspector().open(inspector, {
- title,
- });
- }
- }
-
inspect(): Adapters | undefined {
return this.execution ? (this.execution.inspect() as Adapters) : undefined;
}
diff --git a/src/plugins/expressions/public/mocks.tsx b/src/plugins/expressions/public/mocks.tsx
index cb7089f814643..b8f2f693e9c77 100644
--- a/src/plugins/expressions/public/mocks.tsx
+++ b/src/plugins/expressions/public/mocks.tsx
@@ -22,7 +22,6 @@ import { ExpressionsSetup, ExpressionsStart, plugin as pluginInitializer } from
/* eslint-disable */
import { coreMock } from '../../../core/public/mocks';
-import { inspectorPluginMock } from '../../inspector/public/mocks';
import { bfetchPluginMock } from '../../bfetch/public/mocks';
/* eslint-enable */
@@ -89,7 +88,6 @@ const createPlugin = async () => {
const plugin = pluginInitializer(pluginInitializerContext);
const setup = await plugin.setup(coreSetup, {
bfetch: bfetchPluginMock.createSetupContract(),
- inspector: inspectorPluginMock.createSetupContract(),
});
return {
@@ -101,7 +99,6 @@ const createPlugin = async () => {
doStart: async () =>
await plugin.start(coreStart, {
bfetch: bfetchPluginMock.createStartContract(),
- inspector: inspectorPluginMock.createStartContract(),
}),
};
};
diff --git a/src/plugins/expressions/public/plugin.ts b/src/plugins/expressions/public/plugin.ts
index 7c0de271b7706..720c3b701d504 100644
--- a/src/plugins/expressions/public/plugin.ts
+++ b/src/plugins/expressions/public/plugin.ts
@@ -29,11 +29,9 @@ import {
ExpressionsServiceStart,
ExecutionContext,
} from '../common';
-import { Setup as InspectorSetup, Start as InspectorStart } from '../../inspector/public';
import { BfetchPublicSetup, BfetchPublicStart } from '../../bfetch/public';
import {
setCoreStart,
- setInspector,
setInterpreter,
setRenderersRegistry,
setNotifications,
@@ -45,12 +43,10 @@ import { render, ExpressionRenderHandler } from './render';
export interface ExpressionsSetupDeps {
bfetch: BfetchPublicSetup;
- inspector: InspectorSetup;
}
export interface ExpressionsStartDeps {
bfetch: BfetchPublicStart;
- inspector: InspectorStart;
}
export interface ExpressionsSetup extends ExpressionsServiceSetup {
@@ -120,7 +116,7 @@ export class ExpressionsPublicPlugin
});
}
- public setup(core: CoreSetup, { inspector, bfetch }: ExpressionsSetupDeps): ExpressionsSetup {
+ public setup(core: CoreSetup, { bfetch }: ExpressionsSetupDeps): ExpressionsSetup {
this.configureExecutor(core);
const { expressions } = this;
@@ -180,9 +176,8 @@ export class ExpressionsPublicPlugin
return Object.freeze(setup);
}
- public start(core: CoreStart, { inspector, bfetch }: ExpressionsStartDeps): ExpressionsStart {
+ public start(core: CoreStart, { bfetch }: ExpressionsStartDeps): ExpressionsStart {
setCoreStart(core);
- setInspector(inspector);
setNotifications(core.notifications);
const { expressions } = this;
diff --git a/src/plugins/expressions/public/react_expression_renderer.tsx b/src/plugins/expressions/public/react_expression_renderer.tsx
index 242a49c6d6639..2c99f173c9f33 100644
--- a/src/plugins/expressions/public/react_expression_renderer.tsx
+++ b/src/plugins/expressions/public/react_expression_renderer.tsx
@@ -17,8 +17,7 @@
* under the License.
*/
-import { useRef, useEffect, useState, useLayoutEffect } from 'react';
-import React from 'react';
+import React, { useRef, useEffect, useState, useLayoutEffect } from 'react';
import classNames from 'classnames';
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
diff --git a/src/plugins/expressions/public/render.ts b/src/plugins/expressions/public/render.ts
index ad4d16bcd1323..4aaf0da60fc60 100644
--- a/src/plugins/expressions/public/render.ts
+++ b/src/plugins/expressions/public/render.ts
@@ -21,10 +21,11 @@ import * as Rx from 'rxjs';
import { Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
import { RenderError, RenderErrorHandlerFnType, IExpressionLoaderParams } from './types';
-import { getRenderersRegistry } from './services';
import { renderErrorHandler as defaultRenderErrorHandler } from './render_error_handler';
import { IInterpreterRenderHandlers, ExpressionAstExpression } from '../common';
+import { getRenderersRegistry } from './services';
+
export type IExpressionRendererExtraHandlers = Record;
export interface ExpressionRenderHandlerParams {
diff --git a/src/plugins/expressions/public/services.ts b/src/plugins/expressions/public/services.ts
index a203e87414571..016456c956666 100644
--- a/src/plugins/expressions/public/services.ts
+++ b/src/plugins/expressions/public/services.ts
@@ -20,14 +20,11 @@
import { NotificationsStart } from 'kibana/public';
import { createKibanaUtilsCore, createGetterSetter } from '../../kibana_utils/public';
import { ExpressionInterpreter } from './types';
-import { Start as IInspector } from '../../inspector/public';
import { ExpressionsSetup } from './plugin';
import { ExpressionsService } from '../common';
export const { getCoreStart, setCoreStart } = createKibanaUtilsCore();
-export const [getInspector, setInspector] = createGetterSetter('Inspector');
-
export const [getInterpreter, setInterpreter] = createGetterSetter(
'Interpreter'
);
diff --git a/src/plugins/kibana_legacy/public/mocks.ts b/src/plugins/kibana_legacy/public/mocks.ts
index 8e9a05b186191..2fdd0d8b4be59 100644
--- a/src/plugins/kibana_legacy/public/mocks.ts
+++ b/src/plugins/kibana_legacy/public/mocks.ts
@@ -25,6 +25,7 @@ export type Start = jest.Mocked>;
const createSetupContract = (): Setup => ({
forwardApp: jest.fn(),
+ registerLegacyAppAlias: jest.fn(),
registerLegacyApp: jest.fn(),
config: {
defaultAppId: 'home',
@@ -37,6 +38,7 @@ const createSetupContract = (): Setup => ({
const createStartContract = (): Start => ({
getApps: jest.fn(),
+ getLegacyAppAliases: jest.fn(),
getForwards: jest.fn(),
config: {
defaultAppId: 'home',
diff --git a/src/plugins/kibana_legacy/public/plugin.ts b/src/plugins/kibana_legacy/public/plugin.ts
index 2ad620f355848..831fc3f0d4a71 100644
--- a/src/plugins/kibana_legacy/public/plugin.ts
+++ b/src/plugins/kibana_legacy/public/plugin.ts
@@ -28,12 +28,18 @@ import { Observable } from 'rxjs';
import { ConfigSchema } from '../config';
import { getDashboardConfig } from './dashboard_config';
-interface ForwardDefinition {
+interface LegacyAppAliasDefinition {
legacyAppId: string;
newAppId: string;
keepPrefix: boolean;
}
+interface ForwardDefinition {
+ legacyAppId: string;
+ newAppId: string;
+ rewritePath: (legacyPath: string) => string;
+}
+
export type AngularRenderedAppUpdater = (
app: AppBase
) => Partial | undefined;
@@ -54,7 +60,8 @@ export interface AngularRenderedApp extends App {
export class KibanaLegacyPlugin {
private apps: AngularRenderedApp[] = [];
- private forwards: ForwardDefinition[] = [];
+ private legacyAppAliases: LegacyAppAliasDefinition[] = [];
+ private forwardDefinitions: ForwardDefinition[] = [];
constructor(private readonly initializerContext: PluginInitializerContext) {}
@@ -94,17 +101,55 @@ export class KibanaLegacyPlugin {
* renaming or nesting plugins. For route changes after the prefix, please
* use the routing mechanism of your app.
*
+ * This method just redirects URLs within the legacy `kibana` app.
+ *
* @param legacyAppId The name of the old app to forward URLs from
* @param newAppId The name of the new app that handles the URLs now
* @param options Whether the prefix of the old app is kept to nest the legacy
* path into the new path
*/
- forwardApp: (
+ registerLegacyAppAlias: (
legacyAppId: string,
newAppId: string,
options: { keepPrefix: boolean } = { keepPrefix: false }
) => {
- this.forwards.push({ legacyAppId, newAppId, ...options });
+ this.legacyAppAliases.push({ legacyAppId, newAppId, ...options });
+ },
+
+ /**
+ * Forwards URLs within the legacy `kibana` app to a new platform application.
+ *
+ * @param legacyAppId The name of the old app to forward URLs from
+ * @param newAppId The name of the new app that handles the URLs now
+ * @param rewritePath Function to rewrite the legacy sub path of the app to the new path in the core app
+ * path into the new path
+ *
+ * Example usage:
+ * ```
+ * kibanaLegacy.forwardApp(
+ * 'old',
+ * 'new',
+ * path => {
+ * const [, id] = /old/item\/(.*)$/.exec(path) || [];
+ * if (!id) {
+ * return '#/home';
+ * }
+ * return '#/items/${id}';
+ * }
+ * );
+ * ```
+ * This will cause the following redirects:
+ *
+ * * app/kibana#/old/ -> app/new#/home
+ * * app/kibana#/old/item/123 -> app/new#/items/123
+ *
+ */
+ forwardApp: (
+ legacyAppId: string,
+ newAppId: string,
+ rewritePath: (legacyPath: string) => string
+ ) => {
+ this.forwardDefinitions.push({ legacyAppId, newAppId, rewritePath });
},
/**
@@ -132,7 +177,12 @@ export class KibanaLegacyPlugin {
* @deprecated
* Just exported for wiring up with legacy platform, should not be used.
*/
- getForwards: () => this.forwards,
+ getLegacyAppAliases: () => this.legacyAppAliases,
+ /**
+ * @deprecated
+ * Just exported for wiring up with legacy platform, should not be used.
+ */
+ getForwards: () => this.forwardDefinitions,
config: this.initializerContext.config.get(),
dashboardConfig: getDashboardConfig(!application.capabilities.dashboard.showWriteControls),
};
diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts
index 9ad9f14ac5659..9bec91b859ab7 100644
--- a/src/plugins/kibana_react/public/index.ts
+++ b/src/plugins/kibana_react/public/index.ts
@@ -25,7 +25,7 @@ export * from './ui_settings';
export * from './field_icon';
export * from './table_list_view';
export * from './split_panel';
-export { ValidatedDualRange } from './validated_range';
+export { ValidatedDualRange, Value } from './validated_range';
export * from './notifications';
export { Markdown, MarkdownSimple } from './markdown';
export { reactToUiComponent, uiToReactComponent } from './adapters';
diff --git a/src/plugins/kibana_react/public/validated_range/index.ts b/src/plugins/kibana_react/public/validated_range/index.ts
index bc643373f5e60..7d720ec842a43 100644
--- a/src/plugins/kibana_react/public/validated_range/index.ts
+++ b/src/plugins/kibana_react/public/validated_range/index.ts
@@ -17,4 +17,4 @@
* under the License.
*/
-export { ValidatedDualRange } from './validated_dual_range';
+export { ValidatedDualRange, Value } from './validated_dual_range';
diff --git a/src/plugins/kibana_utils/public/core/create_start_service_getter.test.ts b/src/plugins/kibana_utils/public/core/create_start_service_getter.test.ts
new file mode 100644
index 0000000000000..9d9b21269e102
--- /dev/null
+++ b/src/plugins/kibana_utils/public/core/create_start_service_getter.test.ts
@@ -0,0 +1,78 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { StartServicesAccessor } from '../../../../core/public';
+import { createStartServicesGetter } from './create_start_service_getter';
+import { Defer } from '../../common/defer';
+
+describe('createStartServicesGetter', () => {
+ test('throws if services are accessed before accessor resolves', async () => {
+ const future = new Defer();
+ const accessor: StartServicesAccessor = async () => await future.promise;
+ const start = createStartServicesGetter(accessor);
+
+ await new Promise(r => setTimeout(r, 1));
+
+ expect(() => start()).toThrowErrorMatchingInlineSnapshot(
+ `"Trying to access start services before start."`
+ );
+ });
+
+ test('returns services after accessor resolves even if first time called before it resolved', async () => {
+ const future = new Defer();
+ const core = {};
+ const plugins = {};
+ const self = {};
+ const accessor: StartServicesAccessor = async () => await future.promise;
+ const start = createStartServicesGetter(accessor);
+
+ await new Promise(r => setTimeout(r, 1));
+
+ expect(() => start()).toThrow();
+
+ await new Promise(r => setTimeout(r, 1));
+ future.resolve([core, plugins, self]);
+ await future.promise;
+
+ expect(start()).toEqual({
+ core,
+ plugins,
+ self,
+ });
+ });
+
+ test('returns services if called after accessor resolves', async () => {
+ const future = new Defer();
+ const core = {};
+ const plugins = {};
+ const self = {};
+ const accessor: StartServicesAccessor = async () => await future.promise;
+ const start = createStartServicesGetter(accessor);
+
+ await new Promise(r => setTimeout(r, 1));
+ future.resolve([core, plugins, self]);
+ await future.promise;
+
+ expect(start()).toEqual({
+ core,
+ plugins,
+ self,
+ });
+ });
+});
diff --git a/src/plugins/kibana_utils/public/core/create_start_service_getter.ts b/src/plugins/kibana_utils/public/core/create_start_service_getter.ts
new file mode 100644
index 0000000000000..5e385eb5ed473
--- /dev/null
+++ b/src/plugins/kibana_utils/public/core/create_start_service_getter.ts
@@ -0,0 +1,98 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { CoreStart, StartServicesAccessor } from '../../../../core/public';
+
+export interface StartServices {
+ plugins: Plugins;
+ self: OwnContract;
+ core: CoreStart;
+}
+
+export type StartServicesGetter = () => StartServices<
+ Plugins,
+ OwnContract
+>;
+
+/**
+ * Use this utility to create a synchronous *start* service getter in *setup*
+ * life-cycle of your plugin.
+ *
+ * Below is a usage example in a Kibana plugin.
+ *
+ * ```ts
+ * export interface MyPluginStartDeps {
+ * data: DataPublicPluginStart;
+ * expressions: ExpressionsStart;
+ * inspector: InspectorStart;
+ * uiActions: UiActionsStart;
+ * }
+ *
+ * class MyPlugin implements Plugin {
+ * setup(core: CoreSetup, plugins) {
+ * const start = createStartServicesGetter(core.getStartServices);
+ * plugins.expressions.registerFunction(myExpressionFunction(start));
+ * }
+ *
+ * start(core, plugins: MyPluginStartDeps) {
+ *
+ * }
+ * }
+ * ```
+ *
+ * In `myExpressionFunction` you can make sure you are picking only the dependencies
+ * your function needs using the `Pick` type.
+ *
+ * ```ts
+ * const myExpressionFunction =
+ * (start: StartServicesGetter>) => {
+ *
+ * start().plugins.indexPatterns.something(123);
+ * }
+ * ```
+ *
+ * @param accessor Asynchronous start service accessor provided by platform.
+ * @returns Returns a function which synchronously returns *start* core services
+ * and plugin contracts. If you call this function before the *start* life-cycle
+ * has started it will throw.
+ */
+export const createStartServicesGetter = (
+ accessor: StartServicesAccessor
+): StartServicesGetter => {
+ let services: StartServices | undefined;
+
+ accessor().then(
+ ([core, plugins, self]) => {
+ services = {
+ core,
+ plugins,
+ self,
+ };
+ },
+ error => {
+ // eslint-disable-next-line no-console
+ console.error('Could not access start services.', error);
+ }
+ );
+
+ return () => {
+ if (!services) throw new Error('Trying to access start services before start.');
+ return services;
+ };
+};
diff --git a/src/plugins/kibana_utils/public/core/index.ts b/src/plugins/kibana_utils/public/core/index.ts
index 3f08d591300a2..8bbb2129071f5 100644
--- a/src/plugins/kibana_utils/public/core/index.ts
+++ b/src/plugins/kibana_utils/public/core/index.ts
@@ -18,3 +18,4 @@
*/
export * from './create_kibana_utils_core';
+export * from './create_start_service_getter';
diff --git a/src/plugins/maps_legacy/public/__tests__/map/service_settings.js b/src/plugins/maps_legacy/public/__tests__/map/service_settings.js
index a9272ea396639..4cbe098501c67 100644
--- a/src/plugins/maps_legacy/public/__tests__/map/service_settings.js
+++ b/src/plugins/maps_legacy/public/__tests__/map/service_settings.js
@@ -143,24 +143,24 @@ describe('service_settings (FKA tilemaptest)', function() {
}
it('accepts an object', async () => {
- serviceSettings.addQueryParams({ foo: 'bar' });
+ serviceSettings.setQueryParams({ foo: 'bar' });
tilemapServices = await serviceSettings.getTMSServices();
await assertQuery({ foo: 'bar' });
});
it('merged additions with previous values', async () => {
// ensure that changes are always additive
- serviceSettings.addQueryParams({ foo: 'bar' });
- serviceSettings.addQueryParams({ bar: 'stool' });
+ serviceSettings.setQueryParams({ foo: 'bar' });
+ serviceSettings.setQueryParams({ bar: 'stool' });
tilemapServices = await serviceSettings.getTMSServices();
await assertQuery({ foo: 'bar', bar: 'stool' });
});
it('overwrites conflicting previous values', async () => {
// ensure that conflicts are overwritten
- serviceSettings.addQueryParams({ foo: 'bar' });
- serviceSettings.addQueryParams({ bar: 'stool' });
- serviceSettings.addQueryParams({ foo: 'tstool' });
+ serviceSettings.setQueryParams({ foo: 'bar' });
+ serviceSettings.setQueryParams({ bar: 'stool' });
+ serviceSettings.setQueryParams({ foo: 'tstool' });
tilemapServices = await serviceSettings.getTMSServices();
await assertQuery({ foo: 'tstool', bar: 'stool' });
});
@@ -168,7 +168,7 @@ describe('service_settings (FKA tilemaptest)', function() {
it('when overridden, should continue to work', async () => {
mapConfig.emsFileApiUrl = emsFileApiUrl2;
mapConfig.emsTileApiUrl = emsTileApiUrl2;
- serviceSettings.addQueryParams({ foo: 'bar' });
+ serviceSettings.setQueryParams({ foo: 'bar' });
tilemapServices = await serviceSettings.getTMSServices();
await assertQuery({ foo: 'bar' });
});
@@ -292,7 +292,7 @@ describe('service_settings (FKA tilemaptest)', function() {
describe('File layers', function() {
it('should load manifest (all props)', async function() {
- serviceSettings.addQueryParams({ foo: 'bar' });
+ serviceSettings.setQueryParams({ foo: 'bar' });
const fileLayers = await serviceSettings.getFileLayers();
expect(fileLayers.length).to.be(18);
const assertions = fileLayers.map(async function(fileLayer) {
diff --git a/src/plugins/maps_legacy/public/map/service_settings.js b/src/plugins/maps_legacy/public/map/service_settings.js
index 11c853d39e107..f4f0d66ee20de 100644
--- a/src/plugins/maps_legacy/public/map/service_settings.js
+++ b/src/plugins/maps_legacy/public/map/service_settings.js
@@ -69,6 +69,10 @@ export class ServiceSettings {
return origin === ORIGIN.EMS && this._showZoomMessage;
}
+ enableZoomMessage() {
+ this._showZoomMessage = true;
+ }
+
disableZoomMessage() {
this._showZoomMessage = false;
}
@@ -148,11 +152,12 @@ export class ServiceSettings {
}
/**
- * Add optional query-parameters to all requests
+ * Set optional query-parameters for all requests
*
* @param additionalQueryParams
*/
- addQueryParams(additionalQueryParams) {
+ setQueryParams(additionalQueryParams) {
+ // Functions more as a "set" than an "add" in ems-client
this._emsClient.addQueryParams(additionalQueryParams);
}
diff --git a/src/plugins/telemetry/server/config.ts b/src/plugins/telemetry/server/config.ts
index 9621a8b5619b2..99dde0c3b3d96 100644
--- a/src/plugins/telemetry/server/config.ts
+++ b/src/plugins/telemetry/server/config.ts
@@ -36,8 +36,8 @@ export const configSchema = schema.object({
config: schema.string({ defaultValue: getConfigPath() }),
banner: schema.boolean({ defaultValue: true }),
url: schema.conditional(
- schema.contextRef('dev'),
- schema.literal(true),
+ schema.contextRef('dist'),
+ schema.literal(false), // Point to staging if it's not a distributable release
schema.string({
defaultValue: `https://telemetry-staging.elastic.co/xpack/${ENDPOINT_VERSION}/send`,
}),
@@ -46,8 +46,8 @@ export const configSchema = schema.object({
})
),
optInStatusUrl: schema.conditional(
- schema.contextRef('dev'),
- schema.literal(true),
+ schema.contextRef('dist'),
+ schema.literal(false), // Point to staging if it's not a distributable release
schema.string({
defaultValue: `https://telemetry-staging.elastic.co/opt_in_status/${ENDPOINT_VERSION}/send`,
}),
diff --git a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts
index c04625eb1dd42..6d64268569e06 100644
--- a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts
+++ b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts
@@ -22,14 +22,14 @@ import { encryptTelemetry, getKID } from './encrypt';
describe('getKID', () => {
it(`returns 'kibana_dev' kid for development`, async () => {
- const isProd = false;
- const kid = getKID(isProd);
+ const useProdKey = false;
+ const kid = getKID(useProdKey);
expect(kid).toBe('kibana_dev');
});
it(`returns 'kibana_prod' kid for development`, async () => {
- const isProd = true;
- const kid = getKID(isProd);
+ const useProdKey = true;
+ const kid = getKID(useProdKey);
expect(kid).toBe('kibana');
});
});
@@ -41,19 +41,19 @@ describe('encryptTelemetry', () => {
it('encrypts payload', async () => {
const payload = { some: 'value' };
- await encryptTelemetry(payload, { isProd: true });
+ await encryptTelemetry(payload, { useProdKey: true });
expect(createRequestEncryptor).toBeCalledWith(telemetryJWKS);
});
- it('uses kibana kid on { isProd: true }', async () => {
+ it('uses kibana kid on { useProdKey: true }', async () => {
const payload = { some: 'value' };
- await encryptTelemetry(payload, { isProd: true });
+ await encryptTelemetry(payload, { useProdKey: true });
expect(mockEncrypt).toBeCalledWith('kibana', payload);
});
- it('uses kibana_dev kid on { isProd: false }', async () => {
+ it('uses kibana_dev kid on { useProdKey: false }', async () => {
const payload = { some: 'value' };
- await encryptTelemetry(payload, { isProd: false });
+ await encryptTelemetry(payload, { useProdKey: false });
expect(mockEncrypt).toBeCalledWith('kibana_dev', payload);
});
});
diff --git a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts
index 44f053064cfcb..89f34d794f059 100644
--- a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts
+++ b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts
@@ -20,12 +20,15 @@
import { createRequestEncryptor } from '@elastic/request-crypto';
import { telemetryJWKS } from './telemetry_jwks';
-export function getKID(isProd = false): string {
- return isProd ? 'kibana' : 'kibana_dev';
+export function getKID(useProdKey = false): string {
+ return useProdKey ? 'kibana' : 'kibana_dev';
}
-export async function encryptTelemetry(payload: any, { isProd = false } = {}): Promise {
- const kid = getKID(isProd);
+export async function encryptTelemetry(
+ payload: any,
+ { useProdKey = false } = {}
+): Promise {
+ const kid = getKID(useProdKey);
const encryptor = await createRequestEncryptor(telemetryJWKS);
const clusters = [].concat(payload);
return Promise.all(clusters.map((cluster: any) => encryptor.encrypt(kid, cluster)));
diff --git a/src/plugins/telemetry_collection_manager/server/plugin.ts b/src/plugins/telemetry_collection_manager/server/plugin.ts
index f2f20e215c535..0b57fae83c0fb 100644
--- a/src/plugins/telemetry_collection_manager/server/plugin.ts
+++ b/src/plugins/telemetry_collection_manager/server/plugin.ts
@@ -50,12 +50,12 @@ export class TelemetryCollectionManagerPlugin
private readonly collections: Array> = [];
private usageGetterMethodPriority = -1;
private usageCollection?: UsageCollectionSetup;
- private readonly isDev: boolean;
+ private readonly isDistributable: boolean;
private readonly version: string;
constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get();
- this.isDev = initializerContext.env.mode.dev;
+ this.isDistributable = initializerContext.env.packageInfo.dist;
this.version = initializerContext.env.packageInfo.version;
}
@@ -158,7 +158,7 @@ export class TelemetryCollectionManagerPlugin
if (config.unencrypted) {
return optInStats;
}
- return encryptTelemetry(optInStats, { isProd: !this.isDev });
+ return encryptTelemetry(optInStats, { useProdKey: this.isDistributable });
}
} catch (err) {
this.logger.debug(`Failed to collect any opt in stats with registered collections.`);
@@ -176,7 +176,6 @@ export class TelemetryCollectionManagerPlugin
) => {
const context: StatsCollectionContext = {
logger: this.logger.get(collection.title),
- isDev: this.isDev,
version: this.version,
...collection.customContext,
};
@@ -206,7 +205,7 @@ export class TelemetryCollectionManagerPlugin
return usageData;
}
- return encryptTelemetry(usageData, { isProd: !this.isDev });
+ return encryptTelemetry(usageData, { useProdKey: this.isDistributable });
}
} catch (err) {
this.logger.debug(
@@ -225,7 +224,6 @@ export class TelemetryCollectionManagerPlugin
): Promise {
const context: StatsCollectionContext = {
logger: this.logger.get(collection.title),
- isDev: this.isDev,
version: this.version,
...collection.customContext,
};
diff --git a/src/plugins/telemetry_collection_manager/server/types.ts b/src/plugins/telemetry_collection_manager/server/types.ts
index e23d6a4c388f4..d3a47694d38a7 100644
--- a/src/plugins/telemetry_collection_manager/server/types.ts
+++ b/src/plugins/telemetry_collection_manager/server/types.ts
@@ -101,7 +101,6 @@ export interface ESLicense {
export interface StatsCollectionContext {
logger: Logger;
- isDev: boolean;
version: string;
}
diff --git a/src/plugins/timelion/kibana.json b/src/plugins/timelion/kibana.json
deleted file mode 100644
index dddfd6c67e655..0000000000000
--- a/src/plugins/timelion/kibana.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "id": "timelion",
- "version": "8.0.0",
- "kibanaVersion": "kibana",
- "configPath": ["timelion"],
- "server": true,
- "ui": true
-}
diff --git a/src/plugins/timelion/public/index.ts b/src/plugins/timelion/public/index.ts
deleted file mode 100644
index b05c4f8a30b22..0000000000000
--- a/src/plugins/timelion/public/index.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { CoreStart, PluginInitializerContext } from 'kibana/public';
-import { ConfigSchema } from '../config';
-
-export const plugin = (initializerContext: PluginInitializerContext) => ({
- setup() {},
- start(core: CoreStart) {
- if (initializerContext.config.get().ui.enabled === false) {
- core.chrome.navLinks.update('timelion', { hidden: true });
- }
- },
-});
diff --git a/src/legacy/core_plugins/vis_type_timelion/README.md b/src/plugins/vis_type_timelion/README.md
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/README.md
rename to src/plugins/vis_type_timelion/README.md
diff --git a/src/plugins/timelion/common/chain.peg b/src/plugins/vis_type_timelion/common/chain.peg
similarity index 100%
rename from src/plugins/timelion/common/chain.peg
rename to src/plugins/vis_type_timelion/common/chain.peg
diff --git a/src/plugins/timelion/common/lib/calculate_interval.test.ts b/src/plugins/vis_type_timelion/common/lib/calculate_interval.test.ts
similarity index 100%
rename from src/plugins/timelion/common/lib/calculate_interval.test.ts
rename to src/plugins/vis_type_timelion/common/lib/calculate_interval.test.ts
diff --git a/src/plugins/timelion/common/lib/calculate_interval.ts b/src/plugins/vis_type_timelion/common/lib/calculate_interval.ts
similarity index 100%
rename from src/plugins/timelion/common/lib/calculate_interval.ts
rename to src/plugins/vis_type_timelion/common/lib/calculate_interval.ts
diff --git a/src/plugins/timelion/common/lib/index.ts b/src/plugins/vis_type_timelion/common/lib/index.ts
similarity index 100%
rename from src/plugins/timelion/common/lib/index.ts
rename to src/plugins/vis_type_timelion/common/lib/index.ts
diff --git a/src/plugins/timelion/common/lib/to_milliseconds.ts b/src/plugins/vis_type_timelion/common/lib/to_milliseconds.ts
similarity index 100%
rename from src/plugins/timelion/common/lib/to_milliseconds.ts
rename to src/plugins/vis_type_timelion/common/lib/to_milliseconds.ts
diff --git a/src/plugins/timelion/common/types.ts b/src/plugins/vis_type_timelion/common/types.ts
similarity index 100%
rename from src/plugins/timelion/common/types.ts
rename to src/plugins/vis_type_timelion/common/types.ts
diff --git a/src/plugins/timelion/config.ts b/src/plugins/vis_type_timelion/config.ts
similarity index 100%
rename from src/plugins/timelion/config.ts
rename to src/plugins/vis_type_timelion/config.ts
diff --git a/src/plugins/vis_type_timelion/kibana.json b/src/plugins/vis_type_timelion/kibana.json
new file mode 100644
index 0000000000000..85c282c51a2e7
--- /dev/null
+++ b/src/plugins/vis_type_timelion/kibana.json
@@ -0,0 +1,8 @@
+{
+ "id": "visTypeTimelion",
+ "version": "8.0.0",
+ "kibanaVersion": "kibana",
+ "server": true,
+ "ui": true,
+ "requiredPlugins": ["visualizations", "data", "expressions"]
+}
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/_generated_/chain.js b/src/plugins/vis_type_timelion/public/_generated_/chain.js
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/_generated_/chain.js
rename to src/plugins/vis_type_timelion/public/_generated_/chain.js
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/_timelion_editor.scss b/src/plugins/vis_type_timelion/public/_timelion_editor.scss
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/_timelion_editor.scss
rename to src/plugins/vis_type_timelion/public/_timelion_editor.scss
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/_timelion_vis.scss b/src/plugins/vis_type_timelion/public/_timelion_vis.scss
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/_timelion_vis.scss
rename to src/plugins/vis_type_timelion/public/_timelion_vis.scss
diff --git a/src/plugins/vis_type_timelion/public/components/_index.scss b/src/plugins/vis_type_timelion/public/components/_index.scss
new file mode 100644
index 0000000000000..707c9dafebe2b
--- /dev/null
+++ b/src/plugins/vis_type_timelion/public/components/_index.scss
@@ -0,0 +1,2 @@
+@import 'panel';
+@import 'timelion_expression_input';
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/_panel.scss b/src/plugins/vis_type_timelion/public/components/_panel.scss
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/_panel.scss
rename to src/plugins/vis_type_timelion/public/components/_panel.scss
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/_timelion_expression_input.scss b/src/plugins/vis_type_timelion/public/components/_timelion_expression_input.scss
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/_timelion_expression_input.scss
rename to src/plugins/vis_type_timelion/public/components/_timelion_expression_input.scss
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/chart.tsx b/src/plugins/vis_type_timelion/public/components/chart.tsx
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/chart.tsx
rename to src/plugins/vis_type_timelion/public/components/chart.tsx
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/index.ts b/src/plugins/vis_type_timelion/public/components/index.ts
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/index.ts
rename to src/plugins/vis_type_timelion/public/components/index.ts
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx b/src/plugins/vis_type_timelion/public/components/panel.tsx
similarity index 98%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx
rename to src/plugins/vis_type_timelion/public/components/panel.tsx
index 3b42fa7dfcbb8..8f796526e8520 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx
+++ b/src/plugins/vis_type_timelion/public/components/panel.tsx
@@ -22,9 +22,9 @@ import $ from 'jquery';
import moment from 'moment-timezone';
import { debounce, compact, get, each, cloneDeep, last, map } from 'lodash';
-import { useKibana } from '../../../../../plugins/kibana_react/public';
+import { useKibana } from '../../../kibana_react/public';
import '../flot';
-import { DEFAULT_TIME_FORMAT } from '../../../../../plugins/timelion/common/lib';
+import { DEFAULT_TIME_FORMAT } from '../../common/lib';
import {
buildSeriesData,
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx b/src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx
similarity index 96%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx
rename to src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx
index c317451b8201e..999409ef35063 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx
+++ b/src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx
@@ -22,13 +22,10 @@ import { EuiFormLabel } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { monaco } from '@kbn/ui-shared-deps/monaco';
-import { CodeEditor, useKibana } from '../../../../../plugins/kibana_react/public';
+import { CodeEditor, useKibana } from '../../../kibana_react/public';
import { suggest, getSuggestion } from './timelion_expression_input_helpers';
import { getArgValueSuggestions } from '../helpers/arg_value_suggestions';
-import {
- ITimelionFunction,
- TimelionFunctionArgs,
-} from '../../../../../plugins/timelion/common/types';
+import { ITimelionFunction, TimelionFunctionArgs } from '../../common/types';
const LANGUAGE_ID = 'timelion_expression';
monaco.languages.register({ id: LANGUAGE_ID });
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts
similarity index 99%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts
rename to src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts
index 2f99256e2a192..2ff6809d1c83d 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts
+++ b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts
@@ -22,7 +22,7 @@ import { getArgValueSuggestions } from '../helpers/arg_value_suggestions';
import { setIndexPatterns, setSavedObjectsClient } from '../helpers/plugin_services';
import { IndexPatternsContract } from 'src/plugins/data/public';
import { SavedObjectsClient } from 'kibana/public';
-import { ITimelionFunction } from '../../../../../plugins/timelion/common/types';
+import { ITimelionFunction } from '../../common/types';
describe('Timelion expression suggestions', () => {
setIndexPatterns({} as IndexPatternsContract);
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts
similarity index 98%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts
rename to src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts
index 6f23c864419eb..04cb54306c90e 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts
+++ b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts
@@ -27,10 +27,7 @@ import { Parser } from 'pegjs';
import { parse } from '../_generated_/chain';
import { ArgValueSuggestions, FunctionArg, Location } from '../helpers/arg_value_suggestions';
-import {
- ITimelionFunction,
- TimelionFunctionArgs,
-} from '../../../../../plugins/timelion/common/types';
+import { ITimelionFunction, TimelionFunctionArgs } from '../../common/types';
export enum SUGGESTION_TYPE {
ARGUMENTS = 'arguments',
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_interval.tsx b/src/plugins/vis_type_timelion/public/components/timelion_interval.tsx
similarity index 96%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_interval.tsx
rename to src/plugins/vis_type_timelion/public/components/timelion_interval.tsx
index 8a8e1b22fb78d..985ecaeaf3e5a 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_interval.tsx
+++ b/src/plugins/vis_type_timelion/public/components/timelion_interval.tsx
@@ -21,9 +21,9 @@ import React, { useMemo, useCallback } from 'react';
import { EuiFormRow, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { search } from '../../../../../plugins/data/public';
+import { search } from '../../../data/public';
const { isValidEsInterval } = search.aggs;
-import { useValidation } from '../../../../../plugins/vis_default_editor/public';
+import { useValidation } from '../../../vis_default_editor/public';
const intervalOptions = [
{
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx b/src/plugins/vis_type_timelion/public/components/timelion_vis.tsx
similarity index 95%
rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx
rename to src/plugins/vis_type_timelion/public/components/timelion_vis.tsx
index 0fad0a164bf0b..4bb07fe74ee82 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx
+++ b/src/plugins/vis_type_timelion/public/components/timelion_vis.tsx
@@ -23,7 +23,7 @@ import { IUiSettingsClient } from 'kibana/public';
import { ChartComponent } from './chart';
import { VisParams } from '../timelion_vis_fn';
import { TimelionSuccessResponse } from '../helpers/timelion_request_handler';
-import { ExprVis } from '../../../../../plugins/visualizations/public';
+import { ExprVis } from '../../../visualizations/public';
export interface TimelionVisComponentProp {
config: IUiSettingsClient;
diff --git a/src/plugins/vis_type_timelion/public/flot.js b/src/plugins/vis_type_timelion/public/flot.js
new file mode 100644
index 0000000000000..1ccb40c93a3d6
--- /dev/null
+++ b/src/plugins/vis_type_timelion/public/flot.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import './webpackShims/jquery.flot';
+import './webpackShims/jquery.flot.time';
+import './webpackShims/jquery.flot.symbol';
+import './webpackShims/jquery.flot.crosshair';
+import './webpackShims/jquery.flot.selection';
+import './webpackShims/jquery.flot.stack';
+import './webpackShims/jquery.flot.axislabels';
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts b/src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts
similarity index 97%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts
rename to src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts
index ea9532964d6fe..76c25b9b9e8de 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts
+++ b/src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts
@@ -19,11 +19,8 @@
import { get } from 'lodash';
import { getIndexPatterns, getSavedObjectsClient } from './plugin_services';
-import { TimelionFunctionArgs } from '../../../../../plugins/timelion/common/types';
-import {
- indexPatterns as indexPatternsUtils,
- IndexPatternAttributes,
-} from '../../../../../plugins/data/public';
+import { TimelionFunctionArgs } from '../../common/types';
+import { indexPatterns as indexPatternsUtils, IndexPatternAttributes } from '../../../data/public';
export interface Location {
min: number;
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/get_timezone.ts b/src/plugins/vis_type_timelion/public/helpers/get_timezone.ts
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/get_timezone.ts
rename to src/plugins/vis_type_timelion/public/helpers/get_timezone.ts
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts b/src/plugins/vis_type_timelion/public/helpers/panel_utils.ts
similarity index 98%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts
rename to src/plugins/vis_type_timelion/public/helpers/panel_utils.ts
index f932e5ee4b2f4..db29d9112be8e 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts
+++ b/src/plugins/vis_type_timelion/public/helpers/panel_utils.ts
@@ -23,7 +23,7 @@ import moment, { Moment } from 'moment-timezone';
import { TimefilterContract } from 'src/plugins/data/public';
import { IUiSettingsClient } from 'kibana/public';
-import { calculateInterval } from '../../../../../plugins/timelion/common/lib';
+import { calculateInterval } from '../../common/lib';
import { xaxisFormatterProvider } from './xaxis_formatter';
import { Series } from './timelion_request_handler';
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/plugin_services.ts b/src/plugins/vis_type_timelion/public/helpers/plugin_services.ts
similarity index 93%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/plugin_services.ts
rename to src/plugins/vis_type_timelion/public/helpers/plugin_services.ts
index 5ba4ee5e47983..b055626934eea 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/plugin_services.ts
+++ b/src/plugins/vis_type_timelion/public/helpers/plugin_services.ts
@@ -19,7 +19,7 @@
import { IndexPatternsContract } from 'src/plugins/data/public';
import { SavedObjectsClientContract } from 'kibana/public';
-import { createGetterSetter } from '../../../../../plugins/kibana_utils/public';
+import { createGetterSetter } from '../../../kibana_utils/public';
export const [getIndexPatterns, setIndexPatterns] = createGetterSetter(
'IndexPatterns'
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_formatters.test.ts b/src/plugins/vis_type_timelion/public/helpers/tick_formatters.test.ts
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_formatters.test.ts
rename to src/plugins/vis_type_timelion/public/helpers/tick_formatters.test.ts
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_formatters.ts b/src/plugins/vis_type_timelion/public/helpers/tick_formatters.ts
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_formatters.ts
rename to src/plugins/vis_type_timelion/public/helpers/tick_formatters.ts
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_generator.test.ts b/src/plugins/vis_type_timelion/public/helpers/tick_generator.test.ts
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_generator.test.ts
rename to src/plugins/vis_type_timelion/public/helpers/tick_generator.test.ts
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_generator.ts b/src/plugins/vis_type_timelion/public/helpers/tick_generator.ts
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_generator.ts
rename to src/plugins/vis_type_timelion/public/helpers/tick_generator.ts
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts
similarity index 95%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts
rename to src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts
index 61e31420f73ba..a654f7935af5f 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts
+++ b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts
@@ -19,8 +19,8 @@
import { i18n } from '@kbn/i18n';
import { KIBANA_CONTEXT_NAME } from 'src/plugins/expressions/public';
-import { VisParams } from '../../../../../plugins/visualizations/public';
-import { TimeRange, Filter, esQuery, Query } from '../../../../../plugins/data/public';
+import { VisParams } from '../../../visualizations/public';
+import { TimeRange, Filter, esQuery, Query } from '../../../data/public';
import { TimelionVisDependencies } from '../plugin';
import { getTimezone } from './get_timezone';
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/xaxis_formatter.ts b/src/plugins/vis_type_timelion/public/helpers/xaxis_formatter.ts
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/xaxis_formatter.ts
rename to src/plugins/vis_type_timelion/public/helpers/xaxis_formatter.ts
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/index.scss b/src/plugins/vis_type_timelion/public/index.scss
similarity index 59%
rename from src/legacy/core_plugins/vis_type_timelion/public/index.scss
rename to src/plugins/vis_type_timelion/public/index.scss
index 313f14a8acf69..00e9a88520961 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/index.scss
+++ b/src/plugins/vis_type_timelion/public/index.scss
@@ -1,5 +1,3 @@
-@import 'src/legacy/ui/public/styles/styling_constants';
-
@import './timelion_vis';
@import './timelion_editor';
@import './components/index';
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/index.ts b/src/plugins/vis_type_timelion/public/index.ts
similarity index 90%
rename from src/legacy/core_plugins/vis_type_timelion/public/index.ts
rename to src/plugins/vis_type_timelion/public/index.ts
index 6292e2ad3eb08..0aa5f3a810033 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/index.ts
+++ b/src/plugins/vis_type_timelion/public/index.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { PluginInitializerContext } from '../../../../core/public';
+import { PluginInitializerContext } from 'kibana/public';
import { TimelionVisPlugin as Plugin } from './plugin';
export function plugin(initializerContext: PluginInitializerContext) {
@@ -25,3 +25,5 @@ export function plugin(initializerContext: PluginInitializerContext) {
}
export { getTimezone } from './helpers/get_timezone';
+
+export { VisTypeTimelionPluginStart } from './plugin';
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/plugin.ts b/src/plugins/vis_type_timelion/public/plugin.ts
similarity index 67%
rename from src/legacy/core_plugins/vis_type_timelion/public/plugin.ts
rename to src/plugins/vis_type_timelion/public/plugin.ts
index b5aa64db19aa4..060fec04deb3f 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/plugin.ts
+++ b/src/plugins/vis_type_timelion/public/plugin.ts
@@ -26,16 +26,21 @@ import {
HttpSetup,
} from 'kibana/public';
import { Plugin as ExpressionsPlugin } from 'src/plugins/expressions/public';
-import { DataPublicPluginSetup, TimefilterContract } from 'src/plugins/data/public';
+import {
+ DataPublicPluginSetup,
+ DataPublicPluginStart,
+ TimefilterContract,
+} from 'src/plugins/data/public';
-import { PluginsStart } from './legacy_imports';
-import { VisualizationsSetup } from '../../../../plugins/visualizations/public';
+import { VisualizationsSetup } from '../../visualizations/public';
import { getTimelionVisualizationConfig } from './timelion_vis_fn';
import { getTimelionVisDefinition } from './timelion_vis_type';
import { setIndexPatterns, setSavedObjectsClient } from './helpers/plugin_services';
+import { ConfigSchema } from '../config';
-type TimelionVisCoreSetup = CoreSetup;
+import './index.scss';
+import { getArgValueSuggestions } from './helpers/arg_value_suggestions';
/** @internal */
export interface TimelionVisDependencies extends Partial {
@@ -52,11 +57,28 @@ export interface TimelionVisSetupDependencies {
}
/** @internal */
-export class TimelionVisPlugin implements Plugin {
- constructor(public initializerContext: PluginInitializerContext) {}
+export interface TimelionVisStartDependencies {
+ data: DataPublicPluginStart;
+}
+
+/** @public */
+export interface VisTypeTimelionPluginStart {
+ getArgValueSuggestions: typeof getArgValueSuggestions;
+}
+
+/** @internal */
+export class TimelionVisPlugin
+ implements
+ Plugin<
+ void,
+ VisTypeTimelionPluginStart,
+ TimelionVisSetupDependencies,
+ TimelionVisStartDependencies
+ > {
+ constructor(public initializerContext: PluginInitializerContext) {}
- public async setup(
- core: TimelionVisCoreSetup,
+ public setup(
+ core: CoreSetup,
{ expressions, visualizations, data }: TimelionVisSetupDependencies
) {
const dependencies: TimelionVisDependencies = {
@@ -69,8 +91,15 @@ export class TimelionVisPlugin implements Plugin {
visualizations.createReactVisualization(getTimelionVisDefinition(dependencies));
}
- public start(core: CoreStart, plugins: PluginsStart) {
+ public start(core: CoreStart, plugins: TimelionVisStartDependencies) {
setIndexPatterns(plugins.data.indexPatterns);
setSavedObjectsClient(core.savedObjects.client);
+ if (this.initializerContext.config.get().ui.enabled === false) {
+ core.chrome.navLinks.update('timelion', { hidden: true });
+ }
+
+ return {
+ getArgValueSuggestions,
+ };
}
}
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/timelion_options.tsx b/src/plugins/vis_type_timelion/public/timelion_options.tsx
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/timelion_options.tsx
rename to src/plugins/vis_type_timelion/public/timelion_options.tsx
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_fn.ts b/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_fn.ts
rename to src/plugins/vis_type_timelion/public/timelion_vis_fn.ts
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_type.tsx b/src/plugins/vis_type_timelion/public/timelion_vis_type.tsx
similarity index 93%
rename from src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_type.tsx
rename to src/plugins/vis_type_timelion/public/timelion_vis_type.tsx
index 0900b7d898ede..52addb3c2d9d2 100644
--- a/src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_type.tsx
+++ b/src/plugins/vis_type_timelion/public/timelion_vis_type.tsx
@@ -20,8 +20,8 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
-import { KibanaContextProvider } from '../../../../plugins/kibana_react/public';
-import { DefaultEditorSize } from '../../../../plugins/vis_default_editor/public';
+import { KibanaContextProvider } from '../../kibana_react/public';
+import { DefaultEditorSize } from '../../vis_default_editor/public';
import { getTimelionRequestHandler } from './helpers/timelion_request_handler';
import { TimelionVisComponent, TimelionVisComponentProp } from './components';
import { TimelionOptions, TimelionOptionsProps } from './timelion_options';
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.axislabels.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.axislabels.js
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.axislabels.js
rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.axislabels.js
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.crosshair.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.crosshair.js
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.crosshair.js
rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.crosshair.js
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.js
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.js
rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.js
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.selection.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.selection.js
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.selection.js
rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.selection.js
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.stack.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.stack.js
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.stack.js
rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.stack.js
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.symbol.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.symbol.js
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.symbol.js
rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.symbol.js
diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.time.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.time.js
similarity index 100%
rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.time.js
rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.time.js
diff --git a/src/plugins/timelion/server/fit_functions/average.js b/src/plugins/vis_type_timelion/server/fit_functions/average.js
similarity index 100%
rename from src/plugins/timelion/server/fit_functions/average.js
rename to src/plugins/vis_type_timelion/server/fit_functions/average.js
diff --git a/src/plugins/timelion/server/fit_functions/average.test.js b/src/plugins/vis_type_timelion/server/fit_functions/average.test.js
similarity index 100%
rename from src/plugins/timelion/server/fit_functions/average.test.js
rename to src/plugins/vis_type_timelion/server/fit_functions/average.test.js
diff --git a/src/plugins/timelion/server/fit_functions/carry.js b/src/plugins/vis_type_timelion/server/fit_functions/carry.js
similarity index 100%
rename from src/plugins/timelion/server/fit_functions/carry.js
rename to src/plugins/vis_type_timelion/server/fit_functions/carry.js
diff --git a/src/plugins/timelion/server/fit_functions/carry.test.js b/src/plugins/vis_type_timelion/server/fit_functions/carry.test.js
similarity index 100%
rename from src/plugins/timelion/server/fit_functions/carry.test.js
rename to src/plugins/vis_type_timelion/server/fit_functions/carry.test.js
diff --git a/src/plugins/timelion/server/fit_functions/nearest.js b/src/plugins/vis_type_timelion/server/fit_functions/nearest.js
similarity index 100%
rename from src/plugins/timelion/server/fit_functions/nearest.js
rename to src/plugins/vis_type_timelion/server/fit_functions/nearest.js
diff --git a/src/plugins/timelion/server/fit_functions/none.js b/src/plugins/vis_type_timelion/server/fit_functions/none.js
similarity index 100%
rename from src/plugins/timelion/server/fit_functions/none.js
rename to src/plugins/vis_type_timelion/server/fit_functions/none.js
diff --git a/src/plugins/timelion/server/fit_functions/scale.js b/src/plugins/vis_type_timelion/server/fit_functions/scale.js
similarity index 100%
rename from src/plugins/timelion/server/fit_functions/scale.js
rename to src/plugins/vis_type_timelion/server/fit_functions/scale.js
diff --git a/src/plugins/timelion/server/handlers/chain_runner.js b/src/plugins/vis_type_timelion/server/handlers/chain_runner.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/chain_runner.js
rename to src/plugins/vis_type_timelion/server/handlers/chain_runner.js
diff --git a/src/plugins/timelion/server/handlers/lib/arg_type.js b/src/plugins/vis_type_timelion/server/handlers/lib/arg_type.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/lib/arg_type.js
rename to src/plugins/vis_type_timelion/server/handlers/lib/arg_type.js
diff --git a/src/plugins/timelion/server/handlers/lib/index_arguments.js b/src/plugins/vis_type_timelion/server/handlers/lib/index_arguments.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/lib/index_arguments.js
rename to src/plugins/vis_type_timelion/server/handlers/lib/index_arguments.js
diff --git a/src/plugins/timelion/server/handlers/lib/parse_sheet.js b/src/plugins/vis_type_timelion/server/handlers/lib/parse_sheet.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/lib/parse_sheet.js
rename to src/plugins/vis_type_timelion/server/handlers/lib/parse_sheet.js
diff --git a/src/plugins/timelion/server/handlers/lib/parse_sheet.test.js b/src/plugins/vis_type_timelion/server/handlers/lib/parse_sheet.test.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/lib/parse_sheet.test.js
rename to src/plugins/vis_type_timelion/server/handlers/lib/parse_sheet.test.js
diff --git a/src/plugins/timelion/server/handlers/lib/preprocess_chain.js b/src/plugins/vis_type_timelion/server/handlers/lib/preprocess_chain.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/lib/preprocess_chain.js
rename to src/plugins/vis_type_timelion/server/handlers/lib/preprocess_chain.js
diff --git a/src/plugins/timelion/server/handlers/lib/reposition_arguments.js b/src/plugins/vis_type_timelion/server/handlers/lib/reposition_arguments.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/lib/reposition_arguments.js
rename to src/plugins/vis_type_timelion/server/handlers/lib/reposition_arguments.js
diff --git a/src/plugins/timelion/server/handlers/lib/tl_config.js b/src/plugins/vis_type_timelion/server/handlers/lib/tl_config.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/lib/tl_config.js
rename to src/plugins/vis_type_timelion/server/handlers/lib/tl_config.js
diff --git a/src/plugins/timelion/server/handlers/lib/validate_arg.js b/src/plugins/vis_type_timelion/server/handlers/lib/validate_arg.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/lib/validate_arg.js
rename to src/plugins/vis_type_timelion/server/handlers/lib/validate_arg.js
diff --git a/src/plugins/timelion/server/handlers/lib/validate_time.js b/src/plugins/vis_type_timelion/server/handlers/lib/validate_time.js
similarity index 100%
rename from src/plugins/timelion/server/handlers/lib/validate_time.js
rename to src/plugins/vis_type_timelion/server/handlers/lib/validate_time.js
diff --git a/src/plugins/timelion/server/index.ts b/src/plugins/vis_type_timelion/server/index.ts
similarity index 64%
rename from src/plugins/timelion/server/index.ts
rename to src/plugins/vis_type_timelion/server/index.ts
index 5d420327f961e..b40ab2af2b0d7 100644
--- a/src/plugins/timelion/server/index.ts
+++ b/src/plugins/vis_type_timelion/server/index.ts
@@ -17,19 +17,23 @@
* under the License.
*/
-import { PluginInitializerContext } from '../../../../src/core/server';
-import { configSchema } from '../config';
+import { PluginConfigDescriptor, PluginInitializerContext } from '../../../../src/core/server';
+import { configSchema, ConfigSchema } from '../config';
import { Plugin } from './plugin';
export { PluginSetupContract } from './plugin';
-export const config = {
+export const config: PluginConfigDescriptor = {
schema: configSchema,
exposeToBrowser: {
- ui: {
- enabled: true,
- },
+ ui: true,
},
+ deprecations: ({ renameFromRoot }) => [
+ renameFromRoot('timelion_vis.enabled', 'vis_type_timelion.enabled'),
+ renameFromRoot('timelion.enabled', 'vis_type_timelion.enabled'),
+ renameFromRoot('timelion.graphiteUrls', 'vis_type_timelion.graphiteUrls'),
+ renameFromRoot('timelion.ui.enabled', 'vis_type_timelion.ui.enabled'),
+ ],
};
export const plugin = (initializerContext: PluginInitializerContext) =>
new Plugin(initializerContext);
diff --git a/src/plugins/timelion/server/lib/alter.js b/src/plugins/vis_type_timelion/server/lib/alter.js
similarity index 100%
rename from src/plugins/timelion/server/lib/alter.js
rename to src/plugins/vis_type_timelion/server/lib/alter.js
diff --git a/src/plugins/timelion/server/lib/as_sorted.js b/src/plugins/vis_type_timelion/server/lib/as_sorted.js
similarity index 100%
rename from src/plugins/timelion/server/lib/as_sorted.js
rename to src/plugins/vis_type_timelion/server/lib/as_sorted.js
diff --git a/src/plugins/timelion/server/lib/build_target.js b/src/plugins/vis_type_timelion/server/lib/build_target.js
similarity index 100%
rename from src/plugins/timelion/server/lib/build_target.js
rename to src/plugins/vis_type_timelion/server/lib/build_target.js
diff --git a/src/plugins/timelion/server/lib/classes/chainable.js b/src/plugins/vis_type_timelion/server/lib/classes/chainable.js
similarity index 100%
rename from src/plugins/timelion/server/lib/classes/chainable.js
rename to src/plugins/vis_type_timelion/server/lib/classes/chainable.js
diff --git a/src/plugins/timelion/server/lib/classes/datasource.js b/src/plugins/vis_type_timelion/server/lib/classes/datasource.js
similarity index 100%
rename from src/plugins/timelion/server/lib/classes/datasource.js
rename to src/plugins/vis_type_timelion/server/lib/classes/datasource.js
diff --git a/src/plugins/timelion/server/lib/classes/timelion_function.d.ts b/src/plugins/vis_type_timelion/server/lib/classes/timelion_function.d.ts
similarity index 100%
rename from src/plugins/timelion/server/lib/classes/timelion_function.d.ts
rename to src/plugins/vis_type_timelion/server/lib/classes/timelion_function.d.ts
diff --git a/src/plugins/timelion/server/lib/classes/timelion_function.js b/src/plugins/vis_type_timelion/server/lib/classes/timelion_function.js
similarity index 100%
rename from src/plugins/timelion/server/lib/classes/timelion_function.js
rename to src/plugins/vis_type_timelion/server/lib/classes/timelion_function.js
diff --git a/src/plugins/timelion/server/lib/config_manager.ts b/src/plugins/vis_type_timelion/server/lib/config_manager.ts
similarity index 100%
rename from src/plugins/timelion/server/lib/config_manager.ts
rename to src/plugins/vis_type_timelion/server/lib/config_manager.ts
diff --git a/src/plugins/timelion/server/lib/functions_md.js b/src/plugins/vis_type_timelion/server/lib/functions_md.js
similarity index 100%
rename from src/plugins/timelion/server/lib/functions_md.js
rename to src/plugins/vis_type_timelion/server/lib/functions_md.js
diff --git a/src/plugins/timelion/server/lib/get_namespaced_settings.js b/src/plugins/vis_type_timelion/server/lib/get_namespaced_settings.js
similarity index 100%
rename from src/plugins/timelion/server/lib/get_namespaced_settings.js
rename to src/plugins/vis_type_timelion/server/lib/get_namespaced_settings.js
diff --git a/src/plugins/timelion/server/lib/load_functions.d.ts b/src/plugins/vis_type_timelion/server/lib/load_functions.d.ts
similarity index 100%
rename from src/plugins/timelion/server/lib/load_functions.d.ts
rename to src/plugins/vis_type_timelion/server/lib/load_functions.d.ts
diff --git a/src/plugins/timelion/server/lib/load_functions.js b/src/plugins/vis_type_timelion/server/lib/load_functions.js
similarity index 100%
rename from src/plugins/timelion/server/lib/load_functions.js
rename to src/plugins/vis_type_timelion/server/lib/load_functions.js
diff --git a/src/plugins/timelion/server/lib/load_functions.test.js b/src/plugins/vis_type_timelion/server/lib/load_functions.test.js
similarity index 94%
rename from src/plugins/timelion/server/lib/load_functions.test.js
rename to src/plugins/vis_type_timelion/server/lib/load_functions.test.js
index ebe1a04532e05..b4f83611a7773 100644
--- a/src/plugins/timelion/server/lib/load_functions.test.js
+++ b/src/plugins/vis_type_timelion/server/lib/load_functions.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-const fn = require(`src/plugins/timelion/server/lib/load_functions`);
+const fn = require(`src/plugins/vis_type_timelion/server/lib/load_functions`);
const expect = require('chai').expect;
diff --git a/src/plugins/timelion/server/lib/offset_time.js b/src/plugins/vis_type_timelion/server/lib/offset_time.js
similarity index 100%
rename from src/plugins/timelion/server/lib/offset_time.js
rename to src/plugins/vis_type_timelion/server/lib/offset_time.js
diff --git a/src/plugins/timelion/server/lib/offset_time.test.js b/src/plugins/vis_type_timelion/server/lib/offset_time.test.js
similarity index 100%
rename from src/plugins/timelion/server/lib/offset_time.test.js
rename to src/plugins/vis_type_timelion/server/lib/offset_time.test.js
diff --git a/src/plugins/timelion/server/lib/process_function_definition.js b/src/plugins/vis_type_timelion/server/lib/process_function_definition.js
similarity index 100%
rename from src/plugins/timelion/server/lib/process_function_definition.js
rename to src/plugins/vis_type_timelion/server/lib/process_function_definition.js
diff --git a/src/plugins/timelion/server/lib/reduce.js b/src/plugins/vis_type_timelion/server/lib/reduce.js
similarity index 100%
rename from src/plugins/timelion/server/lib/reduce.js
rename to src/plugins/vis_type_timelion/server/lib/reduce.js
diff --git a/src/plugins/timelion/server/lib/split_interval.js b/src/plugins/vis_type_timelion/server/lib/split_interval.js
similarity index 100%
rename from src/plugins/timelion/server/lib/split_interval.js
rename to src/plugins/vis_type_timelion/server/lib/split_interval.js
diff --git a/src/plugins/timelion/server/lib/unzip_pairs.js b/src/plugins/vis_type_timelion/server/lib/unzip_pairs.js
similarity index 100%
rename from src/plugins/timelion/server/lib/unzip_pairs.js
rename to src/plugins/vis_type_timelion/server/lib/unzip_pairs.js
diff --git a/src/plugins/timelion/server/plugin.ts b/src/plugins/vis_type_timelion/server/plugin.ts
similarity index 100%
rename from src/plugins/timelion/server/plugin.ts
rename to src/plugins/vis_type_timelion/server/plugin.ts
diff --git a/src/plugins/timelion/server/routes/functions.ts b/src/plugins/vis_type_timelion/server/routes/functions.ts
similarity index 100%
rename from src/plugins/timelion/server/routes/functions.ts
rename to src/plugins/vis_type_timelion/server/routes/functions.ts
diff --git a/src/plugins/timelion/server/routes/run.ts b/src/plugins/vis_type_timelion/server/routes/run.ts
similarity index 100%
rename from src/plugins/timelion/server/routes/run.ts
rename to src/plugins/vis_type_timelion/server/routes/run.ts
diff --git a/src/plugins/timelion/server/routes/validate_es.ts b/src/plugins/vis_type_timelion/server/routes/validate_es.ts
similarity index 100%
rename from src/plugins/timelion/server/routes/validate_es.ts
rename to src/plugins/vis_type_timelion/server/routes/validate_es.ts
diff --git a/src/plugins/timelion/server/series_functions/abs.js b/src/plugins/vis_type_timelion/server/series_functions/abs.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/abs.js
rename to src/plugins/vis_type_timelion/server/series_functions/abs.js
diff --git a/src/plugins/timelion/server/series_functions/abs.test.js b/src/plugins/vis_type_timelion/server/series_functions/abs.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/abs.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/abs.test.js
diff --git a/src/plugins/timelion/server/series_functions/aggregate/aggregate.test.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/aggregate.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/aggregate/aggregate.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/aggregate.test.js
diff --git a/src/plugins/timelion/server/series_functions/aggregate/avg.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/avg.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/aggregate/avg.js
rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/avg.js
diff --git a/src/plugins/timelion/server/series_functions/aggregate/cardinality.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/cardinality.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/aggregate/cardinality.js
rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/cardinality.js
diff --git a/src/plugins/timelion/server/series_functions/aggregate/first.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/first.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/aggregate/first.js
rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/first.js
diff --git a/src/plugins/timelion/server/series_functions/aggregate/index.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/index.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/aggregate/index.js
rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/index.js
diff --git a/src/plugins/timelion/server/series_functions/aggregate/last.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/last.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/aggregate/last.js
rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/last.js
diff --git a/src/plugins/timelion/server/series_functions/aggregate/max.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/max.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/aggregate/max.js
rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/max.js
diff --git a/src/plugins/timelion/server/series_functions/aggregate/min.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/min.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/aggregate/min.js
rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/min.js
diff --git a/src/plugins/timelion/server/series_functions/aggregate/sum.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/sum.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/aggregate/sum.js
rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/sum.js
diff --git a/src/plugins/timelion/server/series_functions/bars.js b/src/plugins/vis_type_timelion/server/series_functions/bars.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/bars.js
rename to src/plugins/vis_type_timelion/server/series_functions/bars.js
diff --git a/src/plugins/timelion/server/series_functions/bars.test.js b/src/plugins/vis_type_timelion/server/series_functions/bars.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/bars.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/bars.test.js
diff --git a/src/plugins/timelion/server/series_functions/color.js b/src/plugins/vis_type_timelion/server/series_functions/color.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/color.js
rename to src/plugins/vis_type_timelion/server/series_functions/color.js
diff --git a/src/plugins/timelion/server/series_functions/color.test.js b/src/plugins/vis_type_timelion/server/series_functions/color.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/color.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/color.test.js
diff --git a/src/plugins/timelion/server/series_functions/condition.js b/src/plugins/vis_type_timelion/server/series_functions/condition.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/condition.js
rename to src/plugins/vis_type_timelion/server/series_functions/condition.js
diff --git a/src/plugins/timelion/server/series_functions/condition.test.js b/src/plugins/vis_type_timelion/server/series_functions/condition.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/condition.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/condition.test.js
diff --git a/src/plugins/timelion/server/series_functions/cusum.js b/src/plugins/vis_type_timelion/server/series_functions/cusum.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/cusum.js
rename to src/plugins/vis_type_timelion/server/series_functions/cusum.js
diff --git a/src/plugins/timelion/server/series_functions/cusum.test.js b/src/plugins/vis_type_timelion/server/series_functions/cusum.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/cusum.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/cusum.test.js
diff --git a/src/plugins/timelion/server/series_functions/derivative.js b/src/plugins/vis_type_timelion/server/series_functions/derivative.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/derivative.js
rename to src/plugins/vis_type_timelion/server/series_functions/derivative.js
diff --git a/src/plugins/timelion/server/series_functions/derivative.test.js b/src/plugins/vis_type_timelion/server/series_functions/derivative.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/derivative.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/derivative.test.js
diff --git a/src/plugins/timelion/server/series_functions/divide.js b/src/plugins/vis_type_timelion/server/series_functions/divide.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/divide.js
rename to src/plugins/vis_type_timelion/server/series_functions/divide.js
diff --git a/src/plugins/timelion/server/series_functions/divide.test.js b/src/plugins/vis_type_timelion/server/series_functions/divide.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/divide.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/divide.test.js
diff --git a/src/plugins/timelion/server/series_functions/es/es.test.js b/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/es/es.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/es/es.test.js
diff --git a/src/plugins/timelion/server/series_functions/es/index.js b/src/plugins/vis_type_timelion/server/series_functions/es/index.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/es/index.js
rename to src/plugins/vis_type_timelion/server/series_functions/es/index.js
diff --git a/src/plugins/timelion/server/series_functions/es/lib/agg_body.js b/src/plugins/vis_type_timelion/server/series_functions/es/lib/agg_body.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/es/lib/agg_body.js
rename to src/plugins/vis_type_timelion/server/series_functions/es/lib/agg_body.js
diff --git a/src/plugins/timelion/server/series_functions/es/lib/agg_response_to_series_list.js b/src/plugins/vis_type_timelion/server/series_functions/es/lib/agg_response_to_series_list.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/es/lib/agg_response_to_series_list.js
rename to src/plugins/vis_type_timelion/server/series_functions/es/lib/agg_response_to_series_list.js
diff --git a/src/plugins/timelion/server/series_functions/es/lib/build_request.js b/src/plugins/vis_type_timelion/server/series_functions/es/lib/build_request.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/es/lib/build_request.js
rename to src/plugins/vis_type_timelion/server/series_functions/es/lib/build_request.js
diff --git a/src/plugins/timelion/server/series_functions/es/lib/create_date_agg.js b/src/plugins/vis_type_timelion/server/series_functions/es/lib/create_date_agg.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/es/lib/create_date_agg.js
rename to src/plugins/vis_type_timelion/server/series_functions/es/lib/create_date_agg.js
diff --git a/src/plugins/timelion/server/series_functions/first.js b/src/plugins/vis_type_timelion/server/series_functions/first.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/first.js
rename to src/plugins/vis_type_timelion/server/series_functions/first.js
diff --git a/src/plugins/timelion/server/series_functions/first.test.js b/src/plugins/vis_type_timelion/server/series_functions/first.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/first.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/first.test.js
diff --git a/src/plugins/timelion/server/series_functions/fit.js b/src/plugins/vis_type_timelion/server/series_functions/fit.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/fit.js
rename to src/plugins/vis_type_timelion/server/series_functions/fit.js
diff --git a/src/plugins/timelion/server/series_functions/fit.test.js b/src/plugins/vis_type_timelion/server/series_functions/fit.test.js
similarity index 98%
rename from src/plugins/timelion/server/series_functions/fit.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/fit.test.js
index 75eaa2a50ea72..6622259a1fd87 100644
--- a/src/plugins/timelion/server/series_functions/fit.test.js
+++ b/src/plugins/vis_type_timelion/server/series_functions/fit.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-const fn = require(`src/plugins/timelion/server/series_functions/fit`);
+const fn = require(`src/plugins/vis_type_timelion/server/series_functions/fit`);
import moment from 'moment';
const expect = require('chai').expect;
import invoke from './helpers/invoke_series_fn.js';
diff --git a/src/plugins/timelion/server/series_functions/fixtures/bucket_list.js b/src/plugins/vis_type_timelion/server/series_functions/fixtures/bucket_list.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/fixtures/bucket_list.js
rename to src/plugins/vis_type_timelion/server/series_functions/fixtures/bucket_list.js
diff --git a/src/plugins/timelion/server/series_functions/fixtures/es_response.js b/src/plugins/vis_type_timelion/server/series_functions/fixtures/es_response.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/fixtures/es_response.js
rename to src/plugins/vis_type_timelion/server/series_functions/fixtures/es_response.js
diff --git a/src/plugins/timelion/server/series_functions/fixtures/series_list.js b/src/plugins/vis_type_timelion/server/series_functions/fixtures/series_list.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/fixtures/series_list.js
rename to src/plugins/vis_type_timelion/server/series_functions/fixtures/series_list.js
diff --git a/src/plugins/timelion/server/series_functions/fixtures/tl_config.js b/src/plugins/vis_type_timelion/server/series_functions/fixtures/tl_config.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/fixtures/tl_config.js
rename to src/plugins/vis_type_timelion/server/series_functions/fixtures/tl_config.js
diff --git a/src/plugins/timelion/server/series_functions/graphite.js b/src/plugins/vis_type_timelion/server/series_functions/graphite.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/graphite.js
rename to src/plugins/vis_type_timelion/server/series_functions/graphite.js
diff --git a/src/plugins/timelion/server/series_functions/graphite.test.js b/src/plugins/vis_type_timelion/server/series_functions/graphite.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/graphite.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/graphite.test.js
diff --git a/src/plugins/timelion/server/series_functions/helpers/get_series.js b/src/plugins/vis_type_timelion/server/series_functions/helpers/get_series.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/helpers/get_series.js
rename to src/plugins/vis_type_timelion/server/series_functions/helpers/get_series.js
diff --git a/src/plugins/timelion/server/series_functions/helpers/get_series_list.js b/src/plugins/vis_type_timelion/server/series_functions/helpers/get_series_list.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/helpers/get_series_list.js
rename to src/plugins/vis_type_timelion/server/series_functions/helpers/get_series_list.js
diff --git a/src/plugins/timelion/server/series_functions/helpers/get_single_series_list.js b/src/plugins/vis_type_timelion/server/series_functions/helpers/get_single_series_list.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/helpers/get_single_series_list.js
rename to src/plugins/vis_type_timelion/server/series_functions/helpers/get_single_series_list.js
diff --git a/src/plugins/timelion/server/series_functions/helpers/invoke_series_fn.js b/src/plugins/vis_type_timelion/server/series_functions/helpers/invoke_series_fn.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/helpers/invoke_series_fn.js
rename to src/plugins/vis_type_timelion/server/series_functions/helpers/invoke_series_fn.js
diff --git a/src/plugins/timelion/server/series_functions/hide.js b/src/plugins/vis_type_timelion/server/series_functions/hide.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/hide.js
rename to src/plugins/vis_type_timelion/server/series_functions/hide.js
diff --git a/src/plugins/timelion/server/series_functions/hide.test.js b/src/plugins/vis_type_timelion/server/series_functions/hide.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/hide.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/hide.test.js
diff --git a/src/plugins/timelion/server/series_functions/holt/index.js b/src/plugins/vis_type_timelion/server/series_functions/holt/index.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/holt/index.js
rename to src/plugins/vis_type_timelion/server/series_functions/holt/index.js
diff --git a/src/plugins/timelion/server/series_functions/holt/lib/des.js b/src/plugins/vis_type_timelion/server/series_functions/holt/lib/des.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/holt/lib/des.js
rename to src/plugins/vis_type_timelion/server/series_functions/holt/lib/des.js
diff --git a/src/plugins/timelion/server/series_functions/holt/lib/ses.js b/src/plugins/vis_type_timelion/server/series_functions/holt/lib/ses.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/holt/lib/ses.js
rename to src/plugins/vis_type_timelion/server/series_functions/holt/lib/ses.js
diff --git a/src/plugins/timelion/server/series_functions/holt/lib/tes.js b/src/plugins/vis_type_timelion/server/series_functions/holt/lib/tes.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/holt/lib/tes.js
rename to src/plugins/vis_type_timelion/server/series_functions/holt/lib/tes.js
diff --git a/src/plugins/timelion/server/series_functions/label.js b/src/plugins/vis_type_timelion/server/series_functions/label.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/label.js
rename to src/plugins/vis_type_timelion/server/series_functions/label.js
diff --git a/src/plugins/timelion/server/series_functions/label.test.js b/src/plugins/vis_type_timelion/server/series_functions/label.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/label.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/label.test.js
diff --git a/src/plugins/timelion/server/series_functions/legend.js b/src/plugins/vis_type_timelion/server/series_functions/legend.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/legend.js
rename to src/plugins/vis_type_timelion/server/series_functions/legend.js
diff --git a/src/plugins/timelion/server/series_functions/legend.test.js b/src/plugins/vis_type_timelion/server/series_functions/legend.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/legend.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/legend.test.js
diff --git a/src/plugins/timelion/server/series_functions/lines.js b/src/plugins/vis_type_timelion/server/series_functions/lines.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/lines.js
rename to src/plugins/vis_type_timelion/server/series_functions/lines.js
diff --git a/src/plugins/timelion/server/series_functions/lines.test.js b/src/plugins/vis_type_timelion/server/series_functions/lines.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/lines.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/lines.test.js
diff --git a/src/plugins/timelion/server/series_functions/log.js b/src/plugins/vis_type_timelion/server/series_functions/log.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/log.js
rename to src/plugins/vis_type_timelion/server/series_functions/log.js
diff --git a/src/plugins/timelion/server/series_functions/log.test.js b/src/plugins/vis_type_timelion/server/series_functions/log.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/log.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/log.test.js
diff --git a/src/plugins/timelion/server/series_functions/max.js b/src/plugins/vis_type_timelion/server/series_functions/max.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/max.js
rename to src/plugins/vis_type_timelion/server/series_functions/max.js
diff --git a/src/plugins/timelion/server/series_functions/max.test.js b/src/plugins/vis_type_timelion/server/series_functions/max.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/max.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/max.test.js
diff --git a/src/plugins/timelion/server/series_functions/min.js b/src/plugins/vis_type_timelion/server/series_functions/min.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/min.js
rename to src/plugins/vis_type_timelion/server/series_functions/min.js
diff --git a/src/plugins/timelion/server/series_functions/min.test.js b/src/plugins/vis_type_timelion/server/series_functions/min.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/min.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/min.test.js
diff --git a/src/plugins/timelion/server/series_functions/movingaverage.js b/src/plugins/vis_type_timelion/server/series_functions/movingaverage.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/movingaverage.js
rename to src/plugins/vis_type_timelion/server/series_functions/movingaverage.js
diff --git a/src/plugins/timelion/server/series_functions/movingaverage.test.js b/src/plugins/vis_type_timelion/server/series_functions/movingaverage.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/movingaverage.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/movingaverage.test.js
diff --git a/src/plugins/timelion/server/series_functions/movingstd.js b/src/plugins/vis_type_timelion/server/series_functions/movingstd.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/movingstd.js
rename to src/plugins/vis_type_timelion/server/series_functions/movingstd.js
diff --git a/src/plugins/timelion/server/series_functions/movingstd.test.js b/src/plugins/vis_type_timelion/server/series_functions/movingstd.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/movingstd.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/movingstd.test.js
diff --git a/src/plugins/timelion/server/series_functions/multiply.js b/src/plugins/vis_type_timelion/server/series_functions/multiply.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/multiply.js
rename to src/plugins/vis_type_timelion/server/series_functions/multiply.js
diff --git a/src/plugins/timelion/server/series_functions/multiply.test.js b/src/plugins/vis_type_timelion/server/series_functions/multiply.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/multiply.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/multiply.test.js
diff --git a/src/plugins/timelion/server/series_functions/points.js b/src/plugins/vis_type_timelion/server/series_functions/points.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/points.js
rename to src/plugins/vis_type_timelion/server/series_functions/points.js
diff --git a/src/plugins/timelion/server/series_functions/points.test.js b/src/plugins/vis_type_timelion/server/series_functions/points.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/points.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/points.test.js
diff --git a/src/plugins/timelion/server/series_functions/precision.js b/src/plugins/vis_type_timelion/server/series_functions/precision.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/precision.js
rename to src/plugins/vis_type_timelion/server/series_functions/precision.js
diff --git a/src/plugins/timelion/server/series_functions/precision.test.js b/src/plugins/vis_type_timelion/server/series_functions/precision.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/precision.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/precision.test.js
diff --git a/src/plugins/timelion/server/series_functions/props.js b/src/plugins/vis_type_timelion/server/series_functions/props.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/props.js
rename to src/plugins/vis_type_timelion/server/series_functions/props.js
diff --git a/src/plugins/timelion/server/series_functions/quandl.js b/src/plugins/vis_type_timelion/server/series_functions/quandl.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/quandl.js
rename to src/plugins/vis_type_timelion/server/series_functions/quandl.js
diff --git a/src/plugins/timelion/server/series_functions/quandl.test.js b/src/plugins/vis_type_timelion/server/series_functions/quandl.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/quandl.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/quandl.test.js
diff --git a/src/plugins/timelion/server/series_functions/range.js b/src/plugins/vis_type_timelion/server/series_functions/range.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/range.js
rename to src/plugins/vis_type_timelion/server/series_functions/range.js
diff --git a/src/plugins/timelion/server/series_functions/range.test.js b/src/plugins/vis_type_timelion/server/series_functions/range.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/range.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/range.test.js
diff --git a/src/plugins/timelion/server/series_functions/scale_interval.js b/src/plugins/vis_type_timelion/server/series_functions/scale_interval.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/scale_interval.js
rename to src/plugins/vis_type_timelion/server/series_functions/scale_interval.js
diff --git a/src/plugins/timelion/server/series_functions/scale_interval.test.js b/src/plugins/vis_type_timelion/server/series_functions/scale_interval.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/scale_interval.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/scale_interval.test.js
diff --git a/src/plugins/timelion/server/series_functions/static.js b/src/plugins/vis_type_timelion/server/series_functions/static.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/static.js
rename to src/plugins/vis_type_timelion/server/series_functions/static.js
diff --git a/src/plugins/timelion/server/series_functions/static.test.js b/src/plugins/vis_type_timelion/server/series_functions/static.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/static.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/static.test.js
diff --git a/src/plugins/timelion/server/series_functions/subtract.js b/src/plugins/vis_type_timelion/server/series_functions/subtract.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/subtract.js
rename to src/plugins/vis_type_timelion/server/series_functions/subtract.js
diff --git a/src/plugins/timelion/server/series_functions/subtract.test.js b/src/plugins/vis_type_timelion/server/series_functions/subtract.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/subtract.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/subtract.test.js
diff --git a/src/plugins/timelion/server/series_functions/sum.js b/src/plugins/vis_type_timelion/server/series_functions/sum.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/sum.js
rename to src/plugins/vis_type_timelion/server/series_functions/sum.js
diff --git a/src/plugins/timelion/server/series_functions/sum.test.js b/src/plugins/vis_type_timelion/server/series_functions/sum.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/sum.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/sum.test.js
diff --git a/src/plugins/timelion/server/series_functions/title.js b/src/plugins/vis_type_timelion/server/series_functions/title.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/title.js
rename to src/plugins/vis_type_timelion/server/series_functions/title.js
diff --git a/src/plugins/timelion/server/series_functions/title.test.js b/src/plugins/vis_type_timelion/server/series_functions/title.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/title.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/title.test.js
diff --git a/src/plugins/timelion/server/series_functions/trend/index.js b/src/plugins/vis_type_timelion/server/series_functions/trend/index.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/trend/index.js
rename to src/plugins/vis_type_timelion/server/series_functions/trend/index.js
diff --git a/src/plugins/timelion/server/series_functions/trend/lib/regress.js b/src/plugins/vis_type_timelion/server/series_functions/trend/lib/regress.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/trend/lib/regress.js
rename to src/plugins/vis_type_timelion/server/series_functions/trend/lib/regress.js
diff --git a/src/plugins/timelion/server/series_functions/trim.js b/src/plugins/vis_type_timelion/server/series_functions/trim.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/trim.js
rename to src/plugins/vis_type_timelion/server/series_functions/trim.js
diff --git a/src/plugins/timelion/server/series_functions/trim.test.js b/src/plugins/vis_type_timelion/server/series_functions/trim.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/trim.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/trim.test.js
diff --git a/src/plugins/timelion/server/series_functions/worldbank.js b/src/plugins/vis_type_timelion/server/series_functions/worldbank.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/worldbank.js
rename to src/plugins/vis_type_timelion/server/series_functions/worldbank.js
diff --git a/src/plugins/timelion/server/series_functions/worldbank_indicators.js b/src/plugins/vis_type_timelion/server/series_functions/worldbank_indicators.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/worldbank_indicators.js
rename to src/plugins/vis_type_timelion/server/series_functions/worldbank_indicators.js
diff --git a/src/plugins/timelion/server/series_functions/yaxis.js b/src/plugins/vis_type_timelion/server/series_functions/yaxis.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/yaxis.js
rename to src/plugins/vis_type_timelion/server/series_functions/yaxis.js
diff --git a/src/plugins/timelion/server/series_functions/yaxis.test.js b/src/plugins/vis_type_timelion/server/series_functions/yaxis.test.js
similarity index 100%
rename from src/plugins/timelion/server/series_functions/yaxis.test.js
rename to src/plugins/vis_type_timelion/server/series_functions/yaxis.test.js
diff --git a/src/plugins/timelion/server/timelion.json b/src/plugins/vis_type_timelion/server/timelion.json
similarity index 100%
rename from src/plugins/timelion/server/timelion.json
rename to src/plugins/vis_type_timelion/server/timelion.json
diff --git a/src/plugins/timelion/server/types.ts b/src/plugins/vis_type_timelion/server/types.ts
similarity index 100%
rename from src/plugins/timelion/server/types.ts
rename to src/plugins/vis_type_timelion/server/types.ts
diff --git a/src/plugins/visualizations/kibana.json b/src/plugins/visualizations/kibana.json
index cd22b1375ae1b..f3f9cbd8341ec 100644
--- a/src/plugins/visualizations/kibana.json
+++ b/src/plugins/visualizations/kibana.json
@@ -3,5 +3,5 @@
"version": "kibana",
"server": true,
"ui": true,
- "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection"]
+ "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection", "inspector"]
}
diff --git a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts
index bf2d174f594b2..8e51bd4ac5d4f 100644
--- a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts
+++ b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts
@@ -28,8 +28,9 @@ import {
getTimeFilter,
getCapabilities,
} from '../services';
+import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory';
-export const createVisEmbeddableFromObject = async (
+export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDeps) => async (
vis: Vis,
input: Partial & { id: string },
parent?: IContainer
@@ -58,6 +59,7 @@ export const createVisEmbeddableFromObject = async (
indexPatterns,
editUrl,
editable,
+ deps,
},
input,
parent
diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts
index e64d200251797..ffb028ff131b3 100644
--- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts
+++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts
@@ -42,6 +42,7 @@ import { buildPipeline } from '../legacy/build_pipeline';
import { Vis } from '../vis';
import { getExpressions, getUiActions } from '../services';
import { VIS_EVENT_TO_TRIGGER } from './events';
+import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory';
const getKeys = (o: T): Array => Object.keys(o) as Array;
@@ -50,6 +51,7 @@ export interface VisualizeEmbeddableConfiguration {
indexPatterns?: IIndexPattern[];
editUrl: string;
editable: boolean;
+ deps: VisualizeEmbeddableFactoryDeps;
}
export interface VisualizeInput extends EmbeddableInput {
@@ -84,10 +86,11 @@ export class VisualizeEmbeddable extends Embeddable {
- if (this.handler) {
- return this.handler.openInspector(this.getTitle() || '');
- }
+ if (!this.handler) return;
+
+ const adapters = this.handler.inspect();
+ if (!adapters) return;
+
+ this.deps.start().plugins.inspector.open(adapters, {
+ title: this.getTitle() || '',
+ });
};
/**
diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx
index 4b7d01ae3b246..6ab1c98645988 100644
--- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx
+++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx
@@ -25,7 +25,7 @@ import {
EmbeddableOutput,
ErrorEmbeddable,
IContainer,
-} from '../../../../plugins/embeddable/public';
+} from '../../../embeddable/public';
import { DisabledLabEmbeddable } from './disabled_lab_embeddable';
import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable';
import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
@@ -39,11 +39,17 @@ import {
import { showNewVisModal } from '../wizard';
import { convertToSerializedVis } from '../saved_visualizations/_saved_vis';
import { createVisEmbeddableFromObject } from './create_vis_embeddable_from_object';
+import { StartServicesGetter } from '../../../kibana_utils/public';
+import { VisualizationsStartDeps } from '../plugin';
interface VisualizationAttributes extends SavedObjectAttributes {
visState: string;
}
+export interface VisualizeEmbeddableFactoryDeps {
+ start: StartServicesGetter>;
+}
+
export class VisualizeEmbeddableFactory
implements
EmbeddableFactoryDefinition<
@@ -79,7 +85,8 @@ export class VisualizeEmbeddableFactory
return visType.stage !== 'experimental';
},
};
- constructor() {}
+
+ constructor(private readonly deps: VisualizeEmbeddableFactoryDeps) {}
public async isEditable() {
return getCapabilities().visualize.save as boolean;
@@ -101,7 +108,7 @@ export class VisualizeEmbeddableFactory
try {
const savedObject = await savedVisualizations.get(savedObjectId);
const vis = new Vis(savedObject.visState.type, await convertToSerializedVis(savedObject));
- return createVisEmbeddableFromObject(vis, input, parent);
+ return createVisEmbeddableFromObject(this.deps)(vis, input, parent);
} catch (e) {
console.error(e); // eslint-disable-line no-console
return new ErrorEmbeddable(e, input, parent);
diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts
index 2aa346423297a..d6eeffdb01459 100644
--- a/src/plugins/visualizations/public/mocks.ts
+++ b/src/plugins/visualizations/public/mocks.ts
@@ -26,6 +26,7 @@ import { expressionsPluginMock } from '../../../plugins/expressions/public/mocks
import { dataPluginMock } from '../../../plugins/data/public/mocks';
import { usageCollectionPluginMock } from '../../../plugins/usage_collection/public/mocks';
import { uiActionsPluginMock } from '../../../plugins/ui_actions/public/mocks';
+import { inspectorPluginMock } from '../../../plugins/inspector/public/mocks';
const createSetupContract = (): VisualizationsSetup => ({
createBaseVisualization: jest.fn(),
@@ -53,14 +54,16 @@ const createInstance = async () => {
const setup = plugin.setup(coreMock.createSetup(), {
data: dataPluginMock.createSetupContract(),
- expressions: expressionsPluginMock.createSetupContract(),
embeddable: embeddablePluginMock.createSetupContract(),
+ expressions: expressionsPluginMock.createSetupContract(),
+ inspector: inspectorPluginMock.createSetupContract(),
usageCollection: usageCollectionPluginMock.createSetupContract(),
});
const doStart = () =>
plugin.start(coreMock.createStart(), {
data: dataPluginMock.createStartContract(),
expressions: expressionsPluginMock.createStartContract(),
+ inspector: inspectorPluginMock.createStartContract(),
uiActions: uiActionsPluginMock.createStartContract(),
});
diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts
index 8fcb84b19a9be..b3e8c9b5b61b3 100644
--- a/src/plugins/visualizations/public/plugin.ts
+++ b/src/plugins/visualizations/public/plugin.ts
@@ -43,18 +43,23 @@ import {
VisualizeEmbeddableFactory,
createVisEmbeddableFromObject,
} from './embeddable';
-import { ExpressionsSetup, ExpressionsStart } from '../../../plugins/expressions/public';
-import { EmbeddableSetup } from '../../../plugins/embeddable/public';
+import { ExpressionsSetup, ExpressionsStart } from '../../expressions/public';
+import { EmbeddableSetup } from '../../embeddable/public';
import { visualization as visualizationFunction } from './expressions/visualization_function';
import { visualization as visualizationRenderer } from './expressions/visualization_renderer';
import { range as rangeExpressionFunction } from './expression_functions/range';
import { visDimension as visDimensionExpressionFunction } from './expression_functions/vis_dimension';
import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../plugins/data/public';
-import { UsageCollectionSetup } from '../../../plugins/usage_collection/public';
+import {
+ Setup as InspectorSetup,
+ Start as InspectorStart,
+} from '../../../plugins/inspector/public';
+import { UsageCollectionSetup } from '../../usage_collection/public';
+import { createStartServicesGetter, StartServicesGetter } from '../../kibana_utils/public';
import { createSavedVisLoader, SavedVisualizationsLoader } from './saved_visualizations';
import { SerializedVis, Vis } from './vis';
import { showNewVisModal } from './wizard';
-import { UiActionsStart } from '../../../plugins/ui_actions/public';
+import { UiActionsStart } from '../../ui_actions/public';
import {
convertFromSerializedVis,
convertToSerializedVis,
@@ -74,19 +79,21 @@ export interface VisualizationsStart extends TypesStart {
convertToSerializedVis: typeof convertToSerializedVis;
convertFromSerializedVis: typeof convertFromSerializedVis;
showNewVisModal: typeof showNewVisModal;
- __LEGACY: { createVisEmbeddableFromObject: typeof createVisEmbeddableFromObject };
+ __LEGACY: { createVisEmbeddableFromObject: ReturnType };
}
export interface VisualizationsSetupDeps {
- expressions: ExpressionsSetup;
+ data: DataPublicPluginSetup;
embeddable: EmbeddableSetup;
+ expressions: ExpressionsSetup;
+ inspector: InspectorSetup;
usageCollection: UsageCollectionSetup;
- data: DataPublicPluginSetup;
}
export interface VisualizationsStartDeps {
data: DataPublicPluginStart;
expressions: ExpressionsStart;
+ inspector: InspectorStart;
uiActions: UiActionsStart;
}
@@ -107,13 +114,16 @@ export class VisualizationsPlugin
VisualizationsStartDeps
> {
private readonly types: TypesService = new TypesService();
+ private getStartServicesOrDie?: StartServicesGetter;
constructor(initializerContext: PluginInitializerContext) {}
public setup(
- core: CoreSetup,
+ core: CoreSetup,
{ expressions, embeddable, usageCollection, data }: VisualizationsSetupDeps
): VisualizationsSetup {
+ const start = (this.getStartServicesOrDie = createStartServicesGetter(core.getStartServices));
+
setUISettings(core.uiSettings);
setUsageCollector(usageCollection);
@@ -122,7 +132,7 @@ export class VisualizationsPlugin
expressions.registerFunction(rangeExpressionFunction);
expressions.registerFunction(visDimensionExpressionFunction);
- const embeddableFactory = new VisualizeEmbeddableFactory();
+ const embeddableFactory = new VisualizeEmbeddableFactory({ start });
embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory);
return {
@@ -171,7 +181,11 @@ export class VisualizationsPlugin
convertToSerializedVis,
convertFromSerializedVis,
savedVisualizationsLoader,
- __LEGACY: { createVisEmbeddableFromObject },
+ __LEGACY: {
+ createVisEmbeddableFromObject: createVisEmbeddableFromObject({
+ start: this.getStartServicesOrDie!,
+ }),
+ },
};
}
diff --git a/tasks/config/peg.js b/tasks/config/peg.js
index 1d8667840faba..2de6ff4b5cff9 100644
--- a/tasks/config/peg.js
+++ b/tasks/config/peg.js
@@ -26,7 +26,7 @@ module.exports = {
},
},
timelion_chain: {
- src: 'src/legacy/core_plugins/vis_type_timelion/public/chain.peg',
- dest: 'src/legacy/core_plugins/vis_type_timelion/public/_generated_/chain.js',
+ src: 'src/plugins/vis_type_timelion/public/chain.peg',
+ dest: 'src/plugins/vis_type_timelion/public/_generated_/chain.js',
},
};
diff --git a/test/examples/embeddables/adding_children.ts b/test/examples/embeddables/adding_children.ts
index 5fe88b5dd33f0..9ec4b6cffd31a 100644
--- a/test/examples/embeddables/adding_children.ts
+++ b/test/examples/embeddables/adding_children.ts
@@ -25,7 +25,8 @@ export default function({ getService }: PluginFunctionalProviderContext) {
const testSubjects = getService('testSubjects');
const flyout = getService('flyout');
- describe('creating and adding children', () => {
+ // FLAKY: https://github.com/elastic/kibana/issues/58692
+ describe.skip('creating and adding children', () => {
before(async () => {
await testSubjects.click('embeddablePanelExamplae');
});
diff --git a/test/functional/apps/dashboard/dashboard_back_button.ts b/test/functional/apps/dashboard/dashboard_back_button.ts
new file mode 100644
index 0000000000000..8a488c1780fcc
--- /dev/null
+++ b/test/functional/apps/dashboard/dashboard_back_button.ts
@@ -0,0 +1,47 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import expect from '@kbn/expect';
+import { FtrProviderContext } from '../../ftr_provider_context';
+
+export default function({ getService, getPageObjects }: FtrProviderContext) {
+ const esArchiver = getService('esArchiver');
+ const kibanaServer = getService('kibanaServer');
+ const PageObjects = getPageObjects(['dashboard', 'header', 'common', 'visualize', 'timePicker']);
+ const browser = getService('browser');
+
+ describe('dashboard back button', () => {
+ before(async () => {
+ await esArchiver.loadIfNeeded('dashboard/current/kibana');
+ await kibanaServer.uiSettings.replace({
+ defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c',
+ });
+ await PageObjects.common.navigateToApp('dashboard');
+ await PageObjects.dashboard.preserveCrossAppState();
+ });
+
+ it('after navigation from listing page to dashboard back button works', async () => {
+ await PageObjects.dashboard.gotoDashboardLandingPage();
+ await PageObjects.dashboard.loadSavedDashboard('dashboard with everything');
+ await PageObjects.dashboard.waitForRenderComplete();
+ await browser.goBack();
+ expect(await PageObjects.dashboard.onDashboardLandingPage()).to.be(true);
+ });
+ });
+}
diff --git a/test/functional/apps/dashboard/index.js b/test/functional/apps/dashboard/index.js
index 5e96a55b19014..6666ccc57d584 100644
--- a/test/functional/apps/dashboard/index.js
+++ b/test/functional/apps/dashboard/index.js
@@ -55,6 +55,7 @@ export default function({ getService, loadTestFile }) {
loadTestFile(require.resolve('./dashboard_options'));
loadTestFile(require.resolve('./data_shared_attributes'));
loadTestFile(require.resolve('./embed_mode'));
+ loadTestFile(require.resolve('./dashboard_back_button'));
// Note: This one must be last because it unloads some data for one of its tests!
// No, this isn't ideal, but loading/unloading takes so much time and these are all bunched
diff --git a/test/functional/apps/dashboard/panel_controls.js b/test/functional/apps/dashboard/panel_controls.js
index 52c4a11360355..6e24b9f3570a3 100644
--- a/test/functional/apps/dashboard/panel_controls.js
+++ b/test/functional/apps/dashboard/panel_controls.js
@@ -113,6 +113,50 @@ export default function({ getService, getPageObjects }) {
});
});
+ describe('panel cloning', function() {
+ before(async () => {
+ await PageObjects.dashboard.clickNewDashboard();
+ await PageObjects.timePicker.setHistoricalDataRange();
+ await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME);
+ });
+
+ after(async function() {
+ await PageObjects.dashboard.gotoDashboardLandingPage();
+ });
+
+ it('clones a panel', async () => {
+ const initialPanelTitles = await PageObjects.dashboard.getPanelTitles();
+ await dashboardPanelActions.clonePanelByTitle(PIE_CHART_VIS_NAME);
+ await PageObjects.header.waitUntilLoadingHasFinished();
+ await PageObjects.dashboard.waitForRenderComplete();
+ const postPanelTitles = await PageObjects.dashboard.getPanelTitles();
+ expect(postPanelTitles.length).to.equal(initialPanelTitles.length + 1);
+ });
+
+ it('appends a clone title tag', async () => {
+ const panelTitles = await PageObjects.dashboard.getPanelTitles();
+ expect(panelTitles[1]).to.equal(PIE_CHART_VIS_NAME + ' (copy)');
+ });
+
+ it('retains original panel dimensions', async () => {
+ const panelDimensions = await PageObjects.dashboard.getPanelDimensions();
+ expect(panelDimensions[0]).to.eql(panelDimensions[1]);
+ });
+
+ it('gives a correct title to the clone of a clone', async () => {
+ const initialPanelTitles = await PageObjects.dashboard.getPanelTitles();
+ const clonedPanelName = initialPanelTitles[initialPanelTitles.length - 1];
+ await dashboardPanelActions.clonePanelByTitle(clonedPanelName);
+ await PageObjects.header.waitUntilLoadingHasFinished();
+ await PageObjects.dashboard.waitForRenderComplete();
+ const postPanelTitles = await PageObjects.dashboard.getPanelTitles();
+ expect(postPanelTitles.length).to.equal(initialPanelTitles.length + 1);
+ expect(postPanelTitles[postPanelTitles.length - 1]).to.equal(
+ PIE_CHART_VIS_NAME + ' (copy 1)'
+ );
+ });
+ });
+
describe('panel edit controls', function() {
before(async () => {
await PageObjects.dashboard.clickNewDashboard();
@@ -137,6 +181,7 @@ export default function({ getService, getPageObjects }) {
await dashboardPanelActions.expectExistsEditPanelAction();
await dashboardPanelActions.expectExistsReplacePanelAction();
+ await dashboardPanelActions.expectExistsDuplicatePanelAction();
await dashboardPanelActions.expectExistsRemovePanelAction();
});
@@ -151,6 +196,7 @@ export default function({ getService, getPageObjects }) {
await dashboardPanelActions.openContextMenu();
await dashboardPanelActions.expectExistsEditPanelAction();
await dashboardPanelActions.expectExistsReplacePanelAction();
+ await dashboardPanelActions.expectExistsDuplicatePanelAction();
await dashboardPanelActions.expectExistsRemovePanelAction();
// Get rid of the timestamp in the url.
@@ -166,6 +212,7 @@ export default function({ getService, getPageObjects }) {
await dashboardPanelActions.openContextMenu();
await dashboardPanelActions.expectMissingEditPanelAction();
await dashboardPanelActions.expectMissingReplacePanelAction();
+ await dashboardPanelActions.expectMissingDuplicatePanelAction();
await dashboardPanelActions.expectMissingRemovePanelAction();
});
@@ -174,6 +221,7 @@ export default function({ getService, getPageObjects }) {
await dashboardPanelActions.openContextMenu();
await dashboardPanelActions.expectExistsEditPanelAction();
await dashboardPanelActions.expectExistsReplacePanelAction();
+ await dashboardPanelActions.expectExistsDuplicatePanelAction();
await dashboardPanelActions.expectMissingRemovePanelAction();
await dashboardPanelActions.clickExpandPanelToggle();
});
diff --git a/test/functional/services/dashboard/panel_actions.js b/test/functional/services/dashboard/panel_actions.js
index baea2a52208c1..b155d747f3b93 100644
--- a/test/functional/services/dashboard/panel_actions.js
+++ b/test/functional/services/dashboard/panel_actions.js
@@ -20,6 +20,7 @@
const REMOVE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-deletePanel';
const EDIT_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-editPanel';
const REPLACE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-replacePanel';
+const CLONE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-clonePanel';
const TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-togglePanel';
const CUSTOMIZE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-ACTION_CUSTOMIZE_PANEL';
const OPEN_CONTEXT_MENU_ICON_DATA_TEST_SUBJ = 'embeddablePanelToggleMenuIcon';
@@ -97,6 +98,16 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) {
await testSubjects.click(REPLACE_PANEL_DATA_TEST_SUBJ);
}
+ async clonePanelByTitle(title) {
+ log.debug(`clonePanel(${title})`);
+ let panelOptions = null;
+ if (title) {
+ panelOptions = await this.getPanelHeading(title);
+ }
+ await this.openContextMenu(panelOptions);
+ await testSubjects.click(CLONE_PANEL_DATA_TEST_SUBJ);
+ }
+
async openInspectorByTitle(title) {
const header = await this.getPanelHeading(title);
await this.openInspector(header);
@@ -123,7 +134,12 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) {
}
async expectExistsReplacePanelAction() {
- log.debug('expectExistsEditPanelAction');
+ log.debug('expectExistsReplacePanelAction');
+ await testSubjects.existOrFail(REPLACE_PANEL_DATA_TEST_SUBJ);
+ }
+
+ async expectExistsDuplicatePanelAction() {
+ log.debug('expectExistsDuplicatePanelAction');
await testSubjects.existOrFail(REPLACE_PANEL_DATA_TEST_SUBJ);
}
@@ -133,7 +149,12 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) {
}
async expectMissingReplacePanelAction() {
- log.debug('expectMissingEditPanelAction');
+ log.debug('expectMissingReplacePanelAction');
+ await testSubjects.missingOrFail(REPLACE_PANEL_DATA_TEST_SUBJ);
+ }
+
+ async expectMissingDuplicatePanelAction() {
+ log.debug('expectMissingDuplicatePanelAction');
await testSubjects.missingOrFail(REPLACE_PANEL_DATA_TEST_SUBJ);
}
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/tsconfig.json
index d8096d9aab27a..544c27241f5cb 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/tsconfig.json
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/tsconfig.json
@@ -6,7 +6,8 @@
"types": [
"node",
"jest",
- "react"
+ "react",
+ "flot"
]
},
"include": [
@@ -16,4 +17,4 @@
"../../../../typings/**/*",
],
"exclude": []
-}
\ No newline at end of file
+}
diff --git a/test/scripts/jenkins_xpack.sh b/test/scripts/jenkins_xpack.sh
index 7070fb1063cb5..67d88b308ed91 100755
--- a/test/scripts/jenkins_xpack.sh
+++ b/test/scripts/jenkins_xpack.sh
@@ -17,7 +17,7 @@ if [[ -z "$CODE_COVERAGE" ]] ; then
echo " -> Running SIEM cyclic dependency test"
cd "$XPACK_DIR"
- checks-reporter-with-killswitch "X-Pack SIEM cyclic dependency test" node legacy/plugins/siem/scripts/check_circular_deps
+ checks-reporter-with-killswitch "X-Pack SIEM cyclic dependency test" node plugins/siem/scripts/check_circular_deps
echo ""
echo ""
diff --git a/test/tsconfig.json b/test/tsconfig.json
index 285d3db64a874..5a3716e620fed 100644
--- a/test/tsconfig.json
+++ b/test/tsconfig.json
@@ -3,7 +3,8 @@
"compilerOptions": {
"types": [
"node",
- "mocha"
+ "mocha",
+ "flot"
],
"lib": [
"esnext",
diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json
index 50f36ddd21c97..c8715ac3447bd 100644
--- a/x-pack/.i18nrc.json
+++ b/x-pack/.i18nrc.json
@@ -32,11 +32,11 @@
"xpack.remoteClusters": "plugins/remote_clusters",
"xpack.painlessLab": "plugins/painless_lab",
"xpack.reporting": ["plugins/reporting", "legacy/plugins/reporting"],
- "xpack.rollupJobs": "legacy/plugins/rollup",
+ "xpack.rollupJobs": ["legacy/plugins/rollup", "plugins/rollup"],
"xpack.searchProfiler": "plugins/searchprofiler",
"xpack.security": ["legacy/plugins/security", "plugins/security"],
"xpack.server": "legacy/server",
- "xpack.siem": "legacy/plugins/siem",
+ "xpack.siem": ["plugins/siem", "legacy/plugins/siem"],
"xpack.snapshotRestore": "plugins/snapshot_restore",
"xpack.spaces": ["legacy/plugins/spaces", "plugins/spaces"],
"xpack.taskManager": "legacy/plugins/task_manager",
diff --git a/x-pack/examples/README.md b/x-pack/examples/README.md
new file mode 100644
index 0000000000000..babf744f9777d
--- /dev/null
+++ b/x-pack/examples/README.md
@@ -0,0 +1,7 @@
+## Example plugins
+
+This folder contains X-Pack example plugins. To run the plugins in this folder, use the `--run-examples` flag, via
+
+```
+yarn start --run-examples
+```
diff --git a/x-pack/examples/ui_actions_enhanced_examples/README.md b/x-pack/examples/ui_actions_enhanced_examples/README.md
new file mode 100644
index 0000000000000..c9f53137d8687
--- /dev/null
+++ b/x-pack/examples/ui_actions_enhanced_examples/README.md
@@ -0,0 +1,3 @@
+## Ui actions enhanced examples
+
+To run this example, use the command `yarn start --run-examples`.
diff --git a/x-pack/examples/ui_actions_enhanced_examples/kibana.json b/x-pack/examples/ui_actions_enhanced_examples/kibana.json
new file mode 100644
index 0000000000000..f75852edced5c
--- /dev/null
+++ b/x-pack/examples/ui_actions_enhanced_examples/kibana.json
@@ -0,0 +1,10 @@
+{
+ "id": "uiActionsEnhancedExamples",
+ "version": "0.0.1",
+ "kibanaVersion": "kibana",
+ "configPath": ["ui_actions_enhanced_examples"],
+ "server": false,
+ "ui": true,
+ "requiredPlugins": ["uiActions", "data"],
+ "optionalPlugins": []
+}
diff --git a/x-pack/examples/ui_actions_enhanced_examples/package.json b/x-pack/examples/ui_actions_enhanced_examples/package.json
new file mode 100644
index 0000000000000..a9f004b075cec
--- /dev/null
+++ b/x-pack/examples/ui_actions_enhanced_examples/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "ui_actions_enhanced_examples",
+ "version": "1.0.0",
+ "main": "target/examples/ui_actions_enhanced_examples",
+ "kibana": {
+ "version": "kibana",
+ "templateVersion": "1.0.0"
+ },
+ "license": "Apache-2.0",
+ "scripts": {
+ "kbn": "node ../../scripts/kbn.js",
+ "build": "rm -rf './target' && tsc"
+ },
+ "devDependencies": {
+ "typescript": "3.7.2"
+ }
+}
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/index.ts b/x-pack/examples/ui_actions_enhanced_examples/public/index.ts
new file mode 100644
index 0000000000000..7f3f36089d576
--- /dev/null
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/index.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { UiActionsEnhancedExamplesPlugin } from './plugin';
+
+export const plugin = () => new UiActionsEnhancedExamplesPlugin();
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts b/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts
new file mode 100644
index 0000000000000..a4c43753c8247
--- /dev/null
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts
@@ -0,0 +1,31 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { Plugin, CoreSetup, CoreStart } from '../../../../src/core/public';
+import { UiActionsSetup, UiActionsStart } from '../../../../src/plugins/ui_actions/public';
+import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public';
+
+export interface SetupDependencies {
+ data: DataPublicPluginSetup;
+ uiActions: UiActionsSetup;
+}
+
+export interface StartDependencies {
+ data: DataPublicPluginStart;
+ uiActions: UiActionsStart;
+}
+
+export class UiActionsEnhancedExamplesPlugin
+ implements Plugin {
+ public setup(core: CoreSetup, plugins: SetupDependencies) {
+ // eslint-disable-next-line
+ console.log('ui_actions_enhanced_examples');
+ }
+
+ public start(core: CoreStart, plugins: StartDependencies) {}
+
+ public stop() {}
+}
diff --git a/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json b/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json
new file mode 100644
index 0000000000000..d508076b33199
--- /dev/null
+++ b/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./target",
+ "skipLibCheck": true
+ },
+ "include": [
+ "index.ts",
+ "public/**/*.ts",
+ "public/**/*.tsx",
+ "server/**/*.ts",
+ "../../typings/**/*",
+ ],
+ "exclude": []
+}
diff --git a/x-pack/index.js b/x-pack/index.js
index 61fd4f1752316..7fbd992120ea6 100644
--- a/x-pack/index.js
+++ b/x-pack/index.js
@@ -9,7 +9,6 @@ import { graph } from './legacy/plugins/graph';
import { monitoring } from './legacy/plugins/monitoring';
import { reporting } from './legacy/plugins/reporting';
import { security } from './legacy/plugins/security';
-import { tilemap } from './legacy/plugins/tilemap';
import { dashboardMode } from './legacy/plugins/dashboard_mode';
import { logstash } from './legacy/plugins/logstash';
import { beats } from './legacy/plugins/beats_management';
@@ -40,7 +39,6 @@ module.exports = function(kibana) {
reporting(kibana),
spaces(kibana),
security(kibana),
- tilemap(kibana),
dashboardMode(kibana),
logstash(kibana),
beats(kibana),
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/index.tsx
index a1462c7637358..cc5c62e25b491 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/index.tsx
@@ -57,7 +57,8 @@ export class MachineLearningFlyout extends Component {
};
public addErrorToast = () => {
- const core = this.context;
+ const { core } = this.context;
+
const { urlParams } = this.props;
const { serviceName } = urlParams;
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts
index 416eb879d5974..d844ac8b5988d 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts
@@ -166,6 +166,212 @@ describe('waterfall_helpers', () => {
expect(waterfall.errorsCount).toEqual(0);
expect(waterfall).toMatchSnapshot();
});
+ it('should reparent spans', () => {
+ const traceItems = [
+ {
+ processor: { event: 'transaction' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-node' },
+ transaction: {
+ duration: { us: 49660 },
+ name: 'GET /api',
+ id: 'myTransactionId1'
+ },
+ timestamp: { us: 1549324795784006 }
+ } as Transaction,
+ {
+ parent: { id: 'mySpanIdD' },
+ processor: { event: 'span' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-ruby' },
+ transaction: { id: 'myTransactionId1' },
+ timestamp: { us: 1549324795825633 },
+ span: {
+ duration: { us: 481 },
+ name: 'SELECT FROM products',
+ id: 'mySpanIdB'
+ },
+ child_ids: ['mySpanIdA', 'mySpanIdC']
+ } as Span,
+ {
+ parent: { id: 'mySpanIdD' },
+ processor: { event: 'span' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-ruby' },
+ transaction: { id: 'myTransactionId1' },
+ span: {
+ duration: { us: 6161 },
+ name: 'Api::ProductsController#index',
+ id: 'mySpanIdA'
+ },
+ timestamp: { us: 1549324795824504 }
+ } as Span,
+ {
+ parent: { id: 'mySpanIdD' },
+ processor: { event: 'span' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-ruby' },
+ transaction: { id: 'myTransactionId1' },
+ span: {
+ duration: { us: 532 },
+ name: 'SELECT FROM product',
+ id: 'mySpanIdC'
+ },
+ timestamp: { us: 1549324795827905 }
+ } as Span,
+ {
+ parent: { id: 'myTransactionId1' },
+ processor: { event: 'span' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-node' },
+ transaction: { id: 'myTransactionId1' },
+ span: {
+ duration: { us: 47557 },
+ name: 'GET opbeans-ruby:3000/api/products',
+ id: 'mySpanIdD'
+ },
+ timestamp: { us: 1549324795785760 }
+ } as Span
+ ];
+ const entryTransactionId = 'myTransactionId1';
+ const waterfall = getWaterfall(
+ {
+ trace: { items: traceItems, errorDocs: [], exceedsMax: false },
+ errorsPerTransaction: {}
+ },
+ entryTransactionId
+ );
+ const getIdAndParentId = (item: IWaterfallItem) => ({
+ id: item.id,
+ parentId: item.parent?.id
+ });
+ expect(waterfall.items.length).toBe(5);
+ expect(getIdAndParentId(waterfall.items[0])).toEqual({
+ id: 'myTransactionId1',
+ parentId: undefined
+ });
+ expect(getIdAndParentId(waterfall.items[1])).toEqual({
+ id: 'mySpanIdD',
+ parentId: 'myTransactionId1'
+ });
+ expect(getIdAndParentId(waterfall.items[2])).toEqual({
+ id: 'mySpanIdB',
+ parentId: 'mySpanIdD'
+ });
+ expect(getIdAndParentId(waterfall.items[3])).toEqual({
+ id: 'mySpanIdA',
+ parentId: 'mySpanIdB'
+ });
+ expect(getIdAndParentId(waterfall.items[4])).toEqual({
+ id: 'mySpanIdC',
+ parentId: 'mySpanIdB'
+ });
+ expect(waterfall.errorItems.length).toBe(0);
+ expect(waterfall.errorsCount).toEqual(0);
+ });
+ it("shouldn't reparent spans when child id isn't found", () => {
+ const traceItems = [
+ {
+ processor: { event: 'transaction' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-node' },
+ transaction: {
+ duration: { us: 49660 },
+ name: 'GET /api',
+ id: 'myTransactionId1'
+ },
+ timestamp: { us: 1549324795784006 }
+ } as Transaction,
+ {
+ parent: { id: 'mySpanIdD' },
+ processor: { event: 'span' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-ruby' },
+ transaction: { id: 'myTransactionId1' },
+ timestamp: { us: 1549324795825633 },
+ span: {
+ duration: { us: 481 },
+ name: 'SELECT FROM products',
+ id: 'mySpanIdB'
+ },
+ child_ids: ['incorrectId', 'mySpanIdC']
+ } as Span,
+ {
+ parent: { id: 'mySpanIdD' },
+ processor: { event: 'span' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-ruby' },
+ transaction: { id: 'myTransactionId1' },
+ span: {
+ duration: { us: 6161 },
+ name: 'Api::ProductsController#index',
+ id: 'mySpanIdA'
+ },
+ timestamp: { us: 1549324795824504 }
+ } as Span,
+ {
+ parent: { id: 'mySpanIdD' },
+ processor: { event: 'span' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-ruby' },
+ transaction: { id: 'myTransactionId1' },
+ span: {
+ duration: { us: 532 },
+ name: 'SELECT FROM product',
+ id: 'mySpanIdC'
+ },
+ timestamp: { us: 1549324795827905 }
+ } as Span,
+ {
+ parent: { id: 'myTransactionId1' },
+ processor: { event: 'span' },
+ trace: { id: 'myTraceId' },
+ service: { name: 'opbeans-node' },
+ transaction: { id: 'myTransactionId1' },
+ span: {
+ duration: { us: 47557 },
+ name: 'GET opbeans-ruby:3000/api/products',
+ id: 'mySpanIdD'
+ },
+ timestamp: { us: 1549324795785760 }
+ } as Span
+ ];
+ const entryTransactionId = 'myTransactionId1';
+ const waterfall = getWaterfall(
+ {
+ trace: { items: traceItems, errorDocs: [], exceedsMax: false },
+ errorsPerTransaction: {}
+ },
+ entryTransactionId
+ );
+ const getIdAndParentId = (item: IWaterfallItem) => ({
+ id: item.id,
+ parentId: item.parent?.id
+ });
+ expect(waterfall.items.length).toBe(5);
+ expect(getIdAndParentId(waterfall.items[0])).toEqual({
+ id: 'myTransactionId1',
+ parentId: undefined
+ });
+ expect(getIdAndParentId(waterfall.items[1])).toEqual({
+ id: 'mySpanIdD',
+ parentId: 'myTransactionId1'
+ });
+ expect(getIdAndParentId(waterfall.items[2])).toEqual({
+ id: 'mySpanIdA',
+ parentId: 'mySpanIdD'
+ });
+ expect(getIdAndParentId(waterfall.items[3])).toEqual({
+ id: 'mySpanIdB',
+ parentId: 'mySpanIdD'
+ });
+ expect(getIdAndParentId(waterfall.items[4])).toEqual({
+ id: 'mySpanIdC',
+ parentId: 'mySpanIdB'
+ });
+ expect(waterfall.errorItems.length).toBe(0);
+ expect(waterfall.errorsCount).toEqual(0);
+ });
});
describe('getWaterfallItems', () => {
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts
index 58d9134c4d787..8a873b2ddf1c9 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts
@@ -236,6 +236,29 @@ const getWaterfallItems = (items: TraceAPIResponse['trace']['items']) =>
}
});
+/**
+ * Changes the parent_id of items based on the child_ids property.
+ * Solves the problem of Inferred spans that are created as child of trace spans
+ * when it actually should be its parent.
+ * @param waterfallItems
+ */
+const reparentSpans = (waterfallItems: IWaterfallItem[]) => {
+ return waterfallItems.map(waterfallItem => {
+ if (waterfallItem.docType === 'span') {
+ const { child_ids: childIds } = waterfallItem.doc;
+ if (childIds) {
+ childIds.forEach(childId => {
+ const item = waterfallItems.find(_item => _item.id === childId);
+ if (item) {
+ item.parentId = waterfallItem.id;
+ }
+ });
+ }
+ }
+ return waterfallItem;
+ });
+};
+
const getChildrenGroupedByParentId = (waterfallItems: IWaterfallItem[]) =>
groupBy(waterfallItems, item => (item.parentId ? item.parentId : ROOT_ID));
@@ -306,7 +329,9 @@ export function getWaterfall(
const waterfallItems: IWaterfallItem[] = getWaterfallItems(trace.items);
- const childrenByParentId = getChildrenGroupedByParentId(waterfallItems);
+ const childrenByParentId = getChildrenGroupedByParentId(
+ reparentSpans(waterfallItems)
+ );
const entryWaterfallTransaction = getEntryWaterfallTransaction(
entryTransactionId,
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/WaterfallContainer.stories.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/WaterfallContainer.stories.tsx
index 938962cc9dd18..f681f4dfc675a 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/WaterfallContainer.stories.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/WaterfallContainer.stories.tsx
@@ -14,7 +14,8 @@ import {
urlParams,
simpleTrace,
traceWithErrors,
- traceChildStartBeforeParent
+ traceChildStartBeforeParent,
+ inferredSpans
} from './waterfallContainer.stories.data';
import { getWaterfall } from './Waterfall/waterfall_helpers/waterfall_helpers';
@@ -74,3 +75,22 @@ storiesOf('app/TransactionDetails/Waterfall', module).add(
},
{ info: { source: false } }
);
+
+storiesOf('app/TransactionDetails/Waterfall', module).add(
+ 'inferred spans',
+ () => {
+ const waterfall = getWaterfall(
+ inferredSpans as TraceAPIResponse,
+ 'f2387d37260d00bd'
+ );
+ return (
+
+ );
+ },
+ { info: { source: false } }
+);
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/waterfallContainer.stories.data.ts b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/waterfallContainer.stories.data.ts
index 835183e73b298..306c8e4f3fedb 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/waterfallContainer.stories.data.ts
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/waterfallContainer.stories.data.ts
@@ -1645,3 +1645,667 @@ export const traceChildStartBeforeParent = {
},
errorsPerTransaction: {}
};
+
+export const inferredSpans = {
+ trace: {
+ items: [
+ {
+ container: {
+ id: 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ agent: {
+ name: 'java',
+ ephemeral_id: '1cb5c830-c677-4b13-b340-ab1502f527c3',
+ version: '1.15.1-SNAPSHOT'
+ },
+ process: {
+ pid: 6,
+ title: '/opt/java/openjdk/bin/java',
+ ppid: 1
+ },
+ source: {
+ ip: '172.18.0.8'
+ },
+ processor: {
+ name: 'transaction',
+ event: 'transaction'
+ },
+ url: {
+ path: '/api/products/2',
+ scheme: 'http',
+ port: 3000,
+ domain: '172.18.0.7',
+ full: 'http://172.18.0.7:3000/api/products/2'
+ },
+ observer: {
+ hostname: '7189f754b5a3',
+ id: 'f32d8d9f-a9f9-4355-8370-548dfd8024dc',
+ ephemeral_id: 'bff20764-0195-4f78-aa84-d799fc47b954',
+ type: 'apm-server',
+ version: '8.0.0',
+ version_major: 8
+ },
+ trace: {
+ id: '3b0dc77f3754e5bcb9da0e4c15e0db97'
+ },
+ '@timestamp': '2020-04-09T11:36:00.786Z',
+ ecs: {
+ version: '1.5.0'
+ },
+ service: {
+ node: {
+ name:
+ 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ environment: 'production',
+ name: 'opbeans-java',
+ runtime: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ language: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ version: 'None'
+ },
+ host: {
+ hostname: 'fc2ae281f56f',
+ os: {
+ platform: 'Linux'
+ },
+ ip: '172.18.0.7',
+ name: 'fc2ae281f56f',
+ architecture: 'amd64'
+ },
+ client: {
+ ip: '172.18.0.8'
+ },
+ http: {
+ request: {
+ headers: {
+ Accept: ['*/*'],
+ 'User-Agent': ['Python/3.7 aiohttp/3.3.2'],
+ Host: ['172.18.0.7:3000'],
+ 'Accept-Encoding': ['gzip, deflate']
+ },
+ method: 'get',
+ socket: {
+ encrypted: false,
+ remote_address: '172.18.0.8'
+ }
+ },
+ response: {
+ headers: {
+ 'Transfer-Encoding': ['chunked'],
+ Date: ['Thu, 09 Apr 2020 11:36:01 GMT'],
+ 'Content-Type': ['application/json;charset=UTF-8']
+ },
+ status_code: 200,
+ finished: true,
+ headers_sent: true
+ },
+ version: '1.1'
+ },
+ user_agent: {
+ original: 'Python/3.7 aiohttp/3.3.2',
+ name: 'Other',
+ device: {
+ name: 'Other'
+ }
+ },
+ transaction: {
+ duration: {
+ us: 237537
+ },
+ result: 'HTTP 2xx',
+ name: 'APIRestController#product',
+ span_count: {
+ dropped: 0,
+ started: 3
+ },
+ id: 'f2387d37260d00bd',
+ type: 'request',
+ sampled: true
+ },
+ timestamp: {
+ us: 1586432160786001
+ }
+ },
+ {
+ container: {
+ id: 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ parent: {
+ id: 'f2387d37260d00bd'
+ },
+ agent: {
+ name: 'java',
+ ephemeral_id: '1cb5c830-c677-4b13-b340-ab1502f527c3',
+ version: '1.15.1-SNAPSHOT'
+ },
+ process: {
+ pid: 6,
+ title: '/opt/java/openjdk/bin/java',
+ ppid: 1
+ },
+ processor: {
+ name: 'transaction',
+ event: 'span'
+ },
+ observer: {
+ hostname: '7189f754b5a3',
+ id: 'f32d8d9f-a9f9-4355-8370-548dfd8024dc',
+ ephemeral_id: 'bff20764-0195-4f78-aa84-d799fc47b954',
+ type: 'apm-server',
+ version: '8.0.0',
+ version_major: 8
+ },
+ trace: {
+ id: '3b0dc77f3754e5bcb9da0e4c15e0db97'
+ },
+ '@timestamp': '2020-04-09T11:36:00.810Z',
+ ecs: {
+ version: '1.5.0'
+ },
+ service: {
+ node: {
+ name:
+ 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ environment: 'production',
+ name: 'opbeans-java',
+ runtime: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ language: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ version: 'None'
+ },
+ host: {
+ hostname: 'fc2ae281f56f',
+ os: {
+ platform: 'Linux'
+ },
+ ip: '172.18.0.7',
+ name: 'fc2ae281f56f',
+ architecture: 'amd64'
+ },
+ transaction: {
+ id: 'f2387d37260d00bd'
+ },
+ span: {
+ duration: {
+ us: 204574
+ },
+ subtype: 'inferred',
+ name: 'ServletInvocableHandlerMethod#invokeAndHandle',
+ id: 'a5df600bd7bd5e38',
+ type: 'app'
+ },
+ timestamp: {
+ us: 1586432160810441
+ }
+ },
+ {
+ container: {
+ id: 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ parent: {
+ id: 'a5df600bd7bd5e38'
+ },
+ agent: {
+ name: 'java',
+ ephemeral_id: '1cb5c830-c677-4b13-b340-ab1502f527c3',
+ version: '1.15.1-SNAPSHOT'
+ },
+ process: {
+ pid: 6,
+ title: '/opt/java/openjdk/bin/java',
+ ppid: 1
+ },
+ processor: {
+ name: 'transaction',
+ event: 'span'
+ },
+ observer: {
+ hostname: '7189f754b5a3',
+ id: 'f32d8d9f-a9f9-4355-8370-548dfd8024dc',
+ type: 'apm-server',
+ ephemeral_id: 'bff20764-0195-4f78-aa84-d799fc47b954',
+ version: '8.0.0',
+ version_major: 8
+ },
+ trace: {
+ id: '3b0dc77f3754e5bcb9da0e4c15e0db97'
+ },
+ '@timestamp': '2020-04-09T11:36:00.810Z',
+ ecs: {
+ version: '1.5.0'
+ },
+ service: {
+ node: {
+ name:
+ 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ environment: 'production',
+ name: 'opbeans-java',
+ runtime: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ language: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ version: 'None'
+ },
+ host: {
+ hostname: 'fc2ae281f56f',
+ os: {
+ platform: 'Linux'
+ },
+ ip: '172.18.0.7',
+ name: 'fc2ae281f56f',
+ architecture: 'amd64'
+ },
+ transaction: {
+ id: 'f2387d37260d00bd'
+ },
+ timestamp: {
+ us: 1586432160810441
+ },
+ span: {
+ duration: {
+ us: 102993
+ },
+ stacktrace: [
+ {
+ library_frame: true,
+ exclude_from_grouping: false,
+ filename: 'InvocableHandlerMethod.java',
+ line: {
+ number: -1
+ },
+ function: 'doInvoke'
+ },
+ {
+ exclude_from_grouping: false,
+ library_frame: true,
+ filename: 'InvocableHandlerMethod.java',
+ line: {
+ number: -1
+ },
+ function: 'invokeForRequest'
+ }
+ ],
+ subtype: 'inferred',
+ name: 'APIRestController#product',
+ id: '808dc34fc41ce522',
+ type: 'app'
+ }
+ },
+ {
+ container: {
+ id: 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ parent: {
+ id: 'f2387d37260d00bd'
+ },
+ agent: {
+ name: 'java',
+ ephemeral_id: '1cb5c830-c677-4b13-b340-ab1502f527c3',
+ version: '1.15.1-SNAPSHOT'
+ },
+ process: {
+ pid: 6,
+ title: '/opt/java/openjdk/bin/java',
+ ppid: 1
+ },
+ processor: {
+ name: 'transaction',
+ event: 'span'
+ },
+ labels: {
+ productId: '2'
+ },
+ observer: {
+ hostname: '7189f754b5a3',
+ id: 'f32d8d9f-a9f9-4355-8370-548dfd8024dc',
+ ephemeral_id: 'bff20764-0195-4f78-aa84-d799fc47b954',
+ type: 'apm-server',
+ version: '8.0.0',
+ version_major: 8
+ },
+ trace: {
+ id: '3b0dc77f3754e5bcb9da0e4c15e0db97'
+ },
+ '@timestamp': '2020-04-09T11:36:00.832Z',
+ ecs: {
+ version: '1.5.0'
+ },
+ service: {
+ node: {
+ name:
+ 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ environment: 'production',
+ name: 'opbeans-java',
+ runtime: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ language: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ version: 'None'
+ },
+ host: {
+ hostname: 'fc2ae281f56f',
+ os: {
+ platform: 'Linux'
+ },
+ ip: '172.18.0.7',
+ name: 'fc2ae281f56f',
+ architecture: 'amd64'
+ },
+ transaction: {
+ id: 'f2387d37260d00bd'
+ },
+ timestamp: {
+ us: 1586432160832300
+ },
+ span: {
+ duration: {
+ us: 99295
+ },
+ name: 'OpenTracing product span',
+ id: '41226ae63af4f235',
+ type: 'unknown'
+ },
+ child_ids: ['8d80de06aa11a6fc']
+ },
+ {
+ container: {
+ id: 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ parent: {
+ id: '808dc34fc41ce522'
+ },
+ process: {
+ pid: 6,
+ title: '/opt/java/openjdk/bin/java',
+ ppid: 1
+ },
+ agent: {
+ name: 'java',
+ ephemeral_id: '1cb5c830-c677-4b13-b340-ab1502f527c3',
+ version: '1.15.1-SNAPSHOT'
+ },
+ processor: {
+ name: 'transaction',
+ event: 'span'
+ },
+ observer: {
+ hostname: '7189f754b5a3',
+ id: 'f32d8d9f-a9f9-4355-8370-548dfd8024dc',
+ ephemeral_id: 'bff20764-0195-4f78-aa84-d799fc47b954',
+ type: 'apm-server',
+ version: '8.0.0',
+ version_major: 8
+ },
+ trace: {
+ id: '3b0dc77f3754e5bcb9da0e4c15e0db97'
+ },
+ '@timestamp': '2020-04-09T11:36:00.859Z',
+ ecs: {
+ version: '1.5.0'
+ },
+ service: {
+ node: {
+ name:
+ 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ environment: 'production',
+ name: 'opbeans-java',
+ runtime: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ language: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ version: 'None'
+ },
+ host: {
+ hostname: 'fc2ae281f56f',
+ os: {
+ platform: 'Linux'
+ },
+ ip: '172.18.0.7',
+ name: 'fc2ae281f56f',
+ architecture: 'amd64'
+ },
+ transaction: {
+ id: 'f2387d37260d00bd'
+ },
+ timestamp: {
+ us: 1586432160859600
+ },
+ span: {
+ duration: {
+ us: 53835
+ },
+ subtype: 'inferred',
+ name: 'Loader#executeQueryStatement',
+ id: '8d80de06aa11a6fc',
+ type: 'app'
+ }
+ },
+ {
+ container: {
+ id: 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ parent: {
+ id: '41226ae63af4f235'
+ },
+ agent: {
+ name: 'java',
+ ephemeral_id: '1cb5c830-c677-4b13-b340-ab1502f527c3',
+ version: '1.15.1-SNAPSHOT'
+ },
+ process: {
+ pid: 6,
+ title: '/opt/java/openjdk/bin/java',
+ ppid: 1
+ },
+ destination: {
+ address: 'postgres',
+ port: 5432
+ },
+ processor: {
+ name: 'transaction',
+ event: 'span'
+ },
+ observer: {
+ hostname: '7189f754b5a3',
+ id: 'f32d8d9f-a9f9-4355-8370-548dfd8024dc',
+ ephemeral_id: 'bff20764-0195-4f78-aa84-d799fc47b954',
+ type: 'apm-server',
+ version: '8.0.0',
+ version_major: 8
+ },
+ trace: {
+ id: '3b0dc77f3754e5bcb9da0e4c15e0db97'
+ },
+ '@timestamp': '2020-04-09T11:36:00.903Z',
+ ecs: {
+ version: '1.5.0'
+ },
+ service: {
+ node: {
+ name:
+ 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ environment: 'production',
+ name: 'opbeans-java',
+ runtime: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ language: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ version: 'None'
+ },
+ host: {
+ hostname: 'fc2ae281f56f',
+ os: {
+ platform: 'Linux'
+ },
+ ip: '172.18.0.7',
+ name: 'fc2ae281f56f',
+ architecture: 'amd64'
+ },
+ transaction: {
+ id: 'f2387d37260d00bd'
+ },
+ timestamp: {
+ us: 1586432160903236
+ },
+ span: {
+ duration: {
+ us: 10211
+ },
+ subtype: 'postgresql',
+ destination: {
+ service: {
+ resource: 'postgresql',
+ name: 'postgresql',
+ type: 'db'
+ }
+ },
+ name: 'SELECT FROM products',
+ action: 'query',
+ id: '3708d5623658182f',
+ type: 'db',
+ db: {
+ statement:
+ 'select product0_.id as col_0_0_, product0_.sku as col_1_0_, product0_.name as col_2_0_, product0_.description as col_3_0_, product0_.cost as col_4_0_, product0_.selling_price as col_5_0_, product0_.stock as col_6_0_, producttyp1_.id as col_7_0_, producttyp1_.name as col_8_0_, (select sum(orderline2_.amount) from order_lines orderline2_ where orderline2_.product_id=product0_.id) as col_9_0_ from products product0_ left outer join product_types producttyp1_ on product0_.type_id=producttyp1_.id where product0_.id=?',
+ type: 'sql',
+ user: {
+ name: 'postgres'
+ }
+ }
+ }
+ },
+ {
+ container: {
+ id: 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ parent: {
+ id: '41226ae63af4f235'
+ },
+ process: {
+ pid: 6,
+ title: '/opt/java/openjdk/bin/java',
+ ppid: 1
+ },
+ agent: {
+ name: 'java',
+ ephemeral_id: '1cb5c830-c677-4b13-b340-ab1502f527c3',
+ version: '1.15.1-SNAPSHOT'
+ },
+ destination: {
+ address: 'postgres',
+ port: 5432
+ },
+ processor: {
+ name: 'transaction',
+ event: 'span'
+ },
+ observer: {
+ hostname: '7189f754b5a3',
+ id: 'f32d8d9f-a9f9-4355-8370-548dfd8024dc',
+ ephemeral_id: 'bff20764-0195-4f78-aa84-d799fc47b954',
+ type: 'apm-server',
+ version: '8.0.0',
+ version_major: 8
+ },
+ trace: {
+ id: '3b0dc77f3754e5bcb9da0e4c15e0db97'
+ },
+ '@timestamp': '2020-04-09T11:36:00.859Z',
+ ecs: {
+ version: '1.5.0'
+ },
+ service: {
+ node: {
+ name:
+ 'fc2ae281f56fb84728bc9b5e6c17f3d13bbb7f4efd461158558e5c38e655abad'
+ },
+ environment: 'production',
+ name: 'opbeans-java',
+ runtime: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ language: {
+ name: 'Java',
+ version: '11.0.6'
+ },
+ version: 'None'
+ },
+ host: {
+ hostname: 'fc2ae281f56f',
+ os: {
+ platform: 'Linux'
+ },
+ ip: '172.18.0.7',
+ name: 'fc2ae281f56f',
+ architecture: 'amd64'
+ },
+ transaction: {
+ id: 'f2387d37260d00bd'
+ },
+ timestamp: {
+ us: 1586432160859508
+ },
+ span: {
+ duration: {
+ us: 4503
+ },
+ subtype: 'postgresql',
+ destination: {
+ service: {
+ resource: 'postgresql',
+ name: 'postgresql',
+ type: 'db'
+ }
+ },
+ name: 'empty query',
+ action: 'query',
+ id: '9871cfd612368932',
+ type: 'db',
+ db: {
+ rows_affected: 0,
+ statement: '(empty query)',
+ type: 'sql',
+ user: {
+ name: 'postgres'
+ }
+ }
+ }
+ }
+ ],
+ exceedsMax: false,
+ errorDocs: []
+ },
+ errorsPerTransaction: {}
+};
diff --git a/x-pack/legacy/plugins/apm/public/services/rest/ml.ts b/x-pack/legacy/plugins/apm/public/services/rest/ml.ts
index 1c618098b36e3..0cd1bdf907531 100644
--- a/x-pack/legacy/plugins/apm/public/services/rest/ml.ts
+++ b/x-pack/legacy/plugins/apm/public/services/rest/ml.ts
@@ -12,7 +12,8 @@ import {
} from '../../../../../../plugins/apm/common/elasticsearch_fieldnames';
import {
getMlJobId,
- getMlPrefix
+ getMlPrefix,
+ encodeForMlApi
} from '../../../../../../plugins/apm/common/ml_job_constants';
import { callApi } from './callApi';
import { ESFilter } from '../../../../../../plugins/apm/typings/elasticsearch';
@@ -53,13 +54,16 @@ export async function startMLJob({
http: HttpSetup;
}) {
const transactionIndices = await getTransactionIndices(http);
- const groups = ['apm', serviceName.toLowerCase()];
+ const groups = [
+ 'apm',
+ encodeForMlApi(serviceName),
+ encodeForMlApi(transactionType)
+ ];
const filter: ESFilter[] = [
{ term: { [SERVICE_NAME]: serviceName } },
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
{ term: { [TRANSACTION_TYPE]: transactionType } }
];
- groups.push(transactionType.toLowerCase());
return callApi(http, {
method: 'POST',
pathname: `/api/ml/modules/setup/apm_transaction`,
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.scss b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.scss
index 04f2f393d1e80..ae26a1bee99a6 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.scss
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.scss
@@ -26,8 +26,4 @@
.euiTable {
background: none;
}
-
- .lnsExpressionRenderer {
- @include euiScrollBar;
- }
-}
\ No newline at end of file
+}
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js
index b50c36aa8df9f..24bc7e17356e2 100644
--- a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js
+++ b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js
@@ -145,9 +145,35 @@ export const updateFollowerIndex = (id, followerIndex) => {
if (isUsingAdvancedSettings) {
uiMetrics.push(UIM_FOLLOWER_INDEX_USE_ADVANCED_OPTIONS);
}
+
+ const {
+ maxReadRequestOperationCount,
+ maxOutstandingReadRequests,
+ maxReadRequestSize,
+ maxWriteRequestOperationCount,
+ maxWriteRequestSize,
+ maxOutstandingWriteRequests,
+ maxWriteBufferCount,
+ maxWriteBufferSize,
+ maxRetryDelay,
+ readPollTimeout,
+ } = followerIndex;
+
const request = httpClient.put(`${API_BASE_PATH}/follower_indices/${encodeURIComponent(id)}`, {
- body: JSON.stringify(followerIndex),
+ body: JSON.stringify({
+ maxReadRequestOperationCount,
+ maxOutstandingReadRequests,
+ maxReadRequestSize,
+ maxWriteRequestOperationCount,
+ maxWriteRequestSize,
+ maxOutstandingWriteRequests,
+ maxWriteBufferCount,
+ maxWriteBufferSize,
+ maxRetryDelay,
+ readPollTimeout,
+ }),
});
+
return trackUserRequest(request, uiMetrics);
};
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts
index 3896e1c02c915..1d7dacf4a8688 100644
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts
+++ b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts
@@ -164,6 +164,18 @@ export const registerFollowerIndexRoutes = ({ router, __LEGACY }: RouteDependenc
path: `${API_BASE_PATH}/follower_indices/{id}`,
validate: {
params: schema.object({ id: schema.string() }),
+ body: schema.object({
+ maxReadRequestOperationCount: schema.maybe(schema.number()),
+ maxOutstandingReadRequests: schema.maybe(schema.number()),
+ maxReadRequestSize: schema.maybe(schema.string()), // byte value
+ maxWriteRequestOperationCount: schema.maybe(schema.number()),
+ maxWriteRequestSize: schema.maybe(schema.string()), // byte value
+ maxOutstandingWriteRequests: schema.maybe(schema.number()),
+ maxWriteBufferCount: schema.maybe(schema.number()),
+ maxWriteBufferSize: schema.maybe(schema.string()), // byte value
+ maxRetryDelay: schema.maybe(schema.string()), // time value
+ readPollTimeout: schema.maybe(schema.string()), // time value
+ }),
},
},
licensePreRoutingFactory({
diff --git a/x-pack/legacy/plugins/siem/scripts/check_circular_deps.js b/x-pack/legacy/plugins/maps/common/get_join_key.ts
similarity index 66%
rename from x-pack/legacy/plugins/siem/scripts/check_circular_deps.js
rename to x-pack/legacy/plugins/maps/common/get_join_key.ts
index 046cc010621d7..004f12ca08d2e 100644
--- a/x-pack/legacy/plugins/siem/scripts/check_circular_deps.js
+++ b/x-pack/legacy/plugins/maps/common/get_join_key.ts
@@ -4,5 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/
-require('../../../../../src/setup_node_env');
-require('../dev_tools/circular_deps/run_check_circular_deps_cli');
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+export * from '../../../../plugins/maps/common/get_join_key';
diff --git a/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.test.ts b/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.test.ts
new file mode 100644
index 0000000000000..d92bf06541433
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.test.ts
@@ -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;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { LAYER_TYPE } from '../constants';
+import { migrateJoinAggKey } from './join_agg_key';
+
+describe('migrateJoinAggKey', () => {
+ const joins = [
+ {
+ leftField: 'machine.os',
+ right: {
+ id: '9055b4aa-136a-4b6d-90ab-9f94ccfe5eb5',
+ indexPatternTitle: 'kibana_sample_data_logs',
+ term: 'machine.os.keyword',
+ metrics: [
+ {
+ type: 'avg',
+ field: 'bytes',
+ },
+ {
+ type: 'count',
+ },
+ ],
+ whereQuery: {
+ query: 'bytes > 10000',
+ language: 'kuery',
+ },
+ indexPatternRefName: 'layer_1_join_0_index_pattern',
+ },
+ },
+ {
+ leftField: 'machine.os',
+ right: {
+ id: '9a7f4e71-9500-4512-82f1-b7eaee3d87ff',
+ indexPatternTitle: 'kibana_sample_data_logs',
+ term: 'machine.os.keyword',
+ whereQuery: {
+ query: 'bytes < 10000',
+ language: 'kuery',
+ },
+ metrics: [
+ {
+ type: 'avg',
+ field: 'bytes',
+ },
+ ],
+ indexPatternRefName: 'layer_1_join_1_index_pattern',
+ },
+ },
+ ];
+
+ test('Should handle missing layerListJSON attribute', () => {
+ const attributes = {
+ title: 'my map',
+ };
+ expect(migrateJoinAggKey({ attributes })).toEqual({
+ title: 'my map',
+ });
+ });
+
+ test('Should migrate vector styles from legacy join agg key to new join agg key', () => {
+ const layerListJSON = JSON.stringify([
+ {
+ type: LAYER_TYPE.VECTOR,
+ joins,
+ style: {
+ properties: {
+ fillColor: {
+ type: 'DYNAMIC',
+ options: {
+ color: 'Blues',
+ colorCategory: 'palette_0',
+ field: {
+ name:
+ '__kbnjoin__avg_of_bytes_groupby_kibana_sample_data_logs.machine.os.keyword',
+ origin: 'join',
+ },
+ fieldMetaOptions: {
+ isEnabled: true,
+ sigma: 3,
+ },
+ type: 'ORDINAL',
+ },
+ },
+ lineColor: {
+ type: 'DYNAMIC',
+ options: {
+ color: 'Blues',
+ colorCategory: 'palette_0',
+ field: {
+ name: '__kbnjoin__count_groupby_kibana_sample_data_logs.machine.os.keyword',
+ origin: 'join',
+ },
+ fieldMetaOptions: {
+ isEnabled: true,
+ sigma: 3,
+ },
+ type: 'ORDINAL',
+ },
+ },
+ lineWidth: {
+ type: 'DYNAMIC',
+ options: {
+ color: 'Blues',
+ colorCategory: 'palette_0',
+ field: {
+ name: 'mySourceField',
+ origin: 'source',
+ },
+ fieldMetaOptions: {
+ isEnabled: true,
+ sigma: 3,
+ },
+ type: 'ORDINAL',
+ },
+ },
+ },
+ },
+ },
+ ]);
+ const attributes = {
+ title: 'my map',
+ layerListJSON,
+ };
+ const { layerListJSON: migratedLayerListJSON } = migrateJoinAggKey({ attributes });
+ const migratedLayerList = JSON.parse(migratedLayerListJSON!);
+ expect(migratedLayerList[0].style.properties.fillColor.options.field.name).toBe(
+ '__kbnjoin__avg_of_bytes__9055b4aa-136a-4b6d-90ab-9f94ccfe5eb5'
+ );
+ expect(migratedLayerList[0].style.properties.lineColor.options.field.name).toBe(
+ '__kbnjoin__count__9055b4aa-136a-4b6d-90ab-9f94ccfe5eb5'
+ );
+ expect(migratedLayerList[0].style.properties.lineWidth.options.field.name).toBe(
+ 'mySourceField'
+ );
+ });
+});
diff --git a/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.ts b/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.ts
new file mode 100644
index 0000000000000..29661aedb550c
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.ts
@@ -0,0 +1,121 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import _ from 'lodash';
+import {
+ AGG_DELIMITER,
+ AGG_TYPE,
+ FIELD_ORIGIN,
+ JOIN_FIELD_NAME_PREFIX,
+ LAYER_TYPE,
+ VECTOR_STYLES,
+} from '../constants';
+import { getJoinAggKey } from '../get_join_key';
+import {
+ AggDescriptor,
+ JoinDescriptor,
+ LayerDescriptor,
+ VectorLayerDescriptor,
+} from '../descriptor_types';
+import { MapSavedObjectAttributes } from '../../../../../plugins/maps/common/map_saved_object_type';
+
+const GROUP_BY_DELIMITER = '_groupby_';
+
+function getLegacyAggKey({
+ aggType,
+ aggFieldName,
+ indexPatternTitle,
+ termFieldName,
+}: {
+ aggType: AGG_TYPE;
+ aggFieldName?: string;
+ indexPatternTitle: string;
+ termFieldName: string;
+}): string {
+ const metricKey =
+ aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${aggFieldName}` : aggType;
+ return `${JOIN_FIELD_NAME_PREFIX}${metricKey}${GROUP_BY_DELIMITER}${indexPatternTitle}.${termFieldName}`;
+}
+
+function parseLegacyAggKey(legacyAggKey: string): { aggType: AGG_TYPE; aggFieldName?: string } {
+ const groupBySplit = legacyAggKey
+ .substring(JOIN_FIELD_NAME_PREFIX.length)
+ .split(GROUP_BY_DELIMITER);
+ const metricKey = groupBySplit[0];
+ const metricKeySplit = metricKey.split(AGG_DELIMITER);
+ return {
+ aggType: metricKeySplit[0] as AGG_TYPE,
+ aggFieldName: metricKeySplit.length === 2 ? metricKeySplit[1] : undefined,
+ };
+}
+
+export function migrateJoinAggKey({
+ attributes,
+}: {
+ attributes: MapSavedObjectAttributes;
+}): MapSavedObjectAttributes {
+ if (!attributes || !attributes.layerListJSON) {
+ return attributes;
+ }
+
+ const layerList: LayerDescriptor[] = JSON.parse(attributes.layerListJSON);
+ layerList.forEach((layerDescriptor: LayerDescriptor) => {
+ if (
+ layerDescriptor.type === LAYER_TYPE.VECTOR ||
+ layerDescriptor.type === LAYER_TYPE.BLENDED_VECTOR
+ ) {
+ const vectorLayerDescriptor = layerDescriptor as VectorLayerDescriptor;
+
+ if (
+ !vectorLayerDescriptor.style ||
+ !vectorLayerDescriptor.joins ||
+ vectorLayerDescriptor.joins.length === 0
+ ) {
+ return;
+ }
+
+ const legacyJoinFields = new Map();
+ vectorLayerDescriptor.joins.forEach((joinDescriptor: JoinDescriptor) => {
+ _.get(joinDescriptor, 'right.metrics', []).forEach((aggDescriptor: AggDescriptor) => {
+ const legacyAggKey = getLegacyAggKey({
+ aggType: aggDescriptor.type,
+ aggFieldName: aggDescriptor.field,
+ indexPatternTitle: _.get(joinDescriptor, 'right.indexPatternTitle', ''),
+ termFieldName: _.get(joinDescriptor, 'right.term', ''),
+ });
+ // The legacy getAggKey implemenation has a naming collision bug where
+ // aggType, aggFieldName, indexPatternTitle, and termFieldName would result in the identical aggKey.
+ // The VectorStyle implemenation used the first matching join descriptor
+ // so, in the event of a name collision, the first join descriptor will be used here as well.
+ if (!legacyJoinFields.has(legacyAggKey)) {
+ legacyJoinFields.set(legacyAggKey, joinDescriptor);
+ }
+ });
+ });
+
+ Object.keys(vectorLayerDescriptor.style.properties).forEach(key => {
+ const style: any = vectorLayerDescriptor.style!.properties[key as VECTOR_STYLES];
+ if (_.get(style, 'options.field.origin') === FIELD_ORIGIN.JOIN) {
+ const joinDescriptor = legacyJoinFields.get(style.options.field.name);
+ if (joinDescriptor) {
+ const { aggType, aggFieldName } = parseLegacyAggKey(style.options.field.name);
+ // Update legacy join agg key to new join agg key
+ style.options.field.name = getJoinAggKey({
+ aggType,
+ aggFieldName,
+ rightSourceId: joinDescriptor.right.id!,
+ });
+ }
+ }
+ });
+ }
+ });
+
+ return {
+ ...attributes,
+ layerListJSON: JSON.stringify(layerList),
+ };
+}
diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js
index 1a7f478d3bbad..f4e01efc05f45 100644
--- a/x-pack/legacy/plugins/maps/index.js
+++ b/x-pack/legacy/plugins/maps/index.js
@@ -38,6 +38,7 @@ export function maps(kibana) {
return {
showMapVisualizationTypes: serverConfig.get('xpack.maps.showMapVisualizationTypes'),
showMapsInspectorAdapter: serverConfig.get('xpack.maps.showMapsInspectorAdapter'),
+ enableVectorTiles: serverConfig.get('xpack.maps.enableVectorTiles'),
preserveDrawingBuffer: serverConfig.get('xpack.maps.preserveDrawingBuffer'),
isEmsEnabled: mapConfig.includeElasticMapsService,
emsFontLibraryUrl: mapConfig.emsFontLibraryUrl,
@@ -85,6 +86,7 @@ export function maps(kibana) {
showMapVisualizationTypes: Joi.boolean().default(false),
showMapsInspectorAdapter: Joi.boolean().default(false), // flag used in functional testing
preserveDrawingBuffer: Joi.boolean().default(false), // flag used in functional testing
+ enableVectorTiles: Joi.boolean().default(false), // flag used to enable/disable vector-tiles
}).default();
},
diff --git a/x-pack/legacy/plugins/maps/migrations.js b/x-pack/legacy/plugins/maps/migrations.js
index 6a1f5bc937497..a8e69eef7a02f 100644
--- a/x-pack/legacy/plugins/maps/migrations.js
+++ b/x-pack/legacy/plugins/maps/migrations.js
@@ -11,6 +11,7 @@ import { moveApplyGlobalQueryToSources } from './common/migrations/move_apply_gl
import { addFieldMetaOptions } from './common/migrations/add_field_meta_options';
import { migrateSymbolStyleDescriptor } from './common/migrations/migrate_symbol_style_descriptor';
import { migrateUseTopHitsToScalingType } from './common/migrations/scaling_type';
+import { migrateJoinAggKey } from './common/migrations/join_agg_key';
export const migrations = {
map: {
@@ -57,5 +58,13 @@ export const migrations = {
attributes: attributesPhase2,
};
},
+ '7.8.0': doc => {
+ const attributes = migrateJoinAggKey(doc);
+
+ return {
+ ...doc,
+ attributes,
+ };
+ },
},
};
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/view.js
index a54df69471aa0..92fcf01f3901f 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/view.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/view.js
@@ -63,13 +63,13 @@ export class AddLayerPanel extends Component {
return;
}
- const style =
+ const styleDescriptor =
this.state.layer && this.state.layer.getCurrentStyle()
? this.state.layer.getCurrentStyle().getDescriptor()
: null;
const layerInitProps = {
...options,
- style: style,
+ style: styleDescriptor,
};
const newLayer = source.createDefaultLayer(layerInitProps, this.props.mapColors);
if (!this._isMounted) {
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/layer_settings/index.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/layer_settings/index.js
index 73c98db8e429d..e8f980bbbf2b4 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/layer_settings/index.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/layer_settings/index.js
@@ -13,10 +13,13 @@ import {
updateLayerMinZoom,
updateLayerAlpha,
} from '../../../actions/map_actions';
+import { MAX_ZOOM } from '../../../../../../../plugins/maps/common/constants';
function mapStateToProps(state = {}) {
const selectedLayer = getSelectedLayer(state);
return {
+ minVisibilityZoom: selectedLayer.getMinSourceZoom(),
+ maxVisibilityZoom: MAX_ZOOM,
alpha: selectedLayer.getAlpha(),
label: selectedLayer.getLabel(),
layerId: selectedLayer.getId(),
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/layer_settings/layer_settings.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/layer_settings/layer_settings.js
index bd27450943638..1d352913e54a3 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/layer_settings/layer_settings.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/layer_settings/layer_settings.js
@@ -13,8 +13,6 @@ import { ValidatedRange } from '../../../../../../../plugins/maps/public/compone
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { ValidatedDualRange } from '../../../../../../../../src/plugins/kibana_react/public';
-import { MAX_ZOOM, MIN_ZOOM } from '../../../../common/constants';
-
export function LayerSettings(props) {
const onLabelChange = event => {
const label = event.target.value;
@@ -22,8 +20,8 @@ export function LayerSettings(props) {
};
const onZoomChange = ([min, max]) => {
- props.updateMinZoom(props.layerId, Math.max(MIN_ZOOM, parseInt(min, 10)));
- props.updateMaxZoom(props.layerId, Math.min(MAX_ZOOM, parseInt(max, 10)));
+ props.updateMinZoom(props.layerId, Math.max(props.minVisibilityZoom, parseInt(min, 10)));
+ props.updateMaxZoom(props.layerId, Math.min(props.maxVisibilityZoom, parseInt(max, 10)));
};
const onAlphaChange = alpha => {
@@ -38,8 +36,8 @@ export function LayerSettings(props) {
defaultMessage: 'Visibility',
})}
formRowDisplay="columnCompressed"
- min={MIN_ZOOM}
- max={MAX_ZOOM}
+ min={props.minVisibilityZoom}
+ max={props.maxVisibilityZoom}
value={[props.minZoom, props.maxZoom]}
showInput="inputWithPopover"
showRange
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js
index 1fe3d0d493ee7..a36e1d7048e92 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js
@@ -14,7 +14,12 @@ import {
} from './utils';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getGlyphUrl, isRetina } from '../../../../../../../plugins/maps/public/meta';
-import { DECIMAL_DEGREES_PRECISION, ZOOM_PRECISION } from '../../../../common/constants';
+import {
+ DECIMAL_DEGREES_PRECISION,
+ MAX_ZOOM,
+ MIN_ZOOM,
+ ZOOM_PRECISION,
+} from '../../../../common/constants';
import mapboxgl from 'mapbox-gl/dist/mapbox-gl-csp';
import mbWorkerUrl from '!!file-loader!mapbox-gl/dist/mapbox-gl-csp-worker';
import mbRtlPlugin from '!!file-loader!@mapbox/mapbox-gl-rtl-text/mapbox-gl-rtl-text.min.js';
@@ -132,6 +137,8 @@ export class MBMapContainer extends React.Component {
scrollZoom: this.props.scrollZoom,
preserveDrawingBuffer: getInjectedVarFunc()('preserveDrawingBuffer', false),
interactive: !this.props.disableInteractive,
+ minZoom: MIN_ZOOM,
+ maxZoom: MAX_ZOOM,
};
const initialView = _.get(this.props.goto, 'center');
if (initialView) {
diff --git a/x-pack/legacy/plugins/maps/public/plugin.ts b/x-pack/legacy/plugins/maps/public/plugin.ts
index 4ec068ff44029..71f1a30c1fbef 100644
--- a/x-pack/legacy/plugins/maps/public/plugin.ts
+++ b/x-pack/legacy/plugins/maps/public/plugin.ts
@@ -4,13 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import '../../../../plugins/maps/public/layers/layer_wizard_registry';
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import '../../../../plugins/maps/public/layers/sources/source_registry';
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import '../../../../plugins/maps/public/layers/load_layer_wizards';
-
import { Plugin, CoreStart, CoreSetup } from 'src/core/public';
// @ts-ignore
import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
diff --git a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
index f350a2c944756..1e71025935519 100644
--- a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
+++ b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
@@ -19,6 +19,8 @@ import { BlendedVectorLayer } from '../../../../../plugins/maps/public/layers/bl
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getTimeFilter } from '../../../../../plugins/maps/public/kibana_services';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { TiledVectorLayer } from '../../../../../plugins/maps/public/layers/tiled_vector_layer';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getInspectorAdapters } from '../../../../../plugins/maps/public/reducers/non_serializable_instances';
import {
copyPersistentState,
@@ -51,6 +53,8 @@ function createLayerInstance(layerDescriptor, inspectorAdapters) {
return new HeatmapLayer({ layerDescriptor, source });
case BlendedVectorLayer.type:
return new BlendedVectorLayer({ layerDescriptor, source });
+ case TiledVectorLayer.type:
+ return new TiledVectorLayer({ layerDescriptor, source });
default:
throw new Error(`Unrecognized layerType ${layerDescriptor.type}`);
}
diff --git a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js
index b83be301653b8..72cc748617540 100644
--- a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js
+++ b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js
@@ -5,6 +5,7 @@
*/
jest.mock('../../../../../plugins/maps/public/layers/vector_layer', () => {});
+jest.mock('../../../../../plugins/maps/public/layers/tiled_vector_layer', () => {});
jest.mock('../../../../../plugins/maps/public/layers/blended_vector_layer', () => {});
jest.mock('../../../../../plugins/maps/public/layers/heatmap_layer', () => {});
jest.mock('../../../../../plugins/maps/public/layers/vector_tile_layer', () => {});
diff --git a/x-pack/legacy/plugins/rollup/README.md b/x-pack/legacy/plugins/rollup/README.md
index 6d04973de591e..3647be38b6a09 100644
--- a/x-pack/legacy/plugins/rollup/README.md
+++ b/x-pack/legacy/plugins/rollup/README.md
@@ -14,7 +14,7 @@ The rest of this doc dives into the implementation details of each of the above
## Create and manage rollup jobs
-The most straight forward part of this plugin! A new app called Rollup Jobs is registered in the Management section and follows a typical CRUD UI pattern. This app allows users to create, start, stop, clone, and delete rollup jobs. There is no way to edit an existing rollup job; instead, the UI offers a cloning ability. The client-side portion of this app lives [here](public/crud_app) and uses endpoints registered [here](server/routes/api/jobs.js).
+The most straight forward part of this plugin! A new app called Rollup Jobs is registered in the Management section and follows a typical CRUD UI pattern. This app allows users to create, start, stop, clone, and delete rollup jobs. There is no way to edit an existing rollup job; instead, the UI offers a cloning ability. The client-side portion of this app lives [here](../../../plugins/rollup/public/crud_app) and uses endpoints registered [here](server/routes/api/jobs.js).
Refer to the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/rollup-getting-started.html) to understand rollup indices and how to create rollup jobs.
@@ -22,22 +22,22 @@ Refer to the [Elasticsearch documentation](https://www.elastic.co/guide/en/elast
Kibana uses index patterns to consume and visualize rollup indices. Typically, Kibana can inspect the indices captured by an index pattern, identify its aggregations and fields, and determine how to consume the data. Rollup indices don't contain this type of information, so we predefine how to consume a rollup index pattern with the type and typeMeta fields on the index pattern saved object. All rollup index patterns have `type` defined as "rollup" and `typeMeta` defined as an object of the index pattern's capabilities.
-In the Index Pattern app, the "Create index pattern" button includes a context menu when a rollup index is detected. This menu offers items for creating a standard index pattern and a rollup index pattern. A [rollup config is registered to index pattern creation extension point](public/index_pattern_creation/rollup_index_pattern_creation_config.js). The context menu behavior in particular uses the `getIndexPatternCreationOption()` method. When the user chooses to create a rollup index pattern, this config changes the behavior of the index pattern creation wizard:
+In the Index Pattern app, the "Create index pattern" button includes a context menu when a rollup index is detected. This menu offers items for creating a standard index pattern and a rollup index pattern. A [rollup config is registered to index pattern creation extension point](../../../plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js). The context menu behavior in particular uses the `getIndexPatternCreationOption()` method. When the user chooses to create a rollup index pattern, this config changes the behavior of the index pattern creation wizard:
1. Adds a `Rollup` badge to rollup indices using `getIndexTags()`.
2. Enforces index pattern rules using `checkIndicesForErrors()`. Rollup index patterns must match **one** rollup index, and optionally, any number of regular indices. A rollup index pattern configured with one or more regular indices is known as a "hybrid" index pattern. This allows the user to visualize historical (rollup) data and live (regular) data in the same visualization.
3. Routes to this plugin's [rollup `_fields_for_wildcard` endpoint](server/routes/api/index_patterns.js), instead of the standard one, using `getFetchForWildcardOptions()`, so that the internal rollup data field names are mapped to the original field names.
4. Writes additional information about aggregations, fields, histogram interval, and date histogram interval and timezone to the rollup index pattern saved object using `getIndexPatternMappings()`. This collection of information is referred to as its "capabilities".
-Once a rollup index pattern is created, it is tagged with `Rollup` in the list of index patterns, and its details page displays capabilities information. This is done by registering [yet another config for the index pattern list](public/index_pattern_list/rollup_index_pattern_list_config.js) extension points.
+Once a rollup index pattern is created, it is tagged with `Rollup` in the list of index patterns, and its details page displays capabilities information. This is done by registering [yet another config for the index pattern list](../../../plugins/rollup/public/index_pattern_list/rollup_index_pattern_list_config.js) extension points.
## Create visualizations from rollup index patterns
This plugin enables the user to create visualizations from rollup data using the Visualize app, excluding TSVB, Vega, and Timelion. When Visualize sends search requests, this plugin routes the requests to the [Elasticsearch rollup search endpoint](https://www.elastic.co/guide/en/elasticsearch/reference/current/rollup-search.html), which searches the special document structure within rollup indices. The visualization options available to users are based on the capabilities of the rollup index pattern they're visualizing.
-Routing to the Elasticsearch rollup search endpoint is done by creating an extension point in Courier, effectively allowing multiple "search strategies" to be registered. A [rollup search strategy](public/search/register.js) is registered by this plugin that queries [this plugin's rollup search endpoint](server/routes/api/search.js).
+Routing to the Elasticsearch rollup search endpoint is done by creating an extension point in Courier, effectively allowing multiple "search strategies" to be registered. A [rollup search strategy](../../../plugins/rollup/public/search/register.js) is registered by this plugin that queries [this plugin's rollup search endpoint](server/routes/api/search.js).
-Limiting visualization editor options is done by [registering configs](public/visualize/index.js) to various vis extension points. These configs use information stored on the rollup index pattern to limit:
+Limiting visualization editor options is done by [registering configs](../../../plugins/rollup/public/visualize/index.js) to various vis extension points. These configs use information stored on the rollup index pattern to limit:
* Available aggregation types
* Available fields for a particular aggregation
* Default and base interval for histogram aggregation
@@ -47,6 +47,6 @@ Limiting visualization editor options is done by [registering configs](public/vi
In Index Management, similar to system indices, rollup indices are hidden by default. A toggle is provided to show rollup indices and add a badge to the table rows. This is done by using Index Management's extension points.
-The toggle and badge are registered on client-side [here](public/extend_index_management/index.js).
+The toggle and badge are registered on client-side [here](../../../plugins/rollup/public/extend_index_management/index.js).
Additional data needed to filter rollup indices in Index Management is provided with a [data enricher](rollup_data_enricher.js).
diff --git a/x-pack/legacy/plugins/rollup/common/index.ts b/x-pack/legacy/plugins/rollup/common/index.ts
index 4229803462203..526af055a3ef6 100644
--- a/x-pack/legacy/plugins/rollup/common/index.ts
+++ b/x-pack/legacy/plugins/rollup/common/index.ts
@@ -16,24 +16,4 @@ export const PLUGIN = {
},
};
-export const CONFIG_ROLLUPS = 'rollups:enableIndexPatterns';
-
-export const API_BASE_PATH = '/api/rollup';
-
-export {
- UIM_APP_NAME,
- UIM_APP_LOAD,
- UIM_JOB_CREATE,
- UIM_JOB_DELETE,
- UIM_JOB_DELETE_MANY,
- UIM_JOB_START,
- UIM_JOB_START_MANY,
- UIM_JOB_STOP,
- UIM_JOB_STOP_MANY,
- UIM_SHOW_DETAILS_CLICK,
- UIM_DETAIL_PANEL_SUMMARY_TAB_CLICK,
- UIM_DETAIL_PANEL_TERMS_TAB_CLICK,
- UIM_DETAIL_PANEL_HISTOGRAM_TAB_CLICK,
- UIM_DETAIL_PANEL_METRICS_TAB_CLICK,
- UIM_DETAIL_PANEL_JSON_TAB_CLICK,
-} from './ui_metric';
+export * from '../../../../plugins/rollup/common';
diff --git a/x-pack/legacy/plugins/rollup/index.ts b/x-pack/legacy/plugins/rollup/index.ts
index 621667f3618b2..f33ae7cfee0a2 100644
--- a/x-pack/legacy/plugins/rollup/index.ts
+++ b/x-pack/legacy/plugins/rollup/index.ts
@@ -4,40 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { resolve } from 'path';
-import { i18n } from '@kbn/i18n';
import { PluginInitializerContext } from 'src/core/server';
import { RollupSetup } from '../../../plugins/rollup/server';
-import { PLUGIN, CONFIG_ROLLUPS } from './common';
+import { PLUGIN } from './common';
import { plugin } from './server';
export function rollup(kibana: any) {
return new kibana.Plugin({
id: PLUGIN.ID,
configPrefix: 'xpack.rollup',
- publicDir: resolve(__dirname, 'public'),
require: ['kibana', 'elasticsearch', 'xpack_main'],
- uiExports: {
- styleSheetPaths: resolve(__dirname, 'public/index.scss'),
- managementSections: ['plugins/rollup/legacy'],
- uiSettingDefaults: {
- [CONFIG_ROLLUPS]: {
- name: i18n.translate('xpack.rollupJobs.rollupIndexPatternsTitle', {
- defaultMessage: 'Enable rollup index patterns',
- }),
- value: true,
- description: i18n.translate('xpack.rollupJobs.rollupIndexPatternsDescription', {
- defaultMessage: `Enable the creation of index patterns which capture rollup indices,
- which in turn enable visualizations based on rollup data. Refresh
- the page to apply the changes.`,
- }),
- category: ['rollups'],
- },
- },
- indexManagement: ['plugins/rollup/legacy'],
- visualize: ['plugins/rollup/legacy'],
- search: ['plugins/rollup/legacy'],
- },
init(server: any) {
const { core: coreSetup, plugins } = server.newPlatform.setup;
const { usageCollection, visTypeTimeseries, indexManagement } = plugins;
diff --git a/x-pack/legacy/plugins/rollup/public/legacy.ts b/x-pack/legacy/plugins/rollup/public/legacy.ts
deleted file mode 100644
index 83945110c2c76..0000000000000
--- a/x-pack/legacy/plugins/rollup/public/legacy.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { npSetup, npStart } from 'ui/new_platform';
-import { RollupPlugin } from './plugin';
-
-const plugin = new RollupPlugin();
-
-export const setup = plugin.setup(npSetup.core, npSetup.plugins);
-export const start = plugin.start(npStart.core, npStart.plugins);
diff --git a/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.ts b/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.ts
deleted file mode 100644
index 4709c0aa498f8..0000000000000
--- a/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { HttpSetup } from 'src/core/public';
-import {
- SearchError,
- getSearchErrorType,
- IIndexPattern,
- SearchStrategyProvider,
- SearchResponse,
- SearchRequest,
-} from '../../../../../../src/plugins/data/public';
-
-function serializeFetchParams(searchRequests: SearchRequest[]) {
- return JSON.stringify(
- searchRequests.map(searchRequestWithFetchParams => {
- const indexPattern =
- searchRequestWithFetchParams.index.title || searchRequestWithFetchParams.index;
- const {
- body: { size, aggs, query: _query },
- } = searchRequestWithFetchParams;
-
- const query = {
- size,
- aggregations: aggs,
- query: _query,
- };
-
- return { index: indexPattern, query };
- })
- );
-}
-
-// Rollup search always returns 0 hits, but visualizations expect search responses
-// to return hits > 0, otherwise they do not render. We fake the number of hits here
-// by counting the number of aggregation buckets/values returned by rollup search.
-function shimHitsInFetchResponse(response: SearchResponse[]) {
- return response.map(result => {
- const buckets = result.aggregations
- ? Object.keys(result.aggregations).reduce((allBuckets, agg) => {
- return allBuckets.concat(
- result.aggregations[agg].buckets || [result.aggregations[agg].value] || []
- );
- }, [])
- : [];
- return buckets && buckets.length
- ? {
- ...result,
- hits: {
- ...result.hits,
- total: buckets.length,
- },
- }
- : result;
- });
-}
-
-export const getRollupSearchStrategy = (fetch: HttpSetup['fetch']): SearchStrategyProvider => ({
- id: 'rollup',
-
- search: ({ searchRequests }) => {
- // Serialize the fetch params into a format suitable for the body of an ES query.
- const serializedFetchParams = serializeFetchParams(searchRequests);
-
- const controller = new AbortController();
- const promise = fetch('../api/rollup/search', {
- signal: controller.signal,
- method: 'POST',
- body: serializedFetchParams,
- });
-
- return {
- searching: promise.then(shimHitsInFetchResponse).catch(error => {
- const {
- body: { statusCode, error: title, message },
- res: { url },
- } = error;
-
- // Format fetch error as a SearchError.
- const searchError = new SearchError({
- status: statusCode,
- title,
- message: `Rollup search error: ${message}`,
- path: url,
- type: getSearchErrorType({ message }) || '',
- });
-
- return Promise.reject(searchError);
- }),
- abort: () => controller.abort(),
- };
- },
-
- isViable: (indexPattern: IIndexPattern) => {
- if (!indexPattern) {
- return false;
- }
-
- return indexPattern.type === 'rollup';
- },
-});
diff --git a/x-pack/legacy/plugins/siem/.gitattributes b/x-pack/legacy/plugins/siem/.gitattributes
index f40e829b65453..a4071d39e63c0 100644
--- a/x-pack/legacy/plugins/siem/.gitattributes
+++ b/x-pack/legacy/plugins/siem/.gitattributes
@@ -1,6 +1,5 @@
# Auto-collapse generated files in GitHub
# https://help.github.com/en/articles/customizing-how-changed-files-appear-on-github
x-pack/legacy/plugins/siem/public/graphql/types.ts linguist-generated=true
-x-pack/legacy/plugins/siem/server/graphql/types.ts linguist-generated=true
x-pack/legacy/plugins/siem/public/graphql/introspection.json linguist-generated=true
diff --git a/x-pack/legacy/plugins/siem/cypress.json b/x-pack/legacy/plugins/siem/cypress.json
deleted file mode 100644
index a0333a1068146..0000000000000
--- a/x-pack/legacy/plugins/siem/cypress.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "baseUrl": "http://localhost:5601",
- "defaultCommandTimeout": 120000,
- "screenshotsFolder": "../../../../target/kibana-siem/cypress/screenshots",
- "trashAssetsBeforeRuns": false,
- "video": false,
- "videosFolder": "../../../../target/kibana-siem/cypress/videos"
-}
diff --git a/x-pack/legacy/plugins/siem/index.ts b/x-pack/legacy/plugins/siem/index.ts
index 3773283555b32..6e03583dda69f 100644
--- a/x-pack/legacy/plugins/siem/index.ts
+++ b/x-pack/legacy/plugins/siem/index.ts
@@ -6,11 +6,10 @@
import { i18n } from '@kbn/i18n';
import { resolve } from 'path';
-import { Server } from 'hapi';
import { Root } from 'joi';
-import { plugin } from './server';
-import { savedObjectMappings } from './server/saved_objects';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { savedObjectMappings } from '../../../plugins/siem/server/saved_objects';
import {
APP_ID,
@@ -23,15 +22,13 @@ import {
DEFAULT_INTERVAL_VALUE,
DEFAULT_FROM,
DEFAULT_TO,
- DEFAULT_SIGNALS_INDEX,
ENABLE_NEWS_FEED_SETTING,
NEWS_FEED_URL_SETTING,
NEWS_FEED_URL_SETTING_DEFAULT,
- SIGNALS_INDEX_KEY,
IP_REPUTATION_LINKS_SETTING,
IP_REPUTATION_LINKS_SETTING_DEFAULT,
-} from './common/constants';
-import { defaultIndexPattern } from './default_index_pattern';
+ DEFAULT_INDEX_PATTERN,
+} from '../../../plugins/siem/common/constants';
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -102,7 +99,7 @@ export const siem = (kibana: any) => {
name: i18n.translate('xpack.siem.uiSettings.defaultIndexLabel', {
defaultMessage: 'Elasticsearch indices',
}),
- value: defaultIndexPattern,
+ value: DEFAULT_INDEX_PATTERN,
description: i18n.translate('xpack.siem.uiSettings.defaultIndexDescription', {
defaultMessage:
'
Comma-delimited list of Elasticsearch indices from which the SIEM app collects events.
',
@@ -162,31 +159,12 @@ export const siem = (kibana: any) => {
},
mappings: savedObjectMappings,
},
- init(server: Server) {
- const { coreContext, env, setup, start } = server.newPlatform;
- const initializerContext = { ...coreContext, env };
- const __legacy = {
- config: server.config,
- route: server.route.bind(server),
- };
-
- // @ts-ignore-next-line: NewPlatform shim is too loosely typed
- const pluginInstance = plugin(initializerContext);
- // @ts-ignore-next-line: NewPlatform shim is too loosely typed
- pluginInstance.setup(setup.core, setup.plugins, __legacy);
- // @ts-ignore-next-line: NewPlatform shim is too loosely typed
- pluginInstance.start(start.core, start.plugins);
- },
config(Joi: Root) {
- // See x-pack/plugins/siem/server/config.ts if you're adding another
- // value where the configuration has to be duplicated at the moment.
- // When we move over to the new platform completely this will be
- // removed and only server/config.ts should be used.
return Joi.object()
.keys({
enabled: Joi.boolean().default(true),
- [SIGNALS_INDEX_KEY]: Joi.string().default(DEFAULT_SIGNALS_INDEX),
})
+ .unknown(true)
.default();
},
});
diff --git a/x-pack/legacy/plugins/siem/package.json b/x-pack/legacy/plugins/siem/package.json
index 472a473842f02..3a93beef963a0 100644
--- a/x-pack/legacy/plugins/siem/package.json
+++ b/x-pack/legacy/plugins/siem/package.json
@@ -1,16 +1,10 @@
{
"author": "Elastic",
- "name": "siem",
+ "name": "siem-legacy-ui",
"version": "8.0.0",
"private": true,
"license": "Elastic-License",
- "scripts": {
- "extract-mitre-attacks": "node scripts/extract_tactics_techniques_mitre.js & node ../../../../scripts/eslint ./public/pages/detection_engine/mitre/mitre_tactics_techniques.ts --fix",
- "build-graphql-types": "node scripts/generate_types_from_graphql.js",
- "cypress:open": "../../../node_modules/.bin/cypress open",
- "cypress:run": "../../../node_modules/.bin/cypress run --spec ./cypress/integration/**/*.spec.ts --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./reporter_config.json; status=$?; ../../../node_modules/.bin/mochawesome-merge --reportDir ../../../../target/kibana-siem/cypress/results > ../../../../target/kibana-siem/cypress/results/output.json; ../../../../node_modules/.bin/marge ../../../../target/kibana-siem/cypress/results/output.json --reportDir ../../../../target/kibana-siem/cypress/results; mkdir -p ../../../../target/junit && cp ../../../../target/kibana-siem/cypress/results/*.xml ../../../../target/junit/ && exit $status;",
- "cypress:run-as-ci": "node ../../../../scripts/functional_tests --config ../../../test/siem_cypress/config.ts"
- },
+ "scripts": {},
"devDependencies": {
"@types/lodash": "^4.14.110",
"@types/js-yaml": "^3.12.1",
diff --git a/x-pack/legacy/plugins/siem/public/app/app.tsx b/x-pack/legacy/plugins/siem/public/app/app.tsx
index 7413aeab549db..44c1c923cd6ee 100644
--- a/x-pack/legacy/plugins/siem/public/app/app.tsx
+++ b/x-pack/legacy/plugins/siem/public/app/app.tsx
@@ -20,7 +20,7 @@ import { pluck } from 'rxjs/operators';
import { KibanaContextProvider, useKibana, useUiSetting$ } from '../lib/kibana';
import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
-import { DEFAULT_DARK_MODE } from '../../common/constants';
+import { DEFAULT_DARK_MODE } from '../../../../../plugins/siem/common/constants';
import { ErrorToastDispatcher } from '../components/error_toast_dispatcher';
import { compose } from '../lib/compose/kibana_compose';
import { AppFrontendLibs, AppApolloClient } from '../lib/lib';
diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx
index 587002c24d526..778adc708d901 100644
--- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx
@@ -6,11 +6,11 @@
import React, { useEffect, useCallback, useMemo } from 'react';
import numeral from '@elastic/numeral';
+import { DEFAULT_NUMBER_FORMAT } from '../../../../../../plugins/siem/common/constants';
import { AlertsComponentsQueryProps } from './types';
import { AlertsTable } from './alerts_table';
import * as i18n from './translations';
import { useUiSetting$ } from '../../lib/kibana';
-import { DEFAULT_NUMBER_FORMAT } from '../../../common/constants';
import { MatrixHistogramContainer } from '../matrix_histogram';
import { histogramConfigs } from './histogram_configs';
import { MatrixHisrogramConfigs } from '../matrix_histogram/types';
diff --git a/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx
index 272c41833f368..635d48cca10fc 100644
--- a/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx
@@ -4,15 +4,29 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { shallow, ShallowWrapper } from 'enzyme';
+import { Chart, BarSeries, Axis, ScaleType } from '@elastic/charts';
+import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
+import { mount, ReactWrapper, shallow, ShallowWrapper } from 'enzyme';
import React from 'react';
+import { ThemeProvider } from 'styled-components';
+
+import { escapeDataProviderId } from '../drag_and_drop/helpers';
+import { TestProviders } from '../../mock';
import { BarChartBaseComponent, BarChartComponent } from './barchart';
import { ChartSeriesData } from './common';
-import { Chart, BarSeries, Axis, ScaleType } from '@elastic/charts';
jest.mock('../../lib/kibana');
+jest.mock('uuid', () => {
+ return {
+ v1: jest.fn(() => 'uuid.v1()'),
+ v4: jest.fn(() => 'uuid.v4()'),
+ };
+});
+
+const theme = () => ({ eui: euiDarkVars, darkMode: true });
+
const customHeight = '100px';
const customWidth = '120px';
const chartDataSets = [
@@ -116,6 +130,19 @@ const mockConfig = {
customHeight: 324,
};
+// Suppress warnings about "react-beautiful-dnd"
+/* eslint-disable no-console */
+const originalError = console.error;
+const originalWarn = console.warn;
+beforeAll(() => {
+ console.warn = jest.fn();
+ console.error = jest.fn();
+});
+afterAll(() => {
+ console.error = originalError;
+ console.warn = originalWarn;
+});
+
describe('BarChartBaseComponent', () => {
let shallowWrapper: ShallowWrapper;
const mockBarChartData: ChartSeriesData[] = [
@@ -280,6 +307,91 @@ describe.each(chartDataSets)('BarChart with valid data [%o]', data => {
expect(shallowWrapper.find('BarChartBase')).toHaveLength(1);
expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(0);
});
+
+ it('it does NOT render a draggable legend because stackByField is not provided', () => {
+ expect(shallowWrapper.find('[data-test-subj="draggable-legend"]').exists()).toBe(false);
+ });
+});
+
+describe.each(chartDataSets)('BarChart with stackByField', () => {
+ let wrapper: ReactWrapper;
+
+ const data = [
+ {
+ key: 'python.exe',
+ value: [
+ {
+ x: 1586754900000,
+ y: 9675,
+ g: 'python.exe',
+ },
+ ],
+ },
+ {
+ key: 'kernel',
+ value: [
+ {
+ x: 1586754900000,
+ y: 8708,
+ g: 'kernel',
+ },
+ {
+ x: 1586757600000,
+ y: 9282,
+ g: 'kernel',
+ },
+ ],
+ },
+ {
+ key: 'sshd',
+ value: [
+ {
+ x: 1586754900000,
+ y: 5907,
+ g: 'sshd',
+ },
+ ],
+ },
+ ];
+
+ const expectedColors = ['#1EA593', '#2B70F7', '#CE0060'];
+
+ const stackByField = 'process.name';
+
+ beforeAll(() => {
+ wrapper = mount(
+
+
+
+
+
+ );
+ });
+
+ it('it renders a draggable legend', () => {
+ expect(wrapper.find('[data-test-subj="draggable-legend"]').exists()).toBe(true);
+ });
+
+ expectedColors.forEach((color, i) => {
+ test(`it renders the expected legend color ${color} for legend item ${i}`, () => {
+ expect(wrapper.find(`div [color="${color}"]`).exists()).toBe(true);
+ });
+ });
+
+ data.forEach(datum => {
+ test(`it renders the expected draggable legend text for datum ${datum.key}`, () => {
+ const dataProviderId = `draggableId.content.draggable-legend-item-uuid_v4()-${escapeDataProviderId(
+ stackByField
+ )}-${escapeDataProviderId(datum.key)}`;
+
+ expect(
+ wrapper
+ .find(`div [data-rbd-draggable-id="${dataProviderId}"]`)
+ .first()
+ .text()
+ ).toEqual(datum.key);
+ });
+ });
});
describe.each(chartHolderDataSets)('BarChart with invalid data [%o]', data => {
diff --git a/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx b/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx
index 2ae0e05850a37..64d15cd6731cb 100644
--- a/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx
@@ -4,13 +4,19 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import React, { useMemo } from 'react';
import { Chart, BarSeries, Axis, Position, ScaleType, Settings } from '@elastic/charts';
import { getOr, get, isNumber } from 'lodash/fp';
import deepmerge from 'deepmerge';
+import uuid from 'uuid';
+import styled from 'styled-components';
-import { useThrottledResizeObserver } from '../utils';
+import { escapeDataProviderId } from '../drag_and_drop/helpers';
import { useTimeZone } from '../../lib/kibana';
+import { defaultLegendColors } from '../matrix_histogram/utils';
+import { useThrottledResizeObserver } from '../utils';
+
import { ChartPlaceHolder } from './chart_place_holder';
import {
chartDefaultSettings,
@@ -22,6 +28,12 @@ import {
WrappedByAutoSizer,
useTheme,
} from './common';
+import { DraggableLegend } from './draggable_legend';
+import { LegendItem } from './draggable_legend_item';
+
+const LegendFlexItem = styled(EuiFlexItem)`
+ overview: hidden;
+`;
const checkIfAllTheDataInTheSeriesAreValid = (series: ChartSeriesData): series is ChartSeriesData =>
series != null &&
@@ -38,12 +50,14 @@ const checkIfAnyValidSeriesExist = (
// Bar chart rotation: https://ela.st/chart-rotations
export const BarChartBaseComponent = ({
data,
+ forceHiddenLegend = false,
...chartConfigs
}: {
data: ChartSeriesData[];
width: string | null | undefined;
height: string | null | undefined;
configs?: ChartSeriesConfigs | undefined;
+ forceHiddenLegend?: boolean;
}) => {
const theme = useTheme();
const timeZone = useTimeZone();
@@ -59,10 +73,10 @@ export const BarChartBaseComponent = ({
return chartConfigs.width && chartConfigs.height ? (
-
+
{data.map(series => {
const barSeriesKey = series.key;
- return checkIfAllTheDataInTheSeriesAreValid ? (
+ return checkIfAllTheDataInTheSeriesAreValid(series) ? (
= ({ barChart, configs }) => {
+const NO_LEGEND_DATA: LegendItem[] = [];
+
+export const BarChartComponent: React.FC = ({
+ barChart,
+ configs,
+ stackByField,
+}) => {
const { ref: measureRef, width, height } = useThrottledResizeObserver();
+ const legendItems: LegendItem[] = useMemo(
+ () =>
+ barChart != null && stackByField != null
+ ? barChart.map((d, i) => ({
+ color: d.color ?? i < defaultLegendColors.length ? defaultLegendColors[i] : undefined,
+ dataProviderId: escapeDataProviderId(
+ `draggable-legend-item-${uuid.v4()}-${stackByField}-${d.key}`
+ ),
+ field: stackByField,
+ value: d.key,
+ }))
+ : NO_LEGEND_DATA,
+ [barChart, stackByField]
+ );
+
const customHeight = get('customHeight', configs);
const customWidth = get('customWidth', configs);
const chartHeight = getChartHeight(customHeight, height);
const chartWidth = getChartWidth(customWidth, width);
return checkIfAnyValidSeriesExist(barChart) ? (
-
-
-
+
+
+
+
+
+
+
+
+
+
) : (
);
diff --git a/x-pack/legacy/plugins/siem/public/components/charts/common.tsx b/x-pack/legacy/plugins/siem/public/components/charts/common.tsx
index d8429cba1b4fb..c7b40c50ffde8 100644
--- a/x-pack/legacy/plugins/siem/public/components/charts/common.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/charts/common.tsx
@@ -19,8 +19,8 @@ import {
import React, { useMemo } from 'react';
import styled from 'styled-components';
+import { DEFAULT_DARK_MODE } from '../../../../../../plugins/siem/common/constants';
import { useUiSetting } from '../../lib/kibana';
-import { DEFAULT_DARK_MODE } from '../../../common/constants';
export const defaultChartHeight = '100%';
export const defaultChartWidth = '100%';
diff --git a/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.test.tsx
new file mode 100644
index 0000000000000..0da0c2bdc35f2
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.test.tsx
@@ -0,0 +1,149 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
+import { mount, ReactWrapper } from 'enzyme';
+import React from 'react';
+import { ThemeProvider } from 'styled-components';
+
+import { TestProviders } from '../../mock';
+
+import { MIN_LEGEND_HEIGHT, DraggableLegend } from './draggable_legend';
+import { LegendItem } from './draggable_legend_item';
+
+const theme = () => ({ eui: euiDarkVars, darkMode: true });
+
+const allOthersDataProviderId =
+ 'draggable-legend-item-527adabe-8e1c-4a1f-965c-2f3d65dda9e1-event_dataset-All others';
+
+const legendItems: LegendItem[] = [
+ {
+ color: '#1EA593',
+ dataProviderId: 'draggable-legend-item-3207fda7-d008-402a-86a0-8ad632081bad-event_dataset-flow',
+ field: 'event.dataset',
+ value: 'flow',
+ },
+ {
+ color: '#2B70F7',
+ dataProviderId:
+ 'draggable-legend-item-83f6c824-811d-4ec8-b373-eba2b0de6398-event_dataset-suricata_eve',
+ field: 'event.dataset',
+ value: 'suricata.eve',
+ },
+ {
+ color: '#CE0060',
+ dataProviderId:
+ 'draggable-legend-item-ec57bb8f-82cd-4e07-bd38-1d11b3f0ee5f-event_dataset-traefik_access',
+ field: 'event.dataset',
+ value: 'traefik.access',
+ },
+ {
+ color: '#38007E',
+ dataProviderId:
+ 'draggable-legend-item-25d5fcd6-87ba-46b5-893e-c655d7d504e3-event_dataset-esensor',
+ field: 'event.dataset',
+ value: 'esensor',
+ },
+ {
+ color: '#F37020',
+ dataProviderId: allOthersDataProviderId,
+ field: 'event.dataset',
+ value: 'All others',
+ },
+];
+
+describe('DraggableLegend', () => {
+ const height = 400;
+
+ // Suppress warnings about "react-beautiful-dnd"
+ /* eslint-disable no-console */
+ const originalError = console.error;
+ const originalWarn = console.warn;
+ beforeAll(() => {
+ console.warn = jest.fn();
+ console.error = jest.fn();
+ });
+ afterAll(() => {
+ console.error = originalError;
+ console.warn = originalWarn;
+ });
+
+ describe('rendering', () => {
+ let wrapper: ReactWrapper;
+
+ beforeEach(() => {
+ wrapper = mount(
+
+
+
+
+
+ );
+ });
+
+ it(`renders a container with the specified non-zero 'height'`, () => {
+ expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule(
+ 'height',
+ `${height}px`
+ );
+ });
+
+ it('scrolls when necessary', () => {
+ expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule(
+ 'overflow',
+ 'auto'
+ );
+ });
+
+ it('renders the legend items', () => {
+ legendItems.forEach(item =>
+ expect(
+ wrapper
+ .find(
+ item.dataProviderId !== allOthersDataProviderId
+ ? `[data-test-subj="legend-item-${item.dataProviderId}"]`
+ : '[data-test-subj="all-others-legend-item"]'
+ )
+ .first()
+ .text()
+ ).toEqual(item.value)
+ );
+ });
+
+ it('renders a spacer for every legend item', () => {
+ expect(wrapper.find('[data-test-subj="draggable-legend-spacer"]').hostNodes().length).toEqual(
+ legendItems.length
+ );
+ });
+ });
+
+ it('does NOT render the legend when an empty collection of legendItems is provided', () => {
+ const wrapper = mount(
+
+
+
+
+
+ );
+
+ expect(wrapper.find('[data-test-subj="draggable-legend"]').exists()).toBe(false);
+ });
+
+ it(`renders a legend with the minimum height when 'height' is zero`, () => {
+ const wrapper = mount(
+
+
+
+
+
+ );
+
+ expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule(
+ 'height',
+ `${MIN_LEGEND_HEIGHT}px`
+ );
+ });
+});
diff --git a/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.tsx b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.tsx
new file mode 100644
index 0000000000000..ef3fbb8780d15
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.tsx
@@ -0,0 +1,68 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui';
+import { rgba } from 'polished';
+import React from 'react';
+import styled from 'styled-components';
+
+import { DraggableLegendItem, LegendItem } from './draggable_legend_item';
+
+export const MIN_LEGEND_HEIGHT = 175;
+
+const DraggableLegendContainer = styled.div<{ height: number }>`
+ height: ${({ height }) => `${height}px`};
+ overflow: auto;
+ scrollbar-width: thin;
+ width: 165px;
+
+ &::-webkit-scrollbar {
+ height: ${({ theme }) => theme.eui.euiScrollBar};
+ width: ${({ theme }) => theme.eui.euiScrollBar};
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background-clip: content-box;
+ background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)};
+ border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent;
+ }
+
+ &::-webkit-scrollbar-corner,
+ &::-webkit-scrollbar-track {
+ background-color: transparent;
+ }
+`;
+
+const DraggableLegendComponent: React.FC<{
+ height: number;
+ legendItems: LegendItem[];
+}> = ({ height, legendItems }) => {
+ if (legendItems.length === 0) {
+ return null;
+ }
+
+ return (
+
+
+
+ {legendItems.map(item => (
+
+
+
+
+ ))}
+
+
+
+ );
+};
+
+DraggableLegendComponent.displayName = 'DraggableLegendComponent';
+
+export const DraggableLegend = React.memo(DraggableLegendComponent);
diff --git a/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.test.tsx
new file mode 100644
index 0000000000000..581952a8415f6
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.test.tsx
@@ -0,0 +1,143 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
+import { mount, ReactWrapper } from 'enzyme';
+import React from 'react';
+import { ThemeProvider } from 'styled-components';
+
+import { TestProviders } from '../../mock';
+
+import { DraggableLegendItem, LegendItem } from './draggable_legend_item';
+
+const theme = () => ({ eui: euiDarkVars, darkMode: true });
+
+describe('DraggableLegendItem', () => {
+ // Suppress warnings about "react-beautiful-dnd"
+ /* eslint-disable no-console */
+ const originalError = console.error;
+ const originalWarn = console.warn;
+ beforeAll(() => {
+ console.warn = jest.fn();
+ console.error = jest.fn();
+ });
+ afterAll(() => {
+ console.error = originalError;
+ console.warn = originalWarn;
+ });
+
+ describe('rendering a regular (non "All others") legend item', () => {
+ const legendItem: LegendItem = {
+ color: '#1EA593',
+ dataProviderId:
+ 'draggable-legend-item-3207fda7-d008-402a-86a0-8ad632081bad-event_dataset-flow',
+ field: 'event.dataset',
+ value: 'flow',
+ };
+
+ let wrapper: ReactWrapper;
+
+ beforeEach(() => {
+ wrapper = mount(
+
+
+
+
+
+ );
+ });
+
+ it('renders a colored circle with the expected legend item color', () => {
+ expect(
+ wrapper
+ .find('[data-test-subj="legend-color"]')
+ .first()
+ .props().color
+ ).toEqual(legendItem.color);
+ });
+
+ it('renders draggable legend item text', () => {
+ expect(
+ wrapper
+ .find(`[data-test-subj="legend-item-${legendItem.dataProviderId}"]`)
+ .first()
+ .text()
+ ).toEqual(legendItem.value);
+ });
+
+ it('does NOT render a non-draggable "All others" legend item', () => {
+ expect(wrapper.find(`[data-test-subj="all-others-legend-item"]`).exists()).toBe(false);
+ });
+ });
+
+ describe('rendering an "All others" legend item', () => {
+ const allOthersLegendItem: LegendItem = {
+ color: '#F37020',
+ dataProviderId:
+ 'draggable-legend-item-527adabe-8e1c-4a1f-965c-2f3d65dda9e1-event_dataset-All others',
+ field: 'event.dataset',
+ value: 'All others',
+ };
+
+ let wrapper: ReactWrapper;
+
+ beforeEach(() => {
+ wrapper = mount(
+
+
+
+
+
+ );
+ });
+
+ it('renders a colored circle with the expected legend item color', () => {
+ expect(
+ wrapper
+ .find('[data-test-subj="legend-color"]')
+ .first()
+ .props().color
+ ).toEqual(allOthersLegendItem.color);
+ });
+
+ it('does NOT render a draggable legend item', () => {
+ expect(
+ wrapper
+ .find(`[data-test-subj="legend-item-${allOthersLegendItem.dataProviderId}"]`)
+ .exists()
+ ).toBe(false);
+ });
+
+ it('renders NON-draggable `All others` legend item text', () => {
+ expect(
+ wrapper
+ .find(`[data-test-subj="all-others-legend-item"]`)
+ .first()
+ .text()
+ ).toEqual(allOthersLegendItem.value);
+ });
+ });
+
+ it('does NOT render a colored circle when the legend item has no color', () => {
+ const noColorLegendItem: LegendItem = {
+ // no `color` attribute for this `LegendItem`!
+ dataProviderId:
+ 'draggable-legend-item-3207fda7-d008-402a-86a0-8ad632081bad-event_dataset-flow',
+ field: 'event.dataset',
+ value: 'flow',
+ };
+
+ const wrapper = mount(
+
+
+
+
+
+ );
+
+ expect(wrapper.find('[data-test-subj="legend-color"]').exists()).toBe(false);
+ });
+});
diff --git a/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.tsx b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.tsx
new file mode 100644
index 0000000000000..cdda1733932d5
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.tsx
@@ -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;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiText } from '@elastic/eui';
+import React from 'react';
+import styled from 'styled-components';
+
+import { DefaultDraggable } from '../draggables';
+
+import * as i18n from './translation';
+
+// The "All others" legend item is not draggable
+const AllOthers = styled.span`
+ padding-left: 7px;
+`;
+
+export interface LegendItem {
+ color?: string;
+ dataProviderId: string;
+ field: string;
+ value: string;
+}
+
+const DraggableLegendItemComponent: React.FC<{
+ legendItem: LegendItem;
+}> = ({ legendItem }) => {
+ const { color, dataProviderId, field, value } = legendItem;
+
+ return (
+
+
+ {color != null && (
+
+
+
+ )}
+
+
+ {value !== i18n.ALL_OTHERS ? (
+
+ ) : (
+ <>
+ {value}
+ >
+ )}
+
+
+
+ );
+};
+
+DraggableLegendItemComponent.displayName = 'DraggableLegendItemComponent';
+
+export const DraggableLegendItem = React.memo(DraggableLegendItemComponent);
diff --git a/x-pack/legacy/plugins/siem/public/components/charts/translation.ts b/x-pack/legacy/plugins/siem/public/components/charts/translation.ts
index 341cb7782f87c..891f59fc97bd1 100644
--- a/x-pack/legacy/plugins/siem/public/components/charts/translation.ts
+++ b/x-pack/legacy/plugins/siem/public/components/charts/translation.ts
@@ -13,3 +13,7 @@ export const ALL_VALUES_ZEROS_TITLE = i18n.translate('xpack.siem.chart.dataAllVa
export const DATA_NOT_AVAILABLE_TITLE = i18n.translate('xpack.siem.chart.dataNotAvailableTitle', {
defaultMessage: 'Chart Data Not Available',
});
+
+export const ALL_OTHERS = i18n.translate('xpack.siem.chart.allOthersGroupingLabel', {
+ defaultMessage: 'All others',
+});
diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx
index 11db33fff6d72..248ae671550ef 100644
--- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx
@@ -27,6 +27,9 @@ import {
draggableIsField,
} from './helpers';
+// @ts-ignore
+window['__react-beautiful-dnd-disable-dev-warnings'] = true;
+
interface Props {
browserFields: BrowserFields;
children: React.ReactNode;
diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx
index 11891afabbf3d..cd9e1dc95ff01 100644
--- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx
@@ -7,12 +7,13 @@
import { shallow } from 'enzyme';
import React from 'react';
import { MockedProvider } from 'react-apollo/test-utils';
+import { DraggableStateSnapshot, DraggingStyle } from 'react-beautiful-dnd';
import { mockBrowserFields, mocksSource } from '../../containers/source/mock';
import { TestProviders } from '../../mock';
import { mockDataProviders } from '../timeline/data_providers/mock/mock_data_providers';
import { DragDropContextWrapper } from './drag_drop_context_wrapper';
-import { DraggableWrapper, ConditionalPortal } from './draggable_wrapper';
+import { ConditionalPortal, DraggableWrapper, getStyle } from './draggable_wrapper';
import { useMountAppended } from '../../utils/use_mount_appended';
describe('DraggableWrapper', () => {
@@ -48,6 +49,36 @@ describe('DraggableWrapper', () => {
expect(wrapper.text()).toEqual(message);
});
+
+ test('it does NOT render hover actions when the mouse is NOT over the draggable wrapper', () => {
+ const wrapper = mount(
+
+
+
+ message} />
+
+
+
+ );
+
+ expect(wrapper.find('[data-test-subj="copy-to-clipboard"]').exists()).toBe(false);
+ });
+
+ test('it renders hover actions when the mouse is over the draggable wrapper', () => {
+ const wrapper = mount(
+
+
+
+ message} />
+
+
+
+ );
+
+ wrapper.simulate('mouseenter');
+ wrapper.update();
+ expect(wrapper.find('[data-test-subj="copy-to-clipboard"]').exists()).toBe(true);
+ });
});
describe('text truncation styling', () => {
@@ -100,4 +131,36 @@ describe('ConditionalPortal', () => {
expect(props.registerProvider.mock.calls.length).toEqual(1);
});
+
+ describe('getStyle', () => {
+ const style: DraggingStyle = {
+ boxSizing: 'border-box',
+ height: 10,
+ left: 1,
+ pointerEvents: 'none',
+ position: 'fixed',
+ transition: 'none',
+ top: 123,
+ width: 50,
+ zIndex: 9999,
+ };
+
+ it('returns a style with no transitionDuration when the snapshot is not drop animating', () => {
+ const snapshot: DraggableStateSnapshot = {
+ isDragging: true,
+ isDropAnimating: false, // <-- NOT drop animating
+ };
+
+ expect(getStyle(style, snapshot)).not.toHaveProperty('transitionDuration');
+ });
+
+ it('returns a style with a transitionDuration when the snapshot is drop animating', () => {
+ const snapshot: DraggableStateSnapshot = {
+ isDragging: true,
+ isDropAnimating: true, // <-- it is drop animating
+ };
+
+ expect(getStyle(style, snapshot)).toHaveProperty('transitionDuration', '0.00000001s');
+ });
+ });
});
diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx
index 3a6a4de7984db..c7da5b5c58951 100644
--- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx
@@ -4,12 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { useCallback, useEffect, useState } from 'react';
+import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
Draggable,
DraggableProvided,
DraggableStateSnapshot,
+ DraggingStyle,
Droppable,
+ NotDraggingStyle,
} from 'react-beautiful-dnd';
import { useDispatch } from 'react-redux';
import styled from 'styled-components';
@@ -18,6 +20,9 @@ import deepEqual from 'fast-deep-equal';
import { dragAndDropActions } from '../../store/drag_and_drop';
import { DataProvider } from '../timeline/data_providers/data_provider';
import { TruncatableText } from '../truncatable_text';
+import { WithHoverActions } from '../with_hover_actions';
+
+import { DraggableWrapperHoverContent } from './draggable_wrapper_hover_content';
import { getDraggableId, getDroppableId } from './helpers';
import { ProviderContainer } from './provider_container';
@@ -67,23 +72,42 @@ type RenderFunctionProp = (
state: DraggableStateSnapshot
) => React.ReactNode;
-interface OwnProps {
+interface Props {
dataProvider: DataProvider;
inline?: boolean;
render: RenderFunctionProp;
truncate?: boolean;
+ onFilterAdded?: () => void;
}
-type Props = OwnProps;
-
/**
* Wraps a draggable component to handle registration / unregistration of the
* data provider associated with the item being dropped
*/
+export const getStyle = (
+ style: DraggingStyle | NotDraggingStyle | undefined,
+ snapshot: DraggableStateSnapshot
+) => {
+ if (!snapshot.isDropAnimating) {
+ return style;
+ }
+
+ return {
+ ...style,
+ transitionDuration: '0.00000001s', // cannot be 0, but can be a very short duration
+ };
+};
+
export const DraggableWrapper = React.memo(
- ({ dataProvider, render, truncate }) => {
+ ({ dataProvider, onFilterAdded, render, truncate }) => {
+ const [showTopN, setShowTopN] = useState(false);
+ const toggleTopN = useCallback(() => {
+ setShowTopN(!showTopN);
+ }, [setShowTopN, showTopN]);
+
const [providerRegistered, setProviderRegistered] = useState(false);
+
const dispatch = useDispatch();
const registerProvider = useCallback(() => {
@@ -105,65 +129,90 @@ export const DraggableWrapper = React.memo(
[]
);
- return (
-
-
- (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-};
-
-export const MonitorList = withUptimeGraphQL(
- MonitorListComponent,
- monitorStatesQuery
-);
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/index.ts b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/index.ts
deleted file mode 100644
index 0cb11587eee48..0000000000000
--- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-export { MonitorSSLCertificate } from './monitor_ssl_certificate';
-export { MonitorStatusBarComponent } from './monitor_status_bar';
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/search_schema.ts b/x-pack/legacy/plugins/uptime/public/components/functional/search_schema.ts
deleted file mode 100644
index bd451a9835288..0000000000000
--- a/x-pack/legacy/plugins/uptime/public/components/functional/search_schema.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-export const filterBarSearchSchema = {
- strict: true,
- fields: {
- 'monitor.id': { type: 'string' },
- 'monitor.status': { type: 'string' },
- 'monitor.ip': { type: 'string' },
- 'monitor.host': { type: 'string' },
- 'monitor.scheme': { type: 'string' },
- 'url.port': { type: 'number' },
- },
-};
diff --git a/x-pack/legacy/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx b/x-pack/legacy/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx
deleted file mode 100644
index 6839050cec7a8..0000000000000
--- a/x-pack/legacy/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { OperationVariables } from 'apollo-client';
-import { GraphQLError } from 'graphql';
-import React, { Fragment, useContext, useEffect, useState } from 'react';
-import { withApollo, WithApolloClient } from 'react-apollo';
-import { formatUptimeGraphQLErrorList } from '../../lib/helper/format_error_list';
-import { UptimeRefreshContext } from '../../contexts';
-
-export interface UptimeGraphQLQueryProps {
- loading: boolean;
- data?: T;
- errors?: GraphQLError[];
-}
-
-interface UptimeGraphQLProps {
- implementsCustomErrorState?: boolean;
- variables: OperationVariables;
-}
-
-/**
- * This HOC abstracts the task of querying our GraphQL endpoint,
- * which eliminates the need for a lot of boilerplate code in the other components.
- *
- * @type T - the expected result's type
- * @type P - any props the wrapped component will require
- * @param WrappedComponent - the consuming component
- * @param query - the graphQL query
- */
-export function withUptimeGraphQL(WrappedComponent: any, query: any) {
- type Props = UptimeGraphQLProps & WithApolloClient & P;
-
- return withApollo((props: Props) => {
- const { lastRefresh } = useContext(UptimeRefreshContext);
- const [loading, setLoading] = useState(true);
- const [data, setData] = useState(undefined);
- const [errors, setErrors] = useState(undefined);
- let updateState = (
- loadingVal: boolean,
- dataVal: T | undefined,
- errorsVal: GraphQLError[] | undefined
- ) => {
- setLoading(loadingVal);
- setData(dataVal);
- setErrors(errorsVal);
- };
- const { client, implementsCustomErrorState, variables } = props;
- const fetch = () => {
- setLoading(true);
- client
- .query({ fetchPolicy: 'network-only', query, variables })
- .then(
- (result: any) => {
- updateState(result.loading, result.data, result.errors);
- },
- (result: any) => {
- updateState(false, undefined, result.graphQLErrors);
- }
- );
- };
- useEffect(() => {
- fetch();
-
- /**
- * If the `then` handler in `fetch`'s promise is fired after
- * this component has unmounted, it will try to set state on an
- * unmounted component, which indicates a memory leak and will trigger
- * React warnings.
- *
- * We counteract this side effect by providing a cleanup function that will
- * reassign the update function to do nothing with the returned values.
- */
- return () => {
- // this component is planned to be deprecated, for the time being
- // we will want to preserve this for the reason above.
- // eslint-disable-next-line react-hooks/exhaustive-deps
- updateState = () => {};
- };
- }, [variables, lastRefresh]);
- if (!implementsCustomErrorState && errors && errors.length > 0) {
- return {formatUptimeGraphQLErrorList(errors)};
- }
- return ;
- });
-}
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_charts.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/__tests__/__snapshots__/monitor_charts.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_charts.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/__tests__/__snapshots__/monitor_charts.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/monitor_charts.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/__tests__/monitor_charts.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/monitor_charts.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/__tests__/monitor_charts.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/index.ts
new file mode 100644
index 0000000000000..cb7b27afded02
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/index.ts
@@ -0,0 +1,12 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export * from './ml';
+export * from './ping_list';
+export * from './location_map';
+export * from './monitor_status_details';
+export * from './ping_histogram';
+export * from './monitor_charts';
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_map.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_map.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_map.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_map.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_missing.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_missing.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_missing.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_missing.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_map.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_map.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_map.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_map.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_missing.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_missing.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_missing.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_missing.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_status_tags.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_status_tags.test.tsx
similarity index 97%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_status_tags.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_status_tags.test.tsx
index 2359938dbbc35..7dde38af99fc3 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_status_tags.test.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_status_tags.test.tsx
@@ -8,9 +8,8 @@ import React from 'react';
import moment from 'moment';
import { renderWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
import { MonitorLocation } from '../../../../../common/runtime_types/monitor';
-import { LocationStatusTags } from '../';
+import { LocationStatusTags } from '../index';
-// Failing: https://github.com/elastic/kibana/issues/54818
describe('LocationStatusTags component', () => {
let monitorLocations: MonitorLocation[];
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__tests__/__mocks__/mock.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/__tests__/__mocks__/mock.ts
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__tests__/__mocks__/mock.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/__tests__/__mocks__/mock.ts
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__tests__/map_config.test.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/__tests__/map_config.test.ts
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__tests__/map_config.test.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/__tests__/map_config.test.ts
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/embedded_map.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/embedded_map.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/low_poly_layer.json b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/low_poly_layer.json
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/low_poly_layer.json
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/low_poly_layer.json
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/map_config.ts
similarity index 98%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/map_config.ts
index a43edae438252..ddb52e119fa87 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/map_config.ts
@@ -5,7 +5,7 @@
*/
import lowPolyLayerFeatures from './low_poly_layer.json';
-import { LocationPoint } from './embedded_map.js';
+import { LocationPoint } from './embedded_map';
import { UptimeAppColors } from '../../../../uptime_app';
/**
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/translations.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/translations.ts
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/translations.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/translations.ts
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/index.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/index.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/index.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/index.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_map.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_map.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_missing.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_missing.tsx
similarity index 97%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_missing.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_missing.tsx
index a20889f6cc653..6ce31e4cc8243 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_missing.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_missing.tsx
@@ -16,7 +16,7 @@ import {
} from '@elastic/eui';
import styled from 'styled-components';
import { FormattedMessage } from '@kbn/i18n/react';
-import { LocationLink } from '../monitor_list/monitor_list_drawer';
+import { LocationLink } from '../../common/location_link';
const EuiPopoverRight = styled(EuiFlexItem)`
margin-left: auto;
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_status_tags.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_status_tags.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_status_tags.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_status_tags.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/license_info.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/license_info.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/confirm_delete.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/confirm_delete.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/confirm_delete.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/confirm_delete.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/license_info.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/license_info.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/license_info.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/license_info.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_flyout.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_flyout.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_flyout.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_flyout.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_integerations.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_integerations.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_integerations.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_integerations.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_job_link.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_job_link.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_job_link.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_job_link.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_manage_job.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_manage_job.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_manage_job.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_manage_job.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/confirm_delete.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/confirm_delete.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/confirm_delete.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/confirm_delete.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/index.ts
similarity index 81%
rename from x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/index.ts
index 95ced104e5188..c644c94d13878 100644
--- a/x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/index.ts
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { PingList, PingListProps } from './ping_list';
+export { ManageMLJobComponent } from './manage_ml_job';
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/license_info.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/license_info.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/license_info.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/license_info.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx
similarity index 97%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx
index ec3e8bb2b9f68..46ac24e9455e5 100644
--- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx
@@ -13,7 +13,7 @@ import { UptimeSettingsContext } from '../../../contexts';
import * as labels from './translations';
import { getMLJobLinkHref } from './ml_job_link';
import { useGetUrlParams } from '../../../hooks';
-import { useMonitorId } from '../../../hooks/use_monitor';
+import { useMonitorId } from '../../../hooks';
interface Props {
hasMLJob: boolean;
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout_container.tsx
similarity index 98%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout_container.tsx
index a13de192cc443..c3e8579ca4837 100644
--- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout_container.tsx
@@ -25,7 +25,7 @@ import { ML_JOB_ID } from '../../../../common/constants';
import { UptimeRefreshContext, UptimeSettingsContext } from '../../../contexts';
import { useGetUrlParams } from '../../../hooks';
import { getDynamicSettings } from '../../../state/actions/dynamic_settings';
-import { useMonitorId } from '../../../hooks/use_monitor';
+import { useMonitorId } from '../../../hooks';
interface Props {
onClose: () => void;
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx
similarity index 98%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx
index e053ca733cb8c..4963a901f0ecc 100644
--- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx
@@ -21,7 +21,7 @@ import * as labels from './translations';
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';
import { ManageMLJobComponent } from './manage_ml_job';
import { JobStat } from '../../../../../../../plugins/ml/common/types/data_recognizer';
-import { useMonitorId } from '../../../hooks/use_monitor';
+import { useMonitorId } from '../../../hooks';
export const MLIntegrationComponent = () => {
const [isMlFlyoutOpen, setIsMlFlyoutOpen] = useState(false);
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_job_link.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_job_link.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_job_link.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_job_link.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/translations.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/translations.tsx
similarity index 95%
rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/translations.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/translations.tsx
index 32374674771e8..bcc3fca770652 100644
--- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/translations.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/translations.tsx
@@ -96,13 +96,6 @@ export const MANAGE_ANOMALY_DETECTION = i18n.translate(
}
);
-export const VIEW_EXISTING_JOB = i18n.translate(
- 'xpack.uptime.ml.enableAnomalyDetectionPanel.callout.jobExistsDescription.viewJobLinkText',
- {
- defaultMessage: 'View existing job',
- }
-);
-
export const ML_MANAGEMENT_PAGE = i18n.translate(
'xpack.uptime.ml.enableAnomalyDetectionPanel.manageMLJobDescription.mlJobsPageLinkText',
{
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_charts.tsx
similarity index 68%
rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_charts.tsx
index c5edd0fd85977..f9cc1aa52b902 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_charts.tsx
@@ -6,7 +6,8 @@
import React from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
-import { PingHistogram, DurationChart } from '../connected';
+import { PingHistogram } from './ping_histogram/ping_histogram_container';
+import { MonitorDuration } from './monitor_duration/monitor_duration_container';
interface MonitorChartsProps {
monitorId: string;
@@ -16,10 +17,10 @@ export const MonitorCharts = ({ monitorId }: MonitorChartsProps) => {
return (
-
+
-
+
);
diff --git a/x-pack/plugins/uptime/server/graphql/monitor_states/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/index.ts
similarity index 65%
rename from x-pack/plugins/uptime/server/graphql/monitor_states/index.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/index.ts
index fb0893dbc4dbf..aa3230a3f9bc0 100644
--- a/x-pack/plugins/uptime/server/graphql/monitor_states/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/index.ts
@@ -4,5 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { createMonitorStatesResolvers } from './resolvers';
-export { monitorStatesSchema } from './schema.gql';
+export { MonitorDuration } from './monitor_duration_container';
+export { MonitorDurationComponent } from './monitor_duration';
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration.tsx
new file mode 100644
index 0000000000000..af1c8dbdc49e3
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration.tsx
@@ -0,0 +1,66 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui';
+import { LocationDurationLine } from '../../../../common/types';
+import { MLIntegrationComponent } from '../ml/ml_integeration';
+import { AnomalyRecords } from '../../../state/actions';
+import { DurationChartComponent } from '../../common/charts';
+
+interface DurationChartProps {
+ loading: boolean;
+ hasMLJob: boolean;
+ anomalies: AnomalyRecords | null;
+ locationDurationLines: LocationDurationLine[];
+}
+
+/**
+ * This chart is intended to visualize monitor duration performance over time to
+ * the users in a helpful way. Its x-axis is based on a timeseries, the y-axis is in
+ * milliseconds.
+ * @param props The props required for this component to render properly
+ */
+export const MonitorDurationComponent = ({
+ locationDurationLines,
+ anomalies,
+ loading,
+ hasMLJob,
+}: DurationChartProps) => {
+ return (
+
+
+
+
+
+ {hasMLJob ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx
similarity index 91%
rename from x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx
index 40480905350af..7e39b977f1271 100644
--- a/x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx
@@ -12,7 +12,6 @@ import {
getMLCapabilitiesAction,
getMonitorDurationAction,
} from '../../../state/actions';
-import { DurationChartComponent } from '../../functional/charts';
import {
anomaliesSelector,
hasMLFeatureAvailable,
@@ -22,12 +21,10 @@ import {
import { UptimeRefreshContext } from '../../../contexts';
import { getMLJobId } from '../../../state/api/ml_anomaly';
import { JobStat } from '../../../../../../../plugins/ml/common/types/data_recognizer';
+import { MonitorDurationComponent } from './monitor_duration';
+import { MonitorIdParam } from '../../../../common/types';
-interface Props {
- monitorId: string;
-}
-
-export const DurationChart: React.FC = ({ monitorId }: Props) => {
+export const MonitorDuration: React.FC = ({ monitorId }) => {
const {
dateRangeStart,
dateRangeEnd,
@@ -75,7 +72,7 @@ export const DurationChart: React.FC = ({ monitorId }: Props) => {
}, [dispatch]);
return (
- {
let monitorLocations: MonitorLocation[];
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/index.ts
similarity index 64%
rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/index.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/index.ts
index 385788cc825a0..e95f14472e9e8 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/index.ts
@@ -5,5 +5,8 @@
*/
export { MonitorStatusBarComponent } from './monitor_status_bar';
-export { MonitorStatusDetailsComponent } from './monitor_status_details';
+export { MonitorStatusDetailsComponent } from './status_details';
export { StatusByLocations } from './monitor_status_bar/status_by_location';
+
+export { MonitorStatusDetails } from './status_details_container';
+export { MonitorStatusBar } from './monitor_status_bar/status_bar_container';
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/index.ts
new file mode 100644
index 0000000000000..3c861412a39e9
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/index.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { MonitorSSLCertificate } from './ssl_certificate';
+export { MonitorStatusBarComponent } from './status_bar';
+export { MonitorStatusBar } from './status_bar_container';
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/ssl_certificate.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/ssl_certificate.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar.tsx
similarity index 95%
rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar.tsx
index ac3cedc517995..36159dc29eccd 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar.tsx
@@ -14,7 +14,7 @@ import {
EuiFlexGroup,
EuiFlexItem,
} from '@elastic/eui';
-import { MonitorSSLCertificate } from './monitor_ssl_certificate';
+import { MonitorSSLCertificate } from './ssl_certificate';
import * as labels from './translations';
import { StatusByLocations } from './status_by_location';
import { Ping } from '../../../../../common/runtime_types';
@@ -22,7 +22,7 @@ import { MonitorLocations } from '../../../../../common/runtime_types';
interface MonitorStatusBarProps {
monitorId: string;
- monitorStatus: Ping;
+ monitorStatus: Ping | null;
monitorLocations: MonitorLocations;
}
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar_container.tsx
new file mode 100644
index 0000000000000..9562295437515
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar_container.tsx
@@ -0,0 +1,40 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { monitorLocationsSelector, monitorStatusSelector } from '../../../../state/selectors';
+import { MonitorStatusBarComponent } from './index';
+import { getMonitorStatusAction } from '../../../../state/actions';
+import { useGetUrlParams } from '../../../../hooks';
+import { UptimeRefreshContext } from '../../../../contexts';
+import { MonitorIdParam } from '../../../../../common/types';
+import { AppState } from '../../../../state';
+
+export const MonitorStatusBar: React.FC = ({ monitorId }) => {
+ const { lastRefresh } = useContext(UptimeRefreshContext);
+
+ const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = useGetUrlParams();
+
+ const dispatch = useDispatch();
+
+ const monitorStatus = useSelector(monitorStatusSelector);
+ const monitorLocations = useSelector((state: AppState) =>
+ monitorLocationsSelector(state, monitorId)
+ );
+
+ useEffect(() => {
+ dispatch(getMonitorStatusAction({ dateStart, dateEnd, monitorId }));
+ }, [monitorId, dateStart, dateEnd, lastRefresh, dispatch]);
+
+ return (
+
+ );
+};
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/status_by_location.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_by_location.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/status_by_location.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_by_location.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/translations.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/translations.ts
similarity index 99%
rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/translations.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/translations.ts
index 1c2844f4f6ccf..f60a1ceeaafb8 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/translations.ts
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/translations.ts
@@ -3,6 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
+
import { i18n } from '@kbn/i18n';
export const healthStatusMessageAriaLabel = i18n.translate(
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx
similarity index 97%
rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx
index 7dea73da7bba0..ebd16b05ecb4a 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx
@@ -10,7 +10,7 @@ import styled from 'styled-components';
import { LocationMap } from '../location_map';
import { UptimeRefreshContext } from '../../../contexts';
import { MonitorLocations } from '../../../../common/runtime_types';
-import { MonitorStatusBar } from '../../connected';
+import { MonitorStatusBar } from './monitor_status_bar';
interface MonitorStatusDetailsProps {
monitorId: string;
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details_container.tsx
new file mode 100644
index 0000000000000..251f3562f9d1a
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details_container.tsx
@@ -0,0 +1,34 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { useGetUrlParams } from '../../../hooks';
+import { monitorLocationsSelector } from '../../../state/selectors';
+import { getMonitorLocationsAction } from '../../../state/actions/monitor';
+import { MonitorStatusDetailsComponent } from './index';
+import { UptimeRefreshContext } from '../../../contexts';
+import { AppState } from '../../../state';
+import { MonitorIdParam } from '../../../../common/types';
+
+export const MonitorStatusDetails: React.FC = ({ monitorId }) => {
+ const { lastRefresh } = useContext(UptimeRefreshContext);
+
+ const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = useGetUrlParams();
+
+ const dispatch = useDispatch();
+ const monitorLocations = useSelector((state: AppState) =>
+ monitorLocationsSelector(state, monitorId)
+ );
+
+ useEffect(() => {
+ dispatch(getMonitorLocationsAction({ dateStart, dateEnd, monitorId }));
+ }, [monitorId, dateStart, dateEnd, lastRefresh, dispatch]);
+
+ return (
+
+ );
+};
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/translations.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/translations.ts
similarity index 99%
rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/translations.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/translations.ts
index 1c2844f4f6ccf..f60a1ceeaafb8 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/translations.ts
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/translations.ts
@@ -3,6 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
+
import { i18n } from '@kbn/i18n';
export const healthStatusMessageAriaLabel = i18n.translate(
diff --git a/x-pack/plugins/uptime/server/graphql/pings/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/index.ts
similarity index 80%
rename from x-pack/plugins/uptime/server/graphql/pings/index.ts
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/index.ts
index 100ce29c398ec..c980b41167d0c 100644
--- a/x-pack/plugins/uptime/server/graphql/pings/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/index.ts
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { pingsSchema } from './schema.gql';
+export { PingHistogram } from './ping_histogram_container';
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx
new file mode 100644
index 0000000000000..c0e17966f5b9f
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx
@@ -0,0 +1,48 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { PingHistogramComponent } from '../../common/charts';
+import { getPingHistogram } from '../../../state/actions';
+import { selectPingHistogram } from '../../../state/selectors';
+import { useGetUrlParams } from '../../../hooks';
+import { useMonitorId } from '../../../hooks';
+import { ResponsiveWrapperProps, withResponsiveWrapper } from '../../common/higher_order';
+
+interface Props {
+ height: string;
+}
+
+const Container: React.FC = ({ height }) => {
+ const {
+ statusFilter,
+ absoluteDateRangeStart,
+ absoluteDateRangeEnd,
+ dateRangeStart: dateStart,
+ dateRangeEnd: dateEnd,
+ } = useGetUrlParams();
+
+ const dispatch = useDispatch();
+ const monitorId = useMonitorId();
+
+ const { loading, data, esKuery, lastRefresh } = useSelector(selectPingHistogram);
+
+ useEffect(() => {
+ dispatch(getPingHistogram({ monitorId, dateStart, dateEnd, statusFilter, filters: esKuery }));
+ }, [dateStart, dateEnd, monitorId, statusFilter, lastRefresh, esKuery, dispatch]);
+ return (
+
+ );
+};
+
+export const PingHistogram = withResponsiveWrapper(Container);
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/doc_link_body.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/doc_link_body.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/doc_link_body.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/doc_link_body.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/expanded_row.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/expanded_row.test.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/ping_list.test.tsx
similarity index 99%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/ping_list.test.tsx
index ec256a886aa16..cb8413ba08a81 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/ping_list.test.tsx
@@ -7,8 +7,8 @@
import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { PingListComponent, toggleDetails } from '../ping_list';
-import { ExpandedRowMap } from '../../monitor_list/types';
import { Ping, PingsResponse } from '../../../../../common/runtime_types';
+import { ExpandedRowMap } from '../../../overview/monitor_list/types';
describe('PingList component', () => {
let response: PingsResponse;
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/doc_link_body.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/doc_link_body.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/doc_link_body.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/doc_link_body.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/expanded_row.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/expanded_row.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/index.tsx
similarity index 85%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/index.tsx
index 808f3f90ef015..7fc19bbc9622b 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/index.tsx
@@ -5,3 +5,4 @@
*/
export { PingListComponent } from './ping_list';
+export { PingList } from './ping_list_container';
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/location_name.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/location_name.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/location_name.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/location_name.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx
similarity index 98%
rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx
index 934dfd961f9e0..5dfc1c0647430 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx
@@ -26,9 +26,9 @@ import styled from 'styled-components';
import { Ping, GetPingsParams, DateRange } from '../../../../common/runtime_types';
import { convertMicrosecondsToMilliseconds as microsToMillis } from '../../../lib/helper';
import { LocationName } from './location_name';
-import { Pagination } from './../monitor_list';
+import { Pagination } from '../../overview/monitor_list';
import { PingListExpandedRowComponent } from './expanded_row';
-import { PingListProps } from '../../connected/pings';
+import { PingListProps } from './ping_list_container';
export const AllLocationOption = {
'data-test-subj': 'xpack.uptime.pingList.locationOptions.all',
@@ -139,7 +139,7 @@ export const PingListComponent = (props: Props) => {
}))
);
- const hasStatus: boolean = pings.reduce(
+ const hasStatus = pings.reduce(
(hasHttpStatus: boolean, currentPing) =>
hasHttpStatus || !!currentPing.http?.response?.status_code,
false
diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list_container.tsx
similarity index 96%
rename from x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx
rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list_container.tsx
index 5b32a623495f1..3c3caab365e3a 100644
--- a/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list_container.tsx
@@ -10,7 +10,7 @@ import { selectPingList } from '../../../state/selectors';
import { getPings } from '../../../state/actions';
import { GetPingsParams } from '../../../../common/runtime_types';
import { UptimeSettingsContext } from '../../../contexts';
-import { PingListComponent } from '../../functional';
+import { PingListComponent } from './index';
export interface PingListProps {
monitorId: string;
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/overview_page_parsing_error_callout.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/parsing_error_callout.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/overview_page_parsing_error_callout.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/parsing_error_callout.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/snapshot.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/snapshot.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot_heading.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/snapshot_heading.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot_heading.test.tsx.snap
rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/snapshot_heading.test.tsx.snap
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/overview_page_parsing_error_callout.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/parsing_error_callout.test.tsx
similarity index 76%
rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/overview_page_parsing_error_callout.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/parsing_error_callout.test.tsx
index fbe55dfedc2fc..01204c33b79d5 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/overview_page_parsing_error_callout.test.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/parsing_error_callout.test.tsx
@@ -6,13 +6,13 @@
import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
-import { OverviewPageParsingErrorCallout } from '../overview_page_parsing_error_callout';
+import { ParsingErrorCallout } from '../parsing_error_callout';
describe('OverviewPageParsingErrorCallout', () => {
it('renders without errors when a valid error is provided', () => {
expect(
shallowWithIntl(
-
)
@@ -21,6 +21,6 @@ describe('OverviewPageParsingErrorCallout', () => {
it('renders without errors when an error with no message is provided', () => {
const error: any = {};
- expect(shallowWithIntl()).toMatchSnapshot();
+ expect(shallowWithIntl()).toMatchSnapshot();
});
});
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot.test.tsx
similarity index 92%
rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot.test.tsx
index 214b0394369f7..cfcab673dcb35 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot.test.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot.test.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { Snapshot } from '../../../../common/runtime_types';
-import { SnapshotComponent } from '../snapshot';
+import { SnapshotComponent } from '../snapshot/snapshot';
describe('Snapshot component', () => {
const snapshot: Snapshot = {
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot_heading.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot_heading.test.tsx
similarity index 93%
rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot_heading.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot_heading.test.tsx
index 70d082b26d653..805c116ef538a 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot_heading.test.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot_heading.test.tsx
@@ -6,7 +6,7 @@
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import React from 'react';
-import { SnapshotHeading } from '../snapshot_heading';
+import { SnapshotHeading } from '../snapshot/snapshot_heading';
describe('SnapshotHeading', () => {
it('renders custom heading for no down monitors', () => {
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/__tests__/alert_monitor_status.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/__tests__/alert_monitor_status.test.tsx
similarity index 98%
rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/__tests__/alert_monitor_status.test.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/__tests__/alert_monitor_status.test.tsx
index af8d17d1fc242..8f33b6f652b9d 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/__tests__/alert_monitor_status.test.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/__tests__/alert_monitor_status.test.tsx
@@ -14,8 +14,8 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
describe('alert monitor status component', () => {
describe('handleAlertFieldNumberChange', () => {
- let mockSetIsInvalid: jest.Mock;
- let mockSetFieldValue: jest.Mock;
+ let mockSetIsInvalid: jest.Mock;
+ let mockSetFieldValue: jest.Mock;
beforeEach(() => {
mockSetIsInvalid = jest.fn();
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/alert_monitor_status.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alert_monitor_status.tsx
similarity index 99%
rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/alert_monitor_status.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alert_monitor_status.tsx
index b86e85f35b17d..83892bf23dced 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/alert_monitor_status.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alert_monitor_status.tsx
@@ -19,7 +19,7 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { DataPublicPluginSetup } from 'src/plugins/data/public';
-import { KueryBar } from '../../connected/kuerybar/kuery_bar_container';
+import { KueryBar } from '..';
interface AlertFieldNumberProps {
'aria-label': string;
diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/alert_monitor_status.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx
similarity index 86%
rename from x-pack/legacy/plugins/uptime/public/components/connected/alerts/alert_monitor_status.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx
index 1529ab6db8875..9dd27db0be607 100644
--- a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/alert_monitor_status.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx
@@ -7,8 +7,8 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { DataPublicPluginSetup } from 'src/plugins/data/public';
-import { selectMonitorStatusAlert } from '../../../state/selectors';
-import { AlertMonitorStatusComponent } from '../../functional/alerts/alert_monitor_status';
+import { selectMonitorStatusAlert } from '../../../../state/selectors';
+import { AlertMonitorStatusComponent } from '../index';
interface Props {
autocomplete: DataPublicPluginSetup['autocomplete'];
diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/connected/alerts/index.ts
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/index.ts
diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/toggle_alert_flyout_button.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx
similarity index 80%
rename from x-pack/legacy/plugins/uptime/public/components/connected/alerts/toggle_alert_flyout_button.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx
index 43b0be45365a1..45ba72d76fba6 100644
--- a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/toggle_alert_flyout_button.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx
@@ -6,8 +6,8 @@
import React from 'react';
import { useDispatch } from 'react-redux';
-import { ToggleAlertFlyoutButtonComponent } from '../../functional';
-import { setAlertFlyoutVisible } from '../../../state/actions';
+import { setAlertFlyoutVisible } from '../../../../state/actions';
+import { ToggleAlertFlyoutButtonComponent } from '../index';
export const ToggleAlertFlyoutButton = () => {
const dispatch = useDispatch();
diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/uptime_alerts_flyout_wrapper.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/uptime_alerts_flyout_wrapper.tsx
similarity index 83%
rename from x-pack/legacy/plugins/uptime/public/components/connected/alerts/uptime_alerts_flyout_wrapper.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/uptime_alerts_flyout_wrapper.tsx
index a49468ad3dd06..7bfd44a762455 100644
--- a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/uptime_alerts_flyout_wrapper.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/uptime_alerts_flyout_wrapper.tsx
@@ -6,9 +6,9 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
-import { UptimeAlertsFlyoutWrapperComponent } from '../../functional';
-import { setAlertFlyoutVisible } from '../../../state/actions';
-import { selectAlertFlyoutVisibility } from '../../../state/selectors';
+import { setAlertFlyoutVisible } from '../../../../state/actions';
+import { selectAlertFlyoutVisibility } from '../../../../state/selectors';
+import { UptimeAlertsFlyoutWrapperComponent } from '../index';
interface Props {
alertTypeId?: string;
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/index.ts
similarity index 93%
rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/index.ts
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/index.ts
index 275333b60c5ee..5ca0f4c3fe8a7 100644
--- a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/index.ts
@@ -8,3 +8,4 @@ export { AlertMonitorStatusComponent } from './alert_monitor_status';
export { ToggleAlertFlyoutButtonComponent } from './toggle_alert_flyout_button';
export { UptimeAlertsContextProvider } from './uptime_alerts_context_provider';
export { UptimeAlertsFlyoutWrapperComponent } from './uptime_alerts_flyout_wrapper';
+export * from './alerts_containers';
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/toggle_alert_flyout_button.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/toggle_alert_flyout_button.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/uptime_alerts_context_provider.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/uptime_alerts_context_provider.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/uptime_alerts_context_provider.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/uptime_alerts_context_provider.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/uptime_alerts_flyout_wrapper.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/uptime_alerts_flyout_wrapper.tsx
similarity index 100%
rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/uptime_alerts_flyout_wrapper.tsx
rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/uptime_alerts_flyout_wrapper.tsx
diff --git a/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap
new file mode 100644
index 0000000000000..25ac5a1f0974e
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap
@@ -0,0 +1,92 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DataOrIndexMissing component renders headingMessage 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ body={
+
+
+
+
+
+
+
+
+ }
+ iconType="logoUptime"
+ title={
+
+
+
+ heartbeat-*
+ ,
+ }
+ }
+ />
+
+
+ }
+ />
+
+
+
+`;
diff --git a/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap
new file mode 100644
index 0000000000000..d0e7af24e1c1b
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap
@@ -0,0 +1,1627 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`EmptyState component does not render empty state with appropriate base path and no docs 1`] = `
+
+
+ ,
+ }
+ }
+ />
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ body={
+
+
+
+
+
+
+
+
+ }
+ iconType="logoUptime"
+ title={
+
+
+ ,
+ }
+ }
+ />
+
+
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+ ,
+ }
+ }
+ >
+ No uptime data found in index
+
+
+
+
+
+
+
+
+
+
+
+
+ If you have not setup heartbeat yet, you can setup heartbeat to start monitoring your services.
+
+
+
+
+ If you have setup heartbeat and confirmed data is being sent to Elasticsearch, update your index pattern settings and insure they are aligned with your Heartbeat config.
+
+
+
+
+
+
+`;
+
+exports[`EmptyState component notifies when index does not exist 1`] = `
+
+
+ ,
+ }
+ }
+ />
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ body={
+
+
+
+
+
+
+
+
+ }
+ iconType="logoUptime"
+ title={
+
+
+ ,
+ }
+ }
+ />
+
+
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+ ,
+ }
+ }
+ >
+ No indices found matching pattern
+
+
+
+
+
+
+
+
+
+
+
+
+ If you have not setup heartbeat yet, you can setup heartbeat to start monitoring your services.
+
+
+
+
+ If you have setup heartbeat and confirmed data is being sent to Elasticsearch, update your index pattern settings and insure they are aligned with your Heartbeat config.
+
+