diff --git a/docs/api/dashboard/export-dashboard.asciidoc b/docs/api/dashboard/export-dashboard.asciidoc
index 7858b69d44c79..36c551dee84fc 100644
--- a/docs/api/dashboard/export-dashboard.asciidoc
+++ b/docs/api/dashboard/export-dashboard.asciidoc
@@ -9,7 +9,7 @@ experimental[] Export dashboards and corresponding saved objects.
[[dashboard-api-export-request]]
==== Request
-`GET /api/kibana/dashboards/export`
+`GET :/api/kibana/dashboards/export`
[[dashboard-api-export-params]]
==== Query parameters
@@ -20,9 +20,9 @@ experimental[] Export dashboards and corresponding saved objects.
[[dashboard-api-export-response-body]]
==== Response body
-`objects`::
+`objects`::
(array) A top level property that includes the saved objects. The order of the objects is not guaranteed. Use the exact response body as the request body for the corresponding <>.
-
+
[[dashboard-api-export-codes]]
==== Response code
@@ -33,10 +33,10 @@ experimental[] Export dashboards and corresponding saved objects.
[[dashboard-api-export-example]]
==== Example
-[source,js]
+[source,sh]
--------------------------------------------------
-GET api/kibana/dashboards/export?dashboard=942dcef0-b2cd-11e8-ad8e-85441f0c2e5c <1>
+$ curl -X GET "localhost:5601/api/kibana/dashboards/export?dashboard=942dcef0-b2cd-11e8-ad8e-85441f0c2e5c" <1>
--------------------------------------------------
// KIBANA
-<1> The dashboard ID is `942dcef0-b2cd-11e8-ad8e-85441f0c2e5c`.
\ No newline at end of file
+<1> The dashboard ID is `942dcef0-b2cd-11e8-ad8e-85441f0c2e5c`.
diff --git a/docs/api/dashboard/import-dashboard.asciidoc b/docs/api/dashboard/import-dashboard.asciidoc
index 14817719ec7ee..320859f78c617 100644
--- a/docs/api/dashboard/import-dashboard.asciidoc
+++ b/docs/api/dashboard/import-dashboard.asciidoc
@@ -9,7 +9,7 @@ experimental[] Import dashboards and corresponding saved objects.
[[dashboard-api-import-request]]
==== Request
-`POST /api/kibana/dashboards/import`
+`POST :/api/kibana/dashboards/import`
[[dashboard-api-import-params]]
==== Query parameters
@@ -40,9 +40,9 @@ Use the complete response body from the <:/api/features`
[float]
[[features-api-get-codes]]
@@ -23,7 +23,7 @@ experimental[] Retrieves all {kib} features. Features are used by spaces and sec
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"id": "discover",
diff --git a/docs/api/logstash-configuration-management.asciidoc b/docs/api/logstash-configuration-management.asciidoc
index fbb45095c214b..621b6c61dad8a 100644
--- a/docs/api/logstash-configuration-management.asciidoc
+++ b/docs/api/logstash-configuration-management.asciidoc
@@ -2,9 +2,9 @@
[[logstash-configuration-management-api]]
== Logstash configuration management APIs
-Programmatically integrate with the Logstash configuration management feature.
+Programmatically integrate with Logstash configuration management.
-WARNING: Do not directly access the `.logstash` index. The structure of the `.logstash` index is subject to change, which could cause your integration to break. Instead, use the Logstash configuration management APIs.
+WARNING: Do not directly access the `.logstash` index. The structure of the `.logstash` index is subject to change, which could cause your integration to break. Instead, use the Logstash configuration management APIs.
The following Logstash configuration management APIs are available:
@@ -20,5 +20,3 @@ include::logstash-configuration-management/delete-pipeline.asciidoc[]
include::logstash-configuration-management/list-pipeline.asciidoc[]
include::logstash-configuration-management/create-logstash.asciidoc[]
include::logstash-configuration-management/retrieve-pipeline.asciidoc[]
-
-
diff --git a/docs/api/logstash-configuration-management/create-logstash.asciidoc b/docs/api/logstash-configuration-management/create-logstash.asciidoc
index 38e0ee12a0ebf..d6ad27fe44603 100644
--- a/docs/api/logstash-configuration-management/create-logstash.asciidoc
+++ b/docs/api/logstash-configuration-management/create-logstash.asciidoc
@@ -9,7 +9,7 @@ experimental[] Create a centrally-managed Logstash pipeline, or update an existi
[[logstash-configuration-management-api-create-request]]
==== Request
-`PUT /api/logstash/pipeline/`
+`PUT :/api/logstash/pipeline/`
[[logstash-configuration-management-api-create-params]]
==== Path parameters
@@ -39,9 +39,9 @@ experimental[] Create a centrally-managed Logstash pipeline, or update an existi
[[logstash-configuration-management-api-create-example]]
==== Example
-[source,js]
+[source,sh]
--------------------------------------------------
-PUT api/logstash/pipeline/hello-world
+$ curl -X PUT "localhost:5601/api/logstash/pipeline/hello-world"
{
"pipeline": "input { stdin {} } output { stdout {} }",
"settings": {
diff --git a/docs/api/logstash-configuration-management/delete-pipeline.asciidoc b/docs/api/logstash-configuration-management/delete-pipeline.asciidoc
index 15d44034b46fe..e982619ee17f4 100644
--- a/docs/api/logstash-configuration-management/delete-pipeline.asciidoc
+++ b/docs/api/logstash-configuration-management/delete-pipeline.asciidoc
@@ -9,7 +9,7 @@ experimental[] Delete a centrally-managed Logstash pipeline.
[[logstash-configuration-management-api-delete-request]]
==== Request
-`DELETE /api/logstash/pipeline/`
+`DELETE :/api/logstash/pipeline/`
[[logstash-configuration-management-api-delete-params]]
==== Path parameters
@@ -26,9 +26,8 @@ experimental[] Delete a centrally-managed Logstash pipeline.
[[logstash-configuration-management-api-delete-example]]
==== Example
-[source,js]
+[source,sh]
--------------------------------------------------
-DELETE api/logstash/pipeline/hello-world
+$ curl -X DELETE "localhost:5601/api/logstash/pipeline/hello-world"
--------------------------------------------------
// KIBANA
-
diff --git a/docs/api/logstash-configuration-management/list-pipeline.asciidoc b/docs/api/logstash-configuration-management/list-pipeline.asciidoc
index 7140c35d89853..d875ea3d95b78 100644
--- a/docs/api/logstash-configuration-management/list-pipeline.asciidoc
+++ b/docs/api/logstash-configuration-management/list-pipeline.asciidoc
@@ -9,14 +9,14 @@ experimental[] List all centrally-managed Logstash pipelines.
[[logstash-configuration-management-api-list-request]]
==== Request
-`GET /api/logstash/pipelines`
+`GET :/api/logstash/pipelines`
[[logstash-configuration-management-api-list-example]]
==== Example
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"pipelines": [
@@ -35,4 +35,4 @@ The API returns the following:
}
--------------------------------------------------
-<1> The `username` property appears when security is enabled, and depends on when the pipeline was created or last updated.
\ No newline at end of file
+<1> The `username` property appears when security is enabled, and depends on when the pipeline was created or last updated.
diff --git a/docs/api/logstash-configuration-management/retrieve-pipeline.asciidoc b/docs/api/logstash-configuration-management/retrieve-pipeline.asciidoc
index 93a1ec3aa1da5..1eb380b71c62a 100644
--- a/docs/api/logstash-configuration-management/retrieve-pipeline.asciidoc
+++ b/docs/api/logstash-configuration-management/retrieve-pipeline.asciidoc
@@ -9,20 +9,20 @@ experimental[] Retrieve a centrally-managed Logstash pipeline.
[[logstash-configuration-management-api-retrieve-request]]
==== Request
-`GET /api/logstash/pipeline/`
+`GET :/api/logstash/pipeline/`
[[logstash-configuration-management-api-retrieve-path-params]]
==== Path parameters
`id`::
(Required, string) The pipeline ID.
-
+
[[logstash-configuration-management-api-retrieve-example]]
==== Example
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"id": "hello-world",
@@ -33,4 +33,4 @@ The API returns the following:
"queue.type": "persistent"
}
}
---------------------------------------------------
\ No newline at end of file
+--------------------------------------------------
diff --git a/docs/api/role-management.asciidoc b/docs/api/role-management.asciidoc
index 482d1a9b3cdd3..4c4620a23943a 100644
--- a/docs/api/role-management.asciidoc
+++ b/docs/api/role-management.asciidoc
@@ -2,9 +2,9 @@
[[role-management-api]]
== {kib} role management APIs
-Manage the roles that grant <>.
+Manage the roles that grant <>.
-WARNING: Do not use the {ref}/security-api.html#security-role-apis[{es} role management APIs] to manage {kib} roles.
+WARNING: Do not use the {ref}/security-api.html#security-role-apis[{es} role management APIs] to manage {kib} roles.
The following {kib} role management APIs are available:
diff --git a/docs/api/role-management/delete.asciidoc b/docs/api/role-management/delete.asciidoc
index acf2e4a3e3f1f..530e1e252ef8f 100644
--- a/docs/api/role-management/delete.asciidoc
+++ b/docs/api/role-management/delete.asciidoc
@@ -4,26 +4,23 @@
Delete role
++++
-Delete a {kib} role.
-
-experimental["The underlying mechanism of enforcing role-based access control is stable, but the APIs for managing the roles are experimental."]
+experimental[] Delete a {kib} role.
[[role-management-api-delete-prereqs]]
-==== Prerequisite
+==== Prerequisite
To use the delete role API, you must have the `manage_security` cluster privilege.
[[role-management-api-delete-request-body]]
==== Request
-`DELETE /api/security/role/my_admin_role`
+`DELETE :/api/security/role/my_admin_role`
[[role-management-api-delete-response-codes]]
==== Response codes
`204`::
Indicates a successful call.
-
+
`404`::
- Indicates an unsuccessful call.
-
\ No newline at end of file
+ Indicates an unsuccessful call.
diff --git a/docs/api/role-management/get-all.asciidoc b/docs/api/role-management/get-all.asciidoc
index 4a3dbd7734d3a..888bf0c8a137c 100644
--- a/docs/api/role-management/get-all.asciidoc
+++ b/docs/api/role-management/get-all.asciidoc
@@ -4,32 +4,30 @@
Get all roles
++++
-Retrieve all {kib} roles.
-
-experimental["The underlying mechanism of enforcing role-based access control is stable, but the APIs for managing the roles are experimental."]
+experimental[] Retrieve all {kib} roles.
[[role-management-api-get-prereqs]]
-==== Prerequisite
+==== Prerequisite
To use the get role API, you must have the `manage_security` cluster privilege.
[[role-management-api-retrieve-all-request-body]]
==== Request
-`GET /api/security/role`
+`GET :/api/security/role`
[[role-management-api-retrieve-all-response-codes]]
==== Response code
-`200`::
+`200`::
Indicates a successful call.
-
+
[[role-management-api-retrieve-all-example]]
==== Example
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
[
{
@@ -77,4 +75,4 @@ The API returns the following:
"kibana": [ ]
}
]
---------------------------------------------------
\ No newline at end of file
+--------------------------------------------------
diff --git a/docs/api/role-management/get.asciidoc b/docs/api/role-management/get.asciidoc
index 44423b01abe5b..d1e9d1e6afa83 100644
--- a/docs/api/role-management/get.asciidoc
+++ b/docs/api/role-management/get.asciidoc
@@ -4,32 +4,30 @@
Get specific role
++++
-Retrieve a specific role.
-
-experimental["The underlying mechanism of enforcing role-based access control is stable, but the APIs for managing the roles are experimental."]
+experimental[] Retrieve a specific role.
[[role-management-specific-api-get-prereqs]]
-==== Prerequisite
+==== Prerequisite
To use the get specific role API, you must have the `manage_security` cluster privilege.
[[role-management-specific-api-retrieve-all-request-body]]
===== Request
-`GET /api/security/role/my_restricted_kibana_role`
+`GET :/api/security/role/my_restricted_kibana_role`
[[role-management-specific-api-retrieve-all-response-codes]]
==== Response code
-`200`::
+`200`::
Indicates a successful call.
-
+
[[role-management-specific-api-retrieve-all-example]]
===== Example
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"name": "my_restricted_kibana_role",
diff --git a/docs/api/role-management/put.asciidoc b/docs/api/role-management/put.asciidoc
index a00fedf7e7ac4..59e6bc8d37eec 100644
--- a/docs/api/role-management/put.asciidoc
+++ b/docs/api/role-management/put.asciidoc
@@ -4,15 +4,13 @@
Create or update role
++++
-Create a new {kib} role, or update the attributes of an existing role. {kib} roles are stored in the
+experimental[] Create a new {kib} role, or update the attributes of an existing role. {kib} roles are stored in the
{es} native realm.
-experimental["The underlying mechanism of enforcing role-based access control is stable, but the APIs for managing the roles are experimental."]
-
[[role-management-api-put-request]]
==== Request
-`PUT /api/security/role/my_kibana_role`
+`PUT :/api/security/role/my_kibana_role`
[[role-management-api-put-prereqs]]
==== Prerequisite
@@ -22,45 +20,45 @@ To use the create or update role API, you must have the `manage_security` cluste
[[role-management-api-response-body]]
==== Request body
-`metadata`::
+`metadata`::
(Optional, object) In the `metadata` object, keys that begin with `_` are reserved for system usage.
-`elasticsearch`::
- (Optional, object) {es} cluster and index privileges. Valid keys include
+`elasticsearch`::
+ (Optional, object) {es} cluster and index privileges. Valid keys include
`cluster`, `indices`, and `run_as`. For more information, see
{ref}/defining-roles.html[Defining roles].
-`kibana`::
+`kibana`::
(list) Objects that specify the <> for the role:
-`base` :::
+`base` :::
(Optional, list) A base privilege. When specified, the base must be `["all"]` or `["read"]`.
When the `base` privilege is specified, you are unable to use the `feature` section.
"all" grants read/write access to all {kib} features for the specified spaces.
"read" grants read-only access to all {kib} features for the specified spaces.
-`feature` :::
+`feature` :::
(object) Contains privileges for specific features.
When the `feature` privileges are specified, you are unable to use the `base` section.
To retrieve a list of available features, use the <>.
-`spaces` :::
+`spaces` :::
(list) The spaces to apply the privileges to.
To grant access to all spaces, set to `["*"]`, or omit the value.
[[role-management-api-put-response-codes]]
==== Response code
-`204`::
+`204`::
Indicates a successful call.
===== Examples
Grant access to various features in all spaces:
-[source,js]
+[source,sh]
--------------------------------------------------
-PUT /api/security/role/my_kibana_role
+$ curl -X PUT "localhost:5601/api/security/role/my_kibana_role"
{
"metadata" : {
"version" : 1
@@ -127,9 +125,9 @@ PUT /api/security/role/my_kibana_role
Grant dashboard-only access to only the Marketing space:
-[source,js]
+[source,sh]
--------------------------------------------------
-PUT /api/security/role/my_kibana_role
+$ curl -X PUT "localhost:5601/api/security/role/my_kibana_role"
{
"metadata" : {
"version" : 1
@@ -155,9 +153,9 @@ PUT /api/security/role/my_kibana_role
Grant full access to all features in the Default space:
-[source,js]
+[source,sh]
--------------------------------------------------
-PUT /api/security/role/my_kibana_role
+$ curl -X PUT "localhost:5601/api/security/role/my_kibana_role"
{
"metadata" : {
"version" : 1
@@ -182,9 +180,9 @@ PUT /api/security/role/my_kibana_role
Grant different access to different spaces:
-[source,js]
+[source,sh]
--------------------------------------------------
-PUT /api/security/role/my_kibana_role
+$ curl -X PUT "localhost:5601/api/security/role/my_kibana_role"
{
"metadata" : {
"version" : 1
@@ -216,11 +214,11 @@ PUT /api/security/role/my_kibana_role
--------------------------------------------------
// KIBANA
-Grant access to {kib} and Elasticsearch:
+Grant access to {kib} and {es}:
-[source,js]
+[source,sh]
--------------------------------------------------
-PUT /api/security/role/my_kibana_role
+$ curl -X PUT "localhost:5601/api/security/role/my_kibana_role"
{
"metadata" : {
"version" : 1
diff --git a/docs/api/saved-objects/bulk_create.asciidoc b/docs/api/saved-objects/bulk_create.asciidoc
index d649684bc30f2..9daba224b317c 100644
--- a/docs/api/saved-objects/bulk_create.asciidoc
+++ b/docs/api/saved-objects/bulk_create.asciidoc
@@ -9,9 +9,9 @@ experimental[] Create multiple {kib} saved objects.
[[saved-objects-api-bulk-create-request]]
==== Request
-`POST /api/saved_objects/_bulk_create`
+`POST :/api/saved_objects/_bulk_create`
-`POST /s//api/saved_objects/_bulk_create`
+`POST :/s//api/saved_objects/_bulk_create`
[[saved-objects-api-bulk-create-path-params]]
@@ -63,9 +63,9 @@ Saved objects that are unable to persist are replaced with an error object.
Create an index pattern with the `my-pattern` ID, and a dashboard with the `my-dashboard` ID:
-[source,js]
+[source,sh]
--------------------------------------------------
-POST api/saved_objects/_bulk_create
+$ curl -X POST "localhost:5601/api/saved_objects/_bulk_create"
[
{
"type": "index-pattern",
@@ -87,7 +87,7 @@ POST api/saved_objects/_bulk_create
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"saved_objects": [
diff --git a/docs/api/saved-objects/bulk_get.asciidoc b/docs/api/saved-objects/bulk_get.asciidoc
index 3ef5823716d79..a6fdeb69ba925 100644
--- a/docs/api/saved-objects/bulk_get.asciidoc
+++ b/docs/api/saved-objects/bulk_get.asciidoc
@@ -9,9 +9,9 @@ experimental[] Retrieve multiple {kib} saved objects by ID.
[[saved-objects-api-bulk-get-request]]
==== Request
-`POST /api/saved_objects/_bulk_get`
+`POST :/api/saved_objects/_bulk_get`
-`POST /s//api/saved_objects/_bulk_get`
+`POST :/s//api/saved_objects/_bulk_get`
[[saved-objects-api-bulk-get-path-params]]
==== Path parameters
@@ -50,9 +50,9 @@ Saved objects that are unable to persist are replaced with an error object.
Retrieve an index pattern with the `my-pattern` ID, and a dashboard with the `my-dashboard` ID:
-[source,js]
+[source,sh]
--------------------------------------------------
-POST api/saved_objects/_bulk_get
+$ curl -X POST "localhost:5601/api/saved_objects/_bulk_get"
[
{
"type": "index-pattern",
@@ -68,7 +68,7 @@ POST api/saved_objects/_bulk_get
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"saved_objects": [
diff --git a/docs/api/saved-objects/create.asciidoc b/docs/api/saved-objects/create.asciidoc
index 634c71bb4eefe..dc010c80fd012 100644
--- a/docs/api/saved-objects/create.asciidoc
+++ b/docs/api/saved-objects/create.asciidoc
@@ -9,11 +9,11 @@ experimental[] Create {kib} saved objects.
[[saved-objects-api-create-request]]
==== Request
-`POST /api/saved_objects/` +
+`POST :/api/saved_objects/` +
-`POST /api/saved_objects//`
+`POST :/api/saved_objects//`
-`POST /s//saved_objects/`
+`POST :/s//saved_objects/`
[[saved-objects-api-create-path-params]]
==== Path parameters
@@ -55,9 +55,9 @@ any data that you send to the API is properly formed.
[[saved-objects-api-create-example]]
==== Example
-[source,js]
+[source,sh]
--------------------------------------------------
-POST api/saved_objects/index-pattern/my-pattern
+$ curl -X POST "localhost:5601/api/saved_objects/index-pattern/my-pattern"
{
"attributes": {
"title": "my-pattern-*"
@@ -68,7 +68,7 @@ POST api/saved_objects/index-pattern/my-pattern
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"id": "my-pattern", <1>
diff --git a/docs/api/saved-objects/delete.asciidoc b/docs/api/saved-objects/delete.asciidoc
index c34f9b67dfd22..65c955e15d360 100644
--- a/docs/api/saved-objects/delete.asciidoc
+++ b/docs/api/saved-objects/delete.asciidoc
@@ -4,16 +4,16 @@
Delete object
++++
-experimental[] Remove {kib} saved objects.
+experimental[] Remove {kib} saved objects.
WARNING: Once you delete a saved object, _it cannot be recovered_.
[[saved-objects-api-delete-request]]
==== Request
-`DELETE /api/saved_objects//`
+`DELETE :/api/saved_objects//`
-`DELETE /s//api/saved_objects//`
+`DELETE :/s//api/saved_objects//`
[[saved-objects-api-delete-path-params]]
==== Path parameters
@@ -33,12 +33,12 @@ WARNING: Once you delete a saved object, _it cannot be recovered_.
`200`::
Indicates a successful call.
-==== Examples
+==== Example
Delete an index pattern object with the `my-pattern` ID:
-[source,js]
+[source,sh]
--------------------------------------------------
-DELETE api/saved_objects/index-pattern/my-pattern
+$ curl -X DELETE "localhost:5601/api/saved_objects/index-pattern/my-pattern"
--------------------------------------------------
// KIBANA
diff --git a/docs/api/saved-objects/export.asciidoc b/docs/api/saved-objects/export.asciidoc
index 1b4f50dda2ddb..e8c762b9543a1 100644
--- a/docs/api/saved-objects/export.asciidoc
+++ b/docs/api/saved-objects/export.asciidoc
@@ -9,9 +9,9 @@ experimental[] Retrieve sets of saved objects that you want to import into {kib}
[[saved-objects-api-export-request]]
==== Request
-`POST /api/saved_objects/_export`
+`POST :/api/saved_objects/_export`
-`POST /s//api/saved_objects/_export`
+`POST :/s//api/saved_objects/_export`
[[saved-objects-api-export-path-params]]
==== Path parameters
@@ -39,7 +39,7 @@ TIP: You must include `type` or `objects` in the request body.
[[saved-objects-api-export-request-response-body]]
==== Response body
-The format of the response body is newline delimited JSON. Each exported object is exported as a valid JSON record and separated by the newline character '\n'.
+The format of the response body is newline delimited JSON. Each exported object is exported as a valid JSON record and separated by the newline character '\n'.
When `excludeExportDetails=false` (the default) we append an export result details record at the end of the file after all the saved object records. The export result details object has the following format:
@@ -66,9 +66,9 @@ When `excludeExportDetails=false` (the default) we append an export result detai
Export all index pattern saved objects:
-[source,js]
+[source,sh]
--------------------------------------------------
-POST api/saved_objects/_export
+$ curl -X POST "localhost:5601/api/saved_objects/_export"
{
"type": "index-pattern"
}
@@ -77,9 +77,9 @@ POST api/saved_objects/_export
Export all index pattern saved objects and exclude the export summary from the stream:
-[source,js]
+[source,sh]
--------------------------------------------------
-POST api/saved_objects/_export
+$ curl -X POST "localhost:5601/api/saved_objects/_export"
{
"type": "index-pattern",
"excludeExportDetails": true
@@ -89,9 +89,9 @@ POST api/saved_objects/_export
Export a specific saved object:
-[source,js]
+[source,sh]
--------------------------------------------------
-POST api/saved_objects/_export
+$ curl -X POST "localhost:5601/api/saved_objects/_export"
{
"objects": [
{
@@ -105,9 +105,9 @@ POST api/saved_objects/_export
Export a specific saved object and it's related objects :
-[source,js]
+[source,sh]
--------------------------------------------------
-POST api/saved_objects/_export
+$ curl -X POST "localhost:5601/api/saved_objects/_export"
{
"objects": [
{
diff --git a/docs/api/saved-objects/find.asciidoc b/docs/api/saved-objects/find.asciidoc
index 955c50922fde7..93e60be5d4923 100644
--- a/docs/api/saved-objects/find.asciidoc
+++ b/docs/api/saved-objects/find.asciidoc
@@ -9,9 +9,9 @@ experimental[] Retrieve a paginated set of {kib} saved objects by various condit
[[saved-objects-api-find-request]]
==== Request
-`GET /api/saved_objects/_find`
+`GET :/api/saved_objects/_find`
-`GET /s//api/saved_objects/_find`
+`GET :/s//api/saved_objects/_find`
[[saved-objects-api-find-path-params]]
==== Path parameters
@@ -67,15 +67,15 @@ change. Use the find API for traditional paginated results, but avoid using it t
Find index patterns with titles that start with `my`:
-[source,js]
+[source,sh]
--------------------------------------------------
-GET api/saved_objects/_find?type=index-pattern&search_fields=title&search=my*
+$ curl -X GET "localhost:5601/api/saved_objects/_find?type=index-pattern&search_fields=title&search=my*"
--------------------------------------------------
// KIBANA
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"total": 1,
@@ -95,8 +95,8 @@ The API returns the following:
For parameters that accept multiple values (e.g. `fields`), repeat the
query parameter for each value:
-[source,js]
+[source,sh]
--------------------------------------------------
-GET api/saved_objects/_find?fields=id&fields=title
+$ curl -X GET "localhost:5601/api/saved_objects/_find?fields=id&fields=title"
--------------------------------------------------
// KIBANA
diff --git a/docs/api/saved-objects/get.asciidoc b/docs/api/saved-objects/get.asciidoc
index 29f8ef67e0a83..86b86795b534f 100644
--- a/docs/api/saved-objects/get.asciidoc
+++ b/docs/api/saved-objects/get.asciidoc
@@ -9,9 +9,9 @@ experimental[] Retrieve a single {kib} saved object by ID.
[[saved-objects-api-get-request]]
==== Request
-`GET /api/saved_objects//`
+`GET :/api/saved_objects//`
-`GET /s//api/saved_objects//`
+`GET :/s//api/saved_objects//`
[[saved-objects-api-get-params]]
==== Path parameters
@@ -37,15 +37,15 @@ experimental[] Retrieve a single {kib} saved object by ID.
Retrieve the index pattern object with the `my-pattern` ID:
-[source,js]
+[source,sh]
--------------------------------------------------
-GET api/saved_objects/index-pattern/my-pattern
+$ curl -X GET "localhost:5601/api/saved_objects/index-pattern/my-pattern"
--------------------------------------------------
// KIBANA
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"id": "my-pattern",
@@ -57,17 +57,17 @@ The API returns the following:
}
--------------------------------------------------
-The following example retrieves a dashboard object in the `testspace` by id.
+Retrieve a dashboard object in the `testspace` by ID:
-[source,js]
+[source,sh]
--------------------------------------------------
-GET /s/testspace/api/saved_objects/dashboard/7adfa750-4c81-11e8-b3d7-01146121b73d
+$ curl -X GET "localhost:5601/s/testspace/api/saved_objects/dashboard/7adfa750-4c81-11e8-b3d7-01146121b73d"
--------------------------------------------------
// KIBANA
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"id": "7adfa750-4c81-11e8-b3d7-01146121b73d",
diff --git a/docs/api/saved-objects/import.asciidoc b/docs/api/saved-objects/import.asciidoc
index 1a380830ed21a..b3e4c48696a17 100644
--- a/docs/api/saved-objects/import.asciidoc
+++ b/docs/api/saved-objects/import.asciidoc
@@ -9,9 +9,9 @@ experimental[] Create sets of {kib} saved objects from a file created by the exp
[[saved-objects-api-import-request]]
==== Request
-`POST /api/saved_objects/_import`
+`POST :/api/saved_objects/_import`
-`POST /s//api/saved_objects/_import`
+`POST :/s//api/saved_objects/_import`
[[saved-objects-api-import-path-params]]
==== Path parameters
@@ -55,14 +55,15 @@ The request body must include the multipart/form-data type.
Import an index pattern and dashboard:
-[source,js]
+[source,sh]
--------------------------------------------------
$ curl -X POST "localhost:5601/api/saved_objects/_import" -H "kbn-xsrf: true" --form file=@file.ndjson
--------------------------------------------------
+// KIBANA
The `file.ndjson` file contains the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{"type":"index-pattern","id":"my-pattern","attributes":{"title":"my-pattern-*"}}
{"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"}}
@@ -70,7 +71,7 @@ The `file.ndjson` file contains the following:
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"success": true,
@@ -80,14 +81,15 @@ The API returns the following:
Import an index pattern and dashboard that includes a conflict on the index pattern:
-[source,js]
+[source,sh]
--------------------------------------------------
$ curl -X POST "localhost:5601/api/saved_objects/_import" -H "kbn-xsrf: true" --form file=@file.ndjson
--------------------------------------------------
+// KIBANA
The `file.ndjson` file contains the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{"type":"index-pattern","id":"my-pattern","attributes":{"title":"my-pattern-*"}}
{"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"}}
@@ -95,7 +97,7 @@ The `file.ndjson` file contains the following:
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"success": false,
@@ -115,14 +117,15 @@ The API returns the following:
Import a visualization and dashboard with an index pattern for the visualization reference that doesn't exist:
-[source,js]
+[source,sh]
--------------------------------------------------
$ curl -X POST "localhost:5601/api/saved_objects/_import" -H "kbn-xsrf: true" --form file=@file.ndjson
--------------------------------------------------
+// KIBANA
The `file.ndjson` file contains the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{"type":"visualization","id":"my-vis","attributes":{"title":"my-vis"},"references":[{"name":"ref_0","type":"index-pattern","id":"my-pattern-*"}]}
{"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"},"references":[{"name":"ref_0","type":"visualization","id":"my-vis"}]}
@@ -130,7 +133,7 @@ The `file.ndjson` file contains the following:
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
"success": false,
"successCount": 0,
diff --git a/docs/api/saved-objects/resolve_import_errors.asciidoc b/docs/api/saved-objects/resolve_import_errors.asciidoc
index b64e5deb361b2..ec03917390d36 100644
--- a/docs/api/saved-objects/resolve_import_errors.asciidoc
+++ b/docs/api/saved-objects/resolve_import_errors.asciidoc
@@ -17,9 +17,9 @@ To resolve errors, you can:
[[saved-objects-api-resolve-import-errors-request]]
==== Request
-`POST /api/saved_objects/_resolve_import_errors`
+`POST :/api/saved_objects/_resolve_import_errors`
-`POST /s//api/saved_objects/_resolve_import_errors`
+`POST :/s//api/saved_objects/_resolve_import_errors`
[[saved-objects-api-resolve-import-errors-path-params]]
==== Path parameters
@@ -61,21 +61,22 @@ The request body must include the multipart/form-data type.
Retry a dashboard import:
-[source,js]
+[source,sh]
--------------------------------------------------
$ curl -X POST "localhost:5601/api/saved_objects/_resolve_import_errors" -H "kbn-xsrf: true" --form file=@file.ndjson --form retries='[{"type":"dashboard","id":"my-dashboard"}]'
--------------------------------------------------
+// KIBANA
The `file.ndjson` file contains the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"}}
--------------------------------------------------
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"success": true,
@@ -85,14 +86,15 @@ The API returns the following:
Resolve errors for a dashboard and overwrite the existing saved object:
-[source,js]
+[source,sh]
--------------------------------------------------
$ curl -X POST "localhost:5601/api/saved_objects/_resolve_import_errors" -H "kbn-xsrf: true" --form file=@file.ndjson --form retries='[{"type":"dashboard","id":"my-dashboard","overwrite":true}]'
--------------------------------------------------
+// KIBANA
The `file.ndjson` file contains the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{"type":"index-pattern","id":"my-pattern","attributes":{"title":"my-pattern-*"}}
{"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"}}
@@ -100,7 +102,7 @@ The `file.ndjson` file contains the following:
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"success": true,
@@ -110,21 +112,22 @@ The API returns the following:
Resolve errors for a visualization by replacing the index pattern with another:
-[source,js]
+[source,sh]
--------------------------------------------------
$ curl -X POST "localhost:5601/api/saved_objects/_resolve_import_errors" -H "kbn-xsrf: true" --form file=@file.ndjson --form retries='[{"type":"visualization","id":"my-vis","replaceReferences":[{"type":"index-pattern","from":"missing","to":"existing"}]}]'
--------------------------------------------------
+// KIBANA
The `file.ndjson` file contains the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{"type":"visualization","id":"my-vis","attributes":{"title":"Look at my visualization"},"references":[{"name":"ref_0","type":"index-pattern","id":"missing"}]}
--------------------------------------------------
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"success": true,
diff --git a/docs/api/saved-objects/update.asciidoc b/docs/api/saved-objects/update.asciidoc
index 99a9bd4ad15bb..62f4104debc77 100644
--- a/docs/api/saved-objects/update.asciidoc
+++ b/docs/api/saved-objects/update.asciidoc
@@ -9,9 +9,9 @@ experimental[] Update the attributes for existing {kib} saved objects.
[[saved-objects-api-update-request]]
==== Request
-`PUT /api/saved_objects//`
+`PUT :/api/saved_objects//`
-`PUT /s//api/saved_objects//`
+`PUT :/s//api/saved_objects//`
[[saved-objects-api-update-path-params]]
==== Path parameters
@@ -47,9 +47,9 @@ WARNING: When you update, attributes are not validated, which allows you to pass
Update an existing index pattern object,`my-pattern`, with a different title:
-[source,js]
+[source,sh]
--------------------------------------------------
-PUT api/saved_objects/index-pattern/my-pattern
+$ curl -X PUT "localhost:5601/api/saved_objects/index-pattern/my-pattern"
{
"attributes": {
"title": "some-other-pattern-*"
@@ -60,7 +60,7 @@ PUT api/saved_objects/index-pattern/my-pattern
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"id": "my-pattern",
diff --git a/docs/api/spaces-management/copy_saved_objects.asciidoc b/docs/api/spaces-management/copy_saved_objects.asciidoc
index c07b5f35efe09..e23a137485b2d 100644
--- a/docs/api/spaces-management/copy_saved_objects.asciidoc
+++ b/docs/api/spaces-management/copy_saved_objects.asciidoc
@@ -5,225 +5,75 @@
Copy saved objects to space
++++
-experimental["The underlying Spaces concepts are stable, but the APIs for managing Spaces are experimental."]
-
-////
-Use the appropriate heading levels for your book.
-Add anchors for each section.
-FYI: The section titles use attributes in case those terms change.
-////
-
-[[spaces-api-copy-saved-objects-request]]
-==== {api-request-title}
-////
-This section show the basic endpoint, without the body or optional parameters.
-Variables should use <...> syntax.
-If an API supports both PUT and POST, include both here.
-////
-
-`POST /api/spaces/_copy_saved_objects`
-
-`POST /s//api/spaces/_copy_saved_objects`
-
-
-////
-[[spaces-api-copy-saved-objects-prereqs]]
-==== {api-prereq-title}
-////
-////
-Optional list of prerequisites.
-
-For example:
-
-* A snapshot of an index created in 5.x can be restored to 6.x. You must...
-* If the {es} {security-features} are enabled, you must have `write`, `monitor`,
-and `manage_follow_index` index privileges...
-////
-
-
-[[spaces-api-copy-saved-objects-desc]]
-==== {api-description-title}
-
-Copy saved objects between spaces.
+experimental[] Copy saved objects between spaces.
It also allows you to automatically copy related objects, so when you copy a `dashboard`, this can automatically copy over the
associated visualizations, index patterns, and saved searches, as required.
-You can request to overwrite any objects that already exist in the target space if they share an ID, or you can use the
+You can request to overwrite any objects that already exist in the target space if they share an ID, or you can use the
<> to do this on a per-object basis.
-////
-Add a more detailed description the context.
-Link to related APIs if appropriate.
+[[spaces-api-copy-saved-objects-request]]
+==== {api-request-title}
-Guidelines for parameter documentation
-***************************************
-* Use a definition list.
-* End each definition with a period.
-* Include whether the parameter is Optional or Required and the data type.
-* Include default values as the last sentence of the first paragraph.
-* Include a range of valid values, if applicable.
-* If the parameter requires a specific delimiter for multiple values, say so.
-* If the parameter supports wildcards, ditto.
-* For large or nested objects, consider linking to a separate definition list.
-***************************************
-////
+`POST :/api/spaces/_copy_saved_objects`
+`POST :/s//api/spaces/_copy_saved_objects`
[[spaces-api-copy-saved-objects-path-params]]
==== {api-path-parms-title}
-////
-A list of all the parameters within the path of the endpoint (before the query string (?)).
-For example:
-``::
-(Required, string) Name of the follower index
-////
`space_id`::
-(Optional, string) Identifies the source space from which saved objects will be copied. If `space_id` is not specified in the URL, the default space is used.
-
-////
-[[spaces-api-copy-saved-objects-params]]
-==== {api-query-parms-title}
-////
-////
-A list of the parameters in the query string of the endpoint (after the ?).
-
-For example:
-`wait_for_active_shards`::
-(Optional, integer) Specifies the number of shards to wait on being active before
-responding. A shard must be restored from the leader index being active.
-Restoring a follower shard requires transferring all the remote Lucene segment
-files to the follower index. The default is `0`, which means waiting on none of
-the shards to be active.
-////
+(Optional, string) The ID of the space that contains the saved objects you want to copy. When `space_id` is unspecified in the URL, the default space is used.
[[spaces-api-copy-saved-objects-request-body]]
==== {api-request-body-title}
-////
-A list of the properties you can specify in the body of the request.
-For example:
-`remote_cluster`::
-(Required, string) The <> that contains
-the leader index.
+`spaces`::
+ (Required, string array) The IDs of the spaces where you want to copy the specified objects.
-`leader_index`::
-(Required, string) The name of the index in the leader cluster to follow.
-////
-`spaces` ::
- (Required, string array) The ids of the spaces the specified object(s) will be copied into.
-
-`objects` ::
+`objects`::
(Required, object array) The saved objects to copy.
- `type` :::
+ `type`:::
(Required, string) The saved object type.
- `id` :::
- (Required, string) The saved object id.
+ `id`:::
+ (Required, string) The saved object ID.
-`includeReferences` ::
+`includeReferences`::
(Optional, boolean) When set to `true`, all saved objects related to the specified saved objects will also be copied into the target spaces. The default value is `false`.
-`overwrite` ::
- (Optional, boolean) When set to `true`, all conflicts will be automatically overidden. If a saved object with a matching `type` and `id` exists in the target space, then that version will be replaced with the version from the source space. The default value is `false`.
+`overwrite`::
+ (Optional, boolean) When set to `true`, all conflicts are automatically overidden. When a saved object with a matching `type` and `id` exists in the target space, that version is replaced with the version from the source space. The default value is `false`.
[[spaces-api-copy-saved-objects-response-body]]
==== {api-response-body-title}
-////
-Response body is only required for detailed responses.
-
-For example:
-`auto_follow_stats`::
- (object) An object representing stats for the auto-follow coordinator. This
- object consists of the following fields:
-
-`auto_follow_stats.number_of_successful_follow_indices`:::
- (long) the number of indices that the auto-follow coordinator successfully
- followed
-...
-
-////
``::
- (object) Specifies the dynamic keys that are included in the response. An object describing the result of the copy operation for this particular space.
+ (object) An object that describes the result of the copy operation for the space. Includes the dynamic keys in the response.
`success`:::
- (boolean) Indicates if the copy operation was successful. Note that some objects may have been copied even if this is set to `false`. Consult the `successCount` and `errors` properties of the response for additional information.
+ (boolean) The copy operation was successful. When set to `false`, some objects may have been copied. For additional information, refer to the `successCount` and `errors` properties.
`successCount`:::
- (number) The number of objects that were successfully copied.
+ (number) The number of objects that successfully copied.
`errors`:::
- (Optional, array) Collection of any errors that were encountered during the copy operation. If any errors are reported, then the `success` flag will be set to `false`.
+ (Optional, array) The errors that occurred during the copy operation. When errors are reported, the `success` flag is set to `false`.v
`id`::::
- (string) The saved object id which failed to copy.
+ (string) The saved object ID that failed to copy.
`type`::::
- (string) The type of saved object which failed to copy.
+ (string) The type of saved object that failed to copy.
`error`::::
- (object) The error which caused the copy operation to fail.
+ (object) The error that caused the copy operation to fail.
`type`:::::
- (string) Indicates the type of error. May be one of: `conflict`, `unsupported_type`, `missing_references`, `unknown`. Errors marked as `conflict` may be resolved by using the <>.
-
-////
-[[spaces-api-copy-saved-objects-response-codes]]
-==== {api-response-codes-title}
-////
-////
-Response codes are only required when needed to understand the response body.
-
-For example:
-`200`::
-Indicates all listed indices or index aliases exist.
-
- `404`::
-Indicates one or more listed indices or index aliases **do not** exist.
-////
-
+ (string) The type of error. For example, `unsupported_type`, `missing_references`, or `unknown`. Errors marked as `conflict` may be resolved by using the <>.
[[spaces-api-copy-saved-objects-example]]
==== {api-examples-title}
-////
-Optional brief example.
-Use an 'Examples' heading if you include multiple examples.
+Copy a dashboard with the `my-dashboard` ID, including all references from the `default` space to the `marketing` and `sales` spaces:
-[source,js]
+[source,sh]
----
-PUT /follower_index/_ccr/follow?wait_for_active_shards=1
-{
- "remote_cluster" : "remote_cluster",
- "leader_index" : "leader_index",
- "max_read_request_operation_count" : 1024,
- "max_outstanding_read_requests" : 16,
- "max_read_request_size" : "1024k",
- "max_write_request_operation_count" : 32768,
- "max_write_request_size" : "16k",
- "max_outstanding_write_requests" : 8,
- "max_write_buffer_count" : 512,
- "max_write_buffer_size" : "512k",
- "max_retry_delay" : "10s",
- "read_poll_timeout" : "30s"
-}
-----
-// CONSOLE
-// TEST[setup:remote_cluster_and_leader_index]
-
-The API returns the following result:
-
-[source,js]
-----
-{
- "follow_index_created" : true,
- "follow_index_shards_acked" : true,
- "index_following_started" : true
-}
-----
-// TESTRESPONSE
-////
-
-The following example attempts to copy a dashboard with id `my-dashboard`, including all references from the `default` space to the `marketing` and `sales` spaces. The `marketing` space succeeds, while the `sales` space fails due to a conflict on the underlying index pattern:
-
-[source,js]
-----
-POST /api/spaces/_copy_saved_objects
+$ curl -X POST "localhost:5601/api/spaces/_copy_saved_objects"
{
"objects": [{
"type": "dashboard",
@@ -235,9 +85,9 @@ POST /api/spaces/_copy_saved_objects
----
// KIBANA
-The API returns the following result:
+The API returns the following:
-[source,js]
+[source,sh]
----
{
"marketing": {
@@ -258,11 +108,13 @@ The API returns the following result:
}
----
-The following example successfully copies a visualization with id `my-viz` from the `marketing` space to the `default` space:
+The `marketing` space succeeds, but the `sales` space fails due to a conflict in the index pattern.
+
+Copy a visualization with the `my-viz` ID from the `marketing` space to the `default` space:
-[source,js]
+[source,sh]
----
-POST /s/marketing/api/spaces/_copy_saved_objects
+$ curl -X POST "localhost:5601/s/marketing/api/spaces/_copy_saved_objects"
{
"objects": [{
"type": "visualization",
@@ -273,9 +125,9 @@ POST /s/marketing/api/spaces/_copy_saved_objects
----
// KIBANA
-The API returns the following result:
+The API returns the following:
-[source,js]
+[source,sh]
----
{
"default": {
diff --git a/docs/api/spaces-management/delete.asciidoc b/docs/api/spaces-management/delete.asciidoc
index c66307ea3070f..5b4db78c056dd 100644
--- a/docs/api/spaces-management/delete.asciidoc
+++ b/docs/api/spaces-management/delete.asciidoc
@@ -4,22 +4,20 @@
Delete space
++++
-Delete a {kib} space.
+experimental[] Delete a {kib} space.
-experimental["The underlying Spaces concepts are stable, but the APIs for managing Spaces are experimental."]
-
-WARNING: When you delete a space, all saved objects that belong to the space are automatically deleted, which is permanent and cannot be undone.
+WARNING: When you delete a space, all saved objects that belong to the space are automatically deleted, which is permanent and cannot be undone.
[[spaces-api-delete-request]]
==== Request
-`DELETE /api/spaces/space/marketing`
+`DELETE :/api/spaces/space/marketing`
[[spaces-api-delete-errors-codes]]
==== Response codes
-`204`::
+`204`::
Indicates a successful call.
-
+
`404`::
Indicates that the request failed.
diff --git a/docs/api/spaces-management/get.asciidoc b/docs/api/spaces-management/get.asciidoc
index 49119d7602b20..48245b7786604 100644
--- a/docs/api/spaces-management/get.asciidoc
+++ b/docs/api/spaces-management/get.asciidoc
@@ -4,14 +4,12 @@
Get space
++++
-Retrieve a specified {kib} space.
-
-experimental["The underlying Spaces concepts are stable, but the APIs for managing Spaces are experimental."]
+experimental[] Retrieve a specified {kib} space.
[[spaces-api-get-request]]
==== Request
-`GET /api/spaces/space/marketing`
+`GET :/api/spaces/space/marketing`
[[spaces-api-get-response-codes]]
==== Response code
@@ -24,7 +22,7 @@ experimental["The underlying Spaces concepts are stable, but the APIs for managi
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"id": "marketing",
@@ -35,4 +33,4 @@ The API returns the following:
"disabledFeatures": [],
"imageUrl": ""
}
---------------------------------------------------
\ No newline at end of file
+--------------------------------------------------
diff --git a/docs/api/spaces-management/get_all.asciidoc b/docs/api/spaces-management/get_all.asciidoc
index f7fb92baa165f..8f7ba86f332de 100644
--- a/docs/api/spaces-management/get_all.asciidoc
+++ b/docs/api/spaces-management/get_all.asciidoc
@@ -4,14 +4,12 @@
Get all spaces
++++
-Retrieve all {kib} spaces.
-
-experimental["The underlying Spaces concepts are stable, but the APIs for managing Spaces are experimental."]
+experimental[] Retrieve all {kib} spaces.
[[spaces-api-get-all-request]]
==== Request
-`GET /api/spaces/space`
+`GET :/api/spaces/space`
[[spaces-api-get-all-response-codes]]
==== Response code
@@ -24,7 +22,7 @@ experimental["The underlying Spaces concepts are stable, but the APIs for managi
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
[
{
diff --git a/docs/api/spaces-management/post.asciidoc b/docs/api/spaces-management/post.asciidoc
index 4d4627e98899e..b96fbe6364c34 100644
--- a/docs/api/spaces-management/post.asciidoc
+++ b/docs/api/spaces-management/post.asciidoc
@@ -4,14 +4,12 @@
Create space
++++
-Create a {kib} space.
-
-experimental["The underlying Spaces concepts are stable, but the APIs for managing Spaces are experimental."]
+experimental[] Create a {kib} space.
[[spaces-api-post-request]]
==== Request
-`POST /api/spaces/space`
+`POST :/api/spaces/space`
[[spaces-api-post-request-body]]
==== Request body
@@ -29,13 +27,13 @@ experimental["The underlying Spaces concepts are stable, but the APIs for managi
(Optional, string array) The list of disabled features for the space. To get a list of available feature IDs, use the <>.
`initials`::
- (Optional, string) Specifies the initials shown in the space avatar. By default, the initials are automatically generated from the space name. Initials must be 1 or 2 characters.
+ (Optional, string) The initials shown in the space avatar. By default, the initials are automatically generated from the space name. Initials must be 1 or 2 characters.
`color`::
- (Optional, string) Specifies the hexadecimal color code used in the space avatar. By default, the color is automatically generated from the space name.
+ (Optional, string) The hexadecimal color code used in the space avatar. By default, the color is automatically generated from the space name.
`imageUrl`::
- (Optional, string) Specifies the data-url encoded image to display in the space avatar. If specified, `initials` will not be displayed, and the `color` will be visible as the background color for transparent images.
+ (Optional, string) The data-URL encoded image to display in the space avatar. If specified, `initials` will not be displayed, and the `color` will be visible as the background color for transparent images.
For best results, your image should be 64x64. Images will not be optimized by this API call, so care should be taken when using custom images.
[[spaces-api-post-response-codes]]
@@ -47,9 +45,9 @@ experimental["The underlying Spaces concepts are stable, but the APIs for managi
[[spaces-api-post-example]]
==== Example
-[source,js]
+[source,sh]
--------------------------------------------------
-POST /api/spaces/space
+$ curl -X POST "localhost:5601/api/spaces/space"
{
"id": "marketing",
"name": "Marketing",
diff --git a/docs/api/spaces-management/put.asciidoc b/docs/api/spaces-management/put.asciidoc
index 586818707c76f..f405d57975a70 100644
--- a/docs/api/spaces-management/put.asciidoc
+++ b/docs/api/spaces-management/put.asciidoc
@@ -4,37 +4,35 @@
Update space
++++
-Update an existing {kib} space.
-
-experimental["The underlying Spaces concepts are stable, but the APIs for managing Spaces are experimental."]
+experimental[] Update an existing {kib} space.
[[spaces-api-put-api-request]]
==== Request
-`PUT /api/spaces/space/`
+`PUT :/api/spaces/space/`
[[spaces-api-put-request-body]]
==== Request body
-`id`::
+`id`::
(Required, string) The space ID that is part of the {kib} URL when inside the space. You are unable to change the ID with the update operation.
-`name`::
+`name`::
(Required, string) The display name for the space.
-`description`::
+`description`::
(Optional, string) The description for the space.
-`disabledFeatures`::
+`disabledFeatures`::
(Optional, string array) The list of disabled features for the space. To get a list of available feature IDs, use the <>.
-`initials`::
+`initials`::
(Optional, string) Specifies the initials shown in the space avatar. By default, the initials are automatically generated from the space name. Initials must be 1 or 2 characters.
-`color`::
+`color`::
(Optional, string) Specifies the hexadecimal color code used in the space avatar. By default, the color is automatically generated from the space name.
-`imageUrl`::
+`imageUrl`::
(Optional, string) Specifies the data-url encoded image to display in the space avatar. If specified, `initials` will not be displayed, and the `color` will be visible as the background color for transparent images.
For best results, your image should be 64x64. Images will not be optimized by this API call, so care should be taken when using custom images.
@@ -43,13 +41,13 @@ experimental["The underlying Spaces concepts are stable, but the APIs for managi
`200`::
Indicates a successful call.
-
+
[[sample-api-example]]
==== Example
-[source,js]
+[source,sh]
--------------------------------------------------
-PUT /api/spaces/space/marketing
+$ curl -X PUT "localhost:5601/api/spaces/space/marketing"
{
"id": "marketing",
"name": "Marketing",
diff --git a/docs/api/spaces-management/resolve_copy_saved_objects_conflicts.asciidoc b/docs/api/spaces-management/resolve_copy_saved_objects_conflicts.asciidoc
index 7b52125599c05..8e874bb9f94e5 100644
--- a/docs/api/spaces-management/resolve_copy_saved_objects_conflicts.asciidoc
+++ b/docs/api/spaces-management/resolve_copy_saved_objects_conflicts.asciidoc
@@ -5,227 +5,80 @@
Resolve copy to space conflicts
++++
-Overwrite specific saved objects that were returned as errors from the <>.
-
-experimental["The underlying Spaces concepts are stable, but the APIs for managing Spaces are experimental."]
-
-////
-Use the appropriate heading levels for your book.
-Add anchors for each section.
-FYI: The section titles use attributes in case those terms change.
-////
+experimental[] Overwrite saved objects that are returned as errors from the <>.
[[spaces-api-resolve-copy-saved-objects-conflicts-request]]
==== {api-request-title}
-////
-This section show the basic endpoint, without the body or optional parameters.
-Variables should use <...> syntax.
-If an API supports both PUT and POST, include both here.
-////
-
-`POST /api/spaces/_resolve_copy_saved_objects_errors`
-
-`POST /s//api/spaces/_resolve_copy_saved_objects_errors`
+`POST :/api/spaces/_resolve_copy_saved_objects_errors`
+`POST :/s//api/spaces/_resolve_copy_saved_objects_errors`
[[spaces-api-resolve-copy-saved-objects-conflicts-prereqs]]
==== {api-prereq-title}
-////
-Optional list of prerequisites.
-
-For example:
-
-* A snapshot of an index created in 5.x can be restored to 6.x. You must...
-* If the {es} {security-features} are enabled, you must have `write`, `monitor`,
-and `manage_follow_index` index privileges...
-////
-* Executed the <>, which returned one or more `conflict` errors that you wish to resolve.
-
-////
-[[spaces-api-resolve-copy-saved-objects-conflicts-desc]]
-==== {api-description-title}
-
-Allows saved objects to be selectively overridden in the target spaces.
-////
-
-////
-Add a more detailed description the context.
-Link to related APIs if appropriate.
-
-Guidelines for parameter documentation
-***************************************
-* Use a definition list.
-* End each definition with a period.
-* Include whether the parameter is Optional or Required and the data type.
-* Include default values as the last sentence of the first paragraph.
-* Include a range of valid values, if applicable.
-* If the parameter requires a specific delimiter for multiple values, say so.
-* If the parameter supports wildcards, ditto.
-* For large or nested objects, consider linking to a separate definition list.
-***************************************
-////
+Execute the <>, which returns the errors for you to resolve.
[[spaces-api-resolve-copy-saved-objects-conflicts-path-params]]
==== {api-path-parms-title}
-////
-A list of all the parameters within the path of the endpoint (before the query string (?)).
-For example:
-``::
-(Required, string) Name of the follower index
-////
`space_id`::
-(Optional, string) Identifies the source space from which saved objects will be copied. If `space_id` is not specified in the URL, the default space is used. Must be the same value that was used during the failed <> operation.
-
-////
-[[spaces-api-resolve-copy-saved-objects-conflicts-request-params]]
-==== {api-query-parms-title}
-////
-////
-A list of the parameters in the query string of the endpoint (after the ?).
-
-For example:
-`wait_for_active_shards`::
-(Optional, integer) Specifies the number of shards to wait on being active before
-responding. A shard must be restored from the leader index being active.
-Restoring a follower shard requires transferring all the remote Lucene segment
-files to the follower index. The default is `0`, which means waiting on none of
-the shards to be active.
-////
+(Optional, string) The ID of the space that contains the saved objects you want to copy. When `space_id` is unspecified in the URL, the default space is used. The `space_id` must be the same value used during the failed <> operation.
[[spaces-api-resolve-copy-saved-objects-conflicts-request-body]]
==== {api-request-body-title}
-////
-A list of the properties you can specify in the body of the request.
-
-For example:
-`remote_cluster`::
-(Required, string) The <> that contains
-the leader index.
-`leader_index`::
-(Required, string) The name of the index in the leader cluster to follow.
-////
-`objects` ::
- (Required, object array) The saved objects to copy. Must be the same value that was used during the failed <> operation.
- `type` :::
+`objects`::
+ (Required, object array) The saved objects to copy. The `objects` must be the same values used during the failed <> operation.
+ `type`:::
(Required, string) The saved object type.
- `id` :::
- (Required, string) The saved object id.
+ `id`:::
+ (Required, string) The saved object ID.
-`includeReferences` ::
- (Optional, boolean) When set to `true`, all saved objects related to the specified saved objects will also be copied into the target spaces. You must set this to the same value that you used when executing the <>. The default value is `false`.
+`includeReferences`::
+ (Optional, boolean) When set to `true`, all saved objects related to the specified saved objects are copied into the target spaces. The `includeReferences` must be the same values used during the failed <> operation. The default value is `false`.
`retries`::
- (Required, object) The retry operations to attempt. Object keys represent the target space ids.
- `` :::
- (Required, array) The the conflicts to resolve for the indicated ``.
- `type` ::::
+ (Required, object) The retry operations to attempt. Object keys represent the target space IDs.
+ ``:::
+ (Required, array) The errors to resolve for the specified ``.
+ `type`::::
(Required, string) The saved object type.
- `id` ::::
- (Required, string) The saved object id.
- `overwrite` ::::
- (Required, boolean) when set to `true`, the saved object from the source space (desigated by the <>) will overwrite the the conflicting object in the destination space. When `false`, this does nothing.
+ `id`::::
+ (Required, string) The saved object ID.
+ `overwrite`::::
+ (Required, boolean) When set to `true`, the saved object from the source space (desigated by the <>) overwrites the conflicting object in the destination space. When set to `false`, this does nothing.
[[spaces-api-resolve-copy-saved-objects-conflicts-response-body]]
==== {api-response-body-title}
-////
-Response body is only required for detailed responses.
-
-For example:
-`auto_follow_stats`::
- (object) An object representing stats for the auto-follow coordinator. This
- object consists of the following fields:
-
-`auto_follow_stats.number_of_successful_follow_indices`:::
- (long) the number of indices that the auto-follow coordinator successfully
- followed
-...
-
-////
``::
- (object) Specifies the dynamic keys that are included in the response. An object describing the result of the copy operation for this particular space.
+ (object) An object that describes the result of the copy operation for the space. Includes the dynamic keys in the response.
`success`:::
- (boolean) Indicates if the copy operation was successful. Note that some objects may have been copied even if this is set to `false`. Consult the `successCount` and `errors` properties of the response for additional information.
+ (boolean) The copy operation was successful. When set to `false`, some objects may have been copied. For additional information, refer to the `successCount` and `errors` properties.
`successCount`:::
- (number) The number of objects that were successfully copied.
+ (number) The number of objects that successfully copied.
`errors`:::
- (Optional, array) Collection of any errors that were encountered during the copy operation. If any errors are reported, then the `success` flag will be set to `false`.
+ (Optional, array) The errors that occurred during the copy operation. When errors are reported, the `success` flag is set to `false`.
`id`::::
- (string) The saved object id which failed to copy.
+ (string) The saved object ID that failed to copy.
`type`::::
- (string) The type of saved object which failed to copy.
+ (string) The type of saved object that failed to copy.
`error`::::
- (object) The error which caused the copy operation to fail.
+ (object) The error that caused the copy operation to fail.
`type`:::::
- (string) Indicates the type of error. May be one of: `unsupported_type`, `missing_references`, `unknown`.
-
-////
-[[spaces-api-resolve-copy-saved-objects-conflicts-response-codes]]
-==== {api-response-codes-title}
-////
-////
-Response codes are only required when needed to understand the response body.
-
-For example:
-`200`::
-Indicates all listed indices or index aliases exist.
-
- `404`::
-Indicates one or more listed indices or index aliases **do not** exist.
-////
+ (string) The type of error. For example, `unsupported_type`, `missing_references`, or `unknown`.
[[spaces-api-resolve-copy-saved-objects-conflicts-example]]
==== {api-examples-title}
-////
-Optional brief example.
-Use an 'Examples' heading if you include multiple examples.
-
-
-[source,js]
-----
-PUT /follower_index/_ccr/follow?wait_for_active_shards=1
-{
- "remote_cluster" : "remote_cluster",
- "leader_index" : "leader_index",
- "max_read_request_operation_count" : 1024,
- "max_outstanding_read_requests" : 16,
- "max_read_request_size" : "1024k",
- "max_write_request_operation_count" : 32768,
- "max_write_request_size" : "16k",
- "max_outstanding_write_requests" : 8,
- "max_write_buffer_count" : 512,
- "max_write_buffer_size" : "512k",
- "max_retry_delay" : "10s",
- "read_poll_timeout" : "30s"
-}
-----
-// CONSOLE
-// TEST[setup:remote_cluster_and_leader_index]
-
-The API returns the following result:
-
-[source,js]
-----
-{
- "follow_index_created" : true,
- "follow_index_shards_acked" : true,
- "index_following_started" : true
-}
-----
-// TESTRESPONSE
-////
-The following example overwrites an index pattern in the marketing space, and a visualization in the sales space.
+Overwrite an index pattern in the `marketing` space, and a visualization in the `sales` space:
-[source,js]
+[source,sh]
----
-POST api/spaces/_resolve_copy_saved_objects_errors
+$ curl -X POST "localhost:5601/api/spaces/_resolve_copy_saved_objects_errors"
{
"objects": [{
"type": "dashboard",
@@ -248,9 +101,9 @@ POST api/spaces/_resolve_copy_saved_objects_errors
----
// KIBANA
-The API returns the following result:
+The API returns the following:
-[source,js]
+[source,sh]
----
{
"marketing": {
diff --git a/docs/api/upgrade-assistant.asciidoc b/docs/api/upgrade-assistant.asciidoc
index 3e9c416b292cf..15d87fbd0dc9d 100644
--- a/docs/api/upgrade-assistant.asciidoc
+++ b/docs/api/upgrade-assistant.asciidoc
@@ -2,7 +2,7 @@
[[upgrade-assistant-api]]
== Upgrade assistant APIs
-Check the upgrade status of your Elasticsearch cluster and reindex indices that were created in the previous major version. The assistant helps you prepare for the next major version of Elasticsearch.
+Check the upgrade status of your {es} cluster and reindex indices that were created in the previous major version. The assistant helps you prepare for the next major version of {es}.
The following upgrade assistant APIs are available:
@@ -16,7 +16,7 @@ The following upgrade assistant APIs are available:
* <> to check the status of the reindex operation
-* <> to cancel reindexes that are waiting for the Elasticsearch reindex task to complete
+* <> to cancel reindexes that are waiting for the {es} reindex task to complete
include::upgrade-assistant/status.asciidoc[]
include::upgrade-assistant/reindexing.asciidoc[]
diff --git a/docs/api/upgrade-assistant/cancel_reindex.asciidoc b/docs/api/upgrade-assistant/cancel_reindex.asciidoc
index d31894cd06a05..04ab3bdde35fc 100644
--- a/docs/api/upgrade-assistant/cancel_reindex.asciidoc
+++ b/docs/api/upgrade-assistant/cancel_reindex.asciidoc
@@ -4,14 +4,14 @@
Cancel reindex
++++
-experimental["The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are experimental."]
+experimental[] Cancel reindexes that are waiting for the {es} reindex task to complete. For example, `lastCompletedStep` set to `40`.
Cancel reindexes that are waiting for the Elasticsearch reindex task to complete. For example, `lastCompletedStep` set to `40`.
[[cancel-reindex-request]]
==== Request
-`POST /api/upgrade_assistant/reindex/myIndex/cancel`
+`POST :/api/upgrade_assistant/reindex/myIndex/cancel`
[[cancel-reindex-response-codes]]
==== Response codes
@@ -24,7 +24,7 @@ Cancel reindexes that are waiting for the Elasticsearch reindex task to complete
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"acknowledged": true
diff --git a/docs/api/upgrade-assistant/check_reindex_status.asciidoc b/docs/api/upgrade-assistant/check_reindex_status.asciidoc
index c422e5764c69f..00801f201d1e1 100644
--- a/docs/api/upgrade-assistant/check_reindex_status.asciidoc
+++ b/docs/api/upgrade-assistant/check_reindex_status.asciidoc
@@ -4,27 +4,27 @@
Check reindex status
++++
-experimental["The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are experimental."]
+experimental[] Check the status of the reindex operation.
Check the status of the reindex operation.
[[check-reindex-status-request]]
==== Request
-`GET /api/upgrade_assistant/reindex/myIndex`
+`GET :/api/upgrade_assistant/reindex/myIndex`
[[check-reindex-status-response-codes]]
==== Response codes
`200`::
Indicates a successful call.
-
+
[[check-reindex-status-example]]
==== Example
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"reindexOp": {
@@ -53,59 +53,58 @@ The API returns the following:
[[status-code]]
==== Status codes
-`0`::
+`0`::
In progress
-`1`::
+`1`::
Completed
-`2`::
+`2`::
Failed
-
-`3`::
+
+`3`::
Paused
NOTE: If the {kib} node that started the reindex is shutdown or restarted, the reindex goes into a paused state after some time.
To resume the reindex, you must submit a new POST request to the `/api/upgrade_assistant/reindex/` endpoint.
-`4`::
+`4`::
Cancelled
[[step-code]]
==== Step codes
-`0`::
+`0`::
The reindex operation has been created in Kibana.
-
-`10`::
+
+`10`::
The index group services stopped. Only applies to some system indices.
-
-`20`::
- The index is set to `readonly`.
-
-`30`::
+
+`20`::
+ The index is set to `readonly`.
+
+`30`::
The new destination index has been created.
-
-`40`::
+
+`40`::
The reindex task in Elasticsearch has started.
-
-`50`::
+
+`50`::
The reindex task in Elasticsearch has completed.
-
-`60`::
+
+`60`::
Aliases were created to point to the new index, and the old index has been deleted.
-
-`70`::
+
+`70`::
The index group services have resumed. Only applies to some system indices.
[[warning-code]]
==== Warning codes
-`0`::
+`0`::
Specifies to remove the `_all` meta field.
-
-`1`::
+
+`1`::
Specifies to convert any coerced boolean values in the source document. For example, `yes`, `1`, and `off`.
-
-`2`::
- Specifies to convert documents to support Elastic Common Schema. Only applies to APM indices created in 6.x.
+`2`::
+ Specifies to convert documents to support Elastic Common Schema. Only applies to APM indices created in 6.x.
diff --git a/docs/api/upgrade-assistant/reindexing.asciidoc b/docs/api/upgrade-assistant/reindexing.asciidoc
index 51e7b917b67ac..ce5670822e5ad 100644
--- a/docs/api/upgrade-assistant/reindexing.asciidoc
+++ b/docs/api/upgrade-assistant/reindexing.asciidoc
@@ -4,14 +4,14 @@
Start or resume reindex
++++
-experimental["The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are experimental."]
+experimental[] Start a new reindex or resume a paused reindex.
Start a new reindex or resume a paused reindex.
[[start-resume-reindex-request]]
==== Request
-`POST /api/upgrade_assistant/reindex/myIndex`
+`POST :/api/upgrade_assistant/reindex/myIndex`
[[start-resume-reindex-codes]]
==== Response code
@@ -24,7 +24,7 @@ Start a new reindex or resume a paused reindex.
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"indexName": ".ml-state",
@@ -37,9 +37,9 @@ The API returns the following:
}
--------------------------------------------------
-<1> Name of the new index that is being created.
-<2> Current status of the reindex. For details, see <>.
-<3> Last successfully completed step of the reindex. For details, see <> table.
-<4> Task ID of the reindex task in Elasticsearch. Only present if reindexing has started.
-<5> Percentage of how far the reindexing task in Elasticsearch has progressed, in decimal from from 0 to 1.
-<6> Error that caused the reindex to fail, if it failed.
+<1> The name of the new index.
+<2> The reindex status. For more information, refer to <>.
+<3> The last successfully completed step of the reindex. For more information, refer to <>.
+<4> The task ID of the reindex task in {es}. Appears when the reindexing starts.
+<5> The progress of the reindexing task in {es}. Appears in decimal form, from 0 to 1.
+<6> The error that caused the reindex to fail, if it failed.
diff --git a/docs/api/upgrade-assistant/status.asciidoc b/docs/api/upgrade-assistant/status.asciidoc
index b087a66fa3bcd..42030061c4289 100644
--- a/docs/api/upgrade-assistant/status.asciidoc
+++ b/docs/api/upgrade-assistant/status.asciidoc
@@ -4,14 +4,14 @@
Upgrade readiness status
++++
-experimental["The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are experimental."]
+experimental[] Check the status of your cluster.
Check the status of your cluster.
[[upgrade-assistant-api-status-request]]
==== Request
-`GET /api/upgrade_assistant/status`
+`GET :/api/upgrade_assistant/status`
[[upgrade-assistant-api-status-response-codes]]
==== Response codes
@@ -24,7 +24,7 @@ Check the status of your cluster.
The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"readyForUpgrade": false,
diff --git a/docs/api/url-shortening.asciidoc b/docs/api/url-shortening.asciidoc
index 8bc701a3d5d12..a62529e11a9ba 100644
--- a/docs/api/url-shortening.asciidoc
+++ b/docs/api/url-shortening.asciidoc
@@ -12,18 +12,18 @@ Short URLs are designed to make sharing {kib} URLs easier.
[[url-shortening-api-request]]
==== Request
-`POST /api/shorten_url`
+`POST :/api/shorten_url`
[[url-shortening-api-request-body]]
==== Request body
`url`::
- (Required, string) The {kib} URL that you want to shorten, Relative to `/app/kibana`.
+ (Required, string) The {kib} URL that you want to shorten, relative to `/app/kibana`.
[[url-shortening-api-response-body]]
==== Response body
-urlId:: A top level property that contains the shortened URL token for the provided request body.
+urlId:: A top-level property that contains the shortened URL token for the provided request body.
[[url-shortening-api-codes]]
==== Response code
@@ -31,21 +31,21 @@ urlId:: A top level property that contains the shortened URL token for the provi
`200`::
Indicates a successful call.
-[[url-shortening-api-example]]
+[[url-shortening-api-example]]
==== Example
-[source,js]
+[source,sh]
--------------------------------------------------
-POST api/shorten_url
+$ curl -X POST "localhost:5601/api/shorten_url"
{
"url": "/app/kibana#/dashboard?_g=()&_a=(description:'',filters:!(),fullScreenMode:!f,options:(hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(),gridData:(h:15,i:'1',w:24,x:0,y:0),id:'8f4d0c00-4c86-11e8-b3d7-01146121b73d',panelIndex:'1',type:visualization,version:'7.0.0-alpha1')),query:(language:lucene,query:''),timeRestore:!f,title:'New%20Dashboard',viewMode:edit)"
}
--------------------------------------------------
// KIBANA
-The API returns the following result:
+The API returns the following:
-[source,js]
+[source,sh]
--------------------------------------------------
{
"urlId": "f73b295ff92718b26bc94edac766d8e3"
diff --git a/docs/api/using-api.asciidoc b/docs/api/using-api.asciidoc
index 37c5315025dc4..aba65f2e921c2 100644
--- a/docs/api/using-api.asciidoc
+++ b/docs/api/using-api.asciidoc
@@ -33,6 +33,7 @@ For example, the following `curl` command exports a dashboard:
--
curl -X POST -u $USER:$PASSWORD "localhost:5601/api/kibana/dashboards/export?dashboard=942dcef0-b2cd-11e8-ad8e-85441f0c2e5c"
--
+// KIBANA
[float]
[[api-request-headers]]
@@ -43,14 +44,14 @@ For all APIs, you must use a request header. The {kib} APIs support the `kbn-xsr
`kbn-xsrf: true`::
By default, you must use `kbn-xsrf` for all API calls, except in the following scenarios:
-* The API endpoint uses the `GET` or `HEAD` methods
+* The API endpoint uses the `GET` or `HEAD` operations
* The path is whitelisted using the <> setting
* XSRF protections are disabled using the `server.xsrf.disableProtection` setting
`Content-Type: application/json`::
- Applicable only when you send a payload in the API request. {kib} API requests and responses use JSON. Typically, if you include the `kbn-xsrf` header, you must also include the `Content-Type` header.
+ Applicable only when you send a payload in the API request. {kib} API requests and responses use JSON. Typically, if you include the `kbn-xsrf` header, you must also include the `Content-Type` header.
Request header example:
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts
index 3f81bfe5aadf2..55e1475fcb03a 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts
@@ -25,17 +25,9 @@
*/
export { npSetup, npStart } from 'ui/new_platform';
-
-export { KbnUrl } from 'ui/url/kbn_url';
-// @ts-ignore
-export { KbnUrlProvider } from 'ui/url/index';
-export { IInjector } from 'ui/chrome';
export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
export {
configureAppAngularModule,
- IPrivate,
migrateLegacyQuery,
- PrivateProvider,
- PromiseServiceCreator,
subscribeWithScope,
} from '../../../../../plugins/kibana_legacy/public';
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts
index 9447b5384d172..877ccab99171d 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts
@@ -29,13 +29,7 @@ import {
PluginInitializerContext,
} from 'kibana/public';
import { Storage } from '../../../../../../plugins/kibana_utils/public';
-import {
- configureAppAngularModule,
- IPrivate,
- KbnUrlProvider,
- PrivateProvider,
- PromiseServiceCreator,
-} from '../legacy_imports';
+import { configureAppAngularModule } from '../legacy_imports';
// @ts-ignore
import { initDashboardApp } from './legacy_app';
import { EmbeddableStart } from '../../../../../../plugins/embeddable/public';
@@ -116,10 +110,7 @@ function mountDashboardApp(appBasePath: string, element: HTMLElement) {
function createLocalAngularModule(core: AppMountContext['core'], navigation: NavigationStart) {
createLocalI18nModule();
- createLocalPrivateModule();
- createLocalPromiseModule();
createLocalConfigModule(core);
- createLocalKbnUrlModule();
createLocalTopNavModule(navigation);
createLocalIconModule();
@@ -127,10 +118,7 @@ function createLocalAngularModule(core: AppMountContext['core'], navigation: Nav
...thirdPartyAngularDependencies,
'app/dashboard/Config',
'app/dashboard/I18n',
- 'app/dashboard/Private',
'app/dashboard/TopNav',
- 'app/dashboard/KbnUrl',
- 'app/dashboard/Promise',
'app/dashboard/icon',
]);
return dashboardAngularModule;
@@ -142,14 +130,8 @@ function createLocalIconModule() {
.directive('icon', reactDirective => reactDirective(EuiIcon));
}
-function createLocalKbnUrlModule() {
- angular
- .module('app/dashboard/KbnUrl', ['app/dashboard/Private', 'ngRoute'])
- .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider));
-}
-
function createLocalConfigModule(core: AppMountContext['core']) {
- angular.module('app/dashboard/Config', ['app/dashboard/Private']).provider('config', () => {
+ angular.module('app/dashboard/Config', []).provider('config', () => {
return {
$get: () => ({
get: core.uiSettings.get.bind(core.uiSettings),
@@ -158,14 +140,6 @@ function createLocalConfigModule(core: AppMountContext['core']) {
});
}
-function createLocalPromiseModule() {
- angular.module('app/dashboard/Promise', []).service('Promise', PromiseServiceCreator);
-}
-
-function createLocalPrivateModule() {
- angular.module('app/dashboard/Private', []).provider('Private', PrivateProvider);
-}
-
function createLocalTopNavModule(navigation: NavigationStart) {
angular
.module('app/dashboard/TopNav', ['react'])
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app.tsx b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app.tsx
index c0a0693431295..4e9942767186e 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app.tsx
+++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app.tsx
@@ -21,8 +21,6 @@ import moment from 'moment';
import { Subscription } from 'rxjs';
import { History } from 'history';
-import { IInjector } from '../legacy_imports';
-
import { ViewMode } from '../../../../embeddable_api/public/np_ready/public';
import { SavedObjectDashboard } from '../saved_dashboard/saved_dashboard';
import { DashboardAppState, SavedDashboardPanel } from './types';
@@ -86,28 +84,26 @@ export interface DashboardAppScope extends ng.IScope {
}
export function initDashboardAppDirective(app: any, deps: RenderDeps) {
- app.directive('dashboardApp', function($injector: IInjector) {
- return {
- restrict: 'E',
- controllerAs: 'dashboardApp',
- controller: (
- $scope: DashboardAppScope,
- $route: any,
- $routeParams: {
- id?: string;
- },
- kbnUrlStateStorage: IKbnUrlStateStorage,
- history: History
- ) =>
- new DashboardAppController({
- $route,
- $scope,
- $routeParams,
- indexPatterns: deps.data.indexPatterns,
- kbnUrlStateStorage,
- history,
- ...deps,
- }),
- };
- });
+ app.directive('dashboardApp', () => ({
+ restrict: 'E',
+ controllerAs: 'dashboardApp',
+ controller: (
+ $scope: DashboardAppScope,
+ $route: any,
+ $routeParams: {
+ id?: string;
+ },
+ kbnUrlStateStorage: IKbnUrlStateStorage,
+ history: History
+ ) =>
+ new DashboardAppController({
+ $route,
+ $scope,
+ $routeParams,
+ indexPatterns: deps.data.indexPatterns,
+ kbnUrlStateStorage,
+ history,
+ ...deps,
+ }),
+ }));
}
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js
index 64abbdfb87d58..dbeaf8a98b461 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js
+++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js
@@ -18,6 +18,7 @@
*/
import { i18n } from '@kbn/i18n';
+import { parse } from 'query-string';
import dashboardTemplate from './dashboard_app.html';
import dashboardListingTemplate from './listing/dashboard_listing_ng_wrapper.html';
@@ -93,9 +94,8 @@ export function initDashboardApp(app, deps) {
.when(DashboardConstants.LANDING_PAGE_PATH, {
...defaults,
template: dashboardListingTemplate,
- controller($injector, $location, $scope, kbnUrlStateStorage) {
+ controller($scope, kbnUrlStateStorage, history) {
const service = deps.savedDashboards;
- const kbnUrl = $injector.get('kbnUrl');
const dashboardConfig = deps.dashboardConfig;
// syncs `_g` portion of url with query services
@@ -106,13 +106,13 @@ export function initDashboardApp(app, deps) {
$scope.listingLimit = deps.uiSettings.get('savedObjects:listingLimit');
$scope.create = () => {
- kbnUrl.redirect(DashboardConstants.CREATE_NEW_DASHBOARD_URL);
+ history.push(DashboardConstants.CREATE_NEW_DASHBOARD_URL);
};
$scope.find = search => {
return service.find(search, $scope.listingLimit);
};
$scope.editItem = ({ id }) => {
- kbnUrl.redirect(`${createDashboardEditUrl(id)}?_a=(viewMode:edit)`);
+ history.push(`${createDashboardEditUrl(id)}?_a=(viewMode:edit)`);
};
$scope.getViewUrl = ({ id }) => {
return deps.addBasePath(`#${createDashboardEditUrl(id)}`);
@@ -121,7 +121,7 @@ export function initDashboardApp(app, deps) {
return service.delete(dashboards.map(d => d.id));
};
$scope.hideWriteControls = dashboardConfig.getHideWriteControls();
- $scope.initialFilter = $location.search().filter || EMPTY_FILTER;
+ $scope.initialFilter = parse(history.location.search).filter || EMPTY_FILTER;
deps.chrome.setBreadcrumbs([
{
text: i18n.translate('kbn.dashboard.dashboardBreadcrumbsTitle', {
@@ -191,7 +191,7 @@ export function initDashboardApp(app, deps) {
template: dashboardTemplate,
controller: createNewDashboardCtrl,
resolve: {
- dash: function($route, kbnUrl, history) {
+ dash: function($route, history) {
const id = $route.current.params.id;
return ensureDefaultIndexPattern(deps.core, deps.data, history)
@@ -208,7 +208,7 @@ export function initDashboardApp(app, deps) {
// A corrupt dashboard was detected (e.g. with invalid JSON properties)
if (error instanceof InvalidJSONProperty) {
deps.core.notifications.toasts.addDanger(error.message);
- kbnUrl.redirect(DashboardConstants.LANDING_PAGE_PATH);
+ history.push(DashboardConstants.LANDING_PAGE_PATH);
return;
}
diff --git a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts
index a19278911507c..031e10e99289f 100644
--- a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts
@@ -24,8 +24,6 @@ import angular from 'angular';
import { EuiIcon } from '@elastic/eui';
import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
import { CoreStart, LegacyCoreStart } from 'kibana/public';
-// @ts-ignore
-import { KbnUrlProvider } from 'ui/url';
import { DataPublicPluginStart } from '../../../../../plugins/data/public';
import { Storage } from '../../../../../plugins/kibana_utils/public';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public';
@@ -59,7 +57,6 @@ import { createRenderCompleteDirective } from './np_ready/angular/directives/ren
import {
initAngularBootstrap,
configureAppAngularModule,
- IPrivate,
KbnAccessibleClickProvider,
PrivateProvider,
PromiseServiceCreator,
@@ -106,7 +103,6 @@ export function initializeInnerAngularModule(
createLocalI18nModule();
createLocalPrivateModule();
createLocalPromiseModule();
- createLocalKbnUrlModule();
createLocalTopNavModule(navigation);
createLocalStorageModule();
createElasticSearchModule(data);
@@ -166,12 +162,6 @@ export function initializeInnerAngularModule(
.service('debounce', ['$timeout', DebounceProviderTimeout]);
}
-function createLocalKbnUrlModule() {
- angular
- .module('discoverKbnUrl', ['discoverPrivate', 'ngRoute'])
- .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider));
-}
-
function createLocalPromiseModule() {
angular.module('discoverPromise', []).service('Promise', PromiseServiceCreator);
}
@@ -223,7 +213,7 @@ function createPagerFactoryModule() {
function createDocTableModule() {
angular
- .module('discoverDocTable', ['discoverKbnUrl', 'discoverPagerFactory', 'react'])
+ .module('discoverDocTable', ['discoverPagerFactory', 'react'])
.directive('docTable', createDocTableDirective)
.directive('kbnTableHeader', createTableHeaderDirective)
.directive('toolBarPagerText', createToolBarPagerTextDirective)
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js
index e45ab2a7d7675..278317ec2e87b 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js
@@ -184,7 +184,6 @@ function discoverController(
$timeout,
$window,
Promise,
- kbnUrl,
localStorage,
uiCapabilities
) {
@@ -255,6 +254,15 @@ function discoverController(
}
});
+ // this listener is waiting for such a path http://localhost:5601/app/kibana#/discover
+ // which could be set through pressing "New" button in top nav or go to "Discover" plugin from the sidebar
+ // to reload the page in a right way
+ const unlistenHistoryBasePath = history.listen(({ pathname, search, hash }) => {
+ if (!search && !hash && pathname === '/discover') {
+ $route.reload();
+ }
+ });
+
$scope.setIndexPattern = async id => {
await replaceUrlAppState({ index: id });
$route.reload();
@@ -310,6 +318,7 @@ function discoverController(
stopStateSync();
stopSyncingGlobalStateWithUrl();
stopSyncingQueryAppStateWithStateContainer();
+ unlistenHistoryBasePath();
});
const getTopNavLinks = () => {
@@ -323,7 +332,7 @@ function discoverController(
}),
run: function() {
$scope.$evalAsync(() => {
- kbnUrl.change('/discover');
+ history.push('/discover');
});
},
testId: 'discoverNewButton',
@@ -391,9 +400,7 @@ function discoverController(
testId: 'discoverOpenButton',
run: () => {
showOpenSearchPanel({
- makeUrl: searchId => {
- return kbnUrl.eval('#/discover/{{id}}', { id: searchId });
- },
+ makeUrl: searchId => `#/discover/${encodeURIComponent(searchId)}`,
I18nContext: core.i18n.Context,
});
},
@@ -751,7 +758,7 @@ function discoverController(
});
if (savedSearch.id !== $route.current.params.id) {
- kbnUrl.change('/discover/{{id}}', { id: savedSearch.id });
+ history.push(`/discover/${encodeURIComponent(savedSearch.id)}`);
} else {
// Update defaults so that "reload saved query" functions correctly
setAppState(getStateDefaults());
@@ -921,11 +928,11 @@ function discoverController(
};
$scope.resetQuery = function() {
- kbnUrl.change('/discover/{{id}}', { id: $route.current.params.id });
+ history.push(`/discover/${encodeURIComponent($route.current.params.id)}`);
};
$scope.newQuery = function() {
- kbnUrl.change('/discover');
+ history.push('/discover');
};
$scope.updateDataSource = () => {
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_row.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_row.ts
index 5d3f6ac199a46..698bfe7416d42 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_row.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_row.ts
@@ -41,11 +41,7 @@ interface LazyScope extends ng.IScope {
[key: string]: any;
}
-export function createTableRowDirective(
- $compile: ng.ICompileService,
- $httpParamSerializer: any,
- kbnUrl: any
-) {
+export function createTableRowDirective($compile: ng.ICompileService, $httpParamSerializer: any) {
const cellTemplate = _.template(noWhiteSpace(cellTemplateHtml));
const truncateByHeightTemplate = _.template(noWhiteSpace(truncateByHeightTemplateHtml));
@@ -110,10 +106,9 @@ export function createTableRowDirective(
};
$scope.getContextAppHref = () => {
- const path = kbnUrl.eval('#/discover/context/{{ indexPattern }}/{{ anchorId }}', {
- anchorId: $scope.row._id,
- indexPattern: $scope.indexPattern.id,
- });
+ const path = `#/discover/context/${encodeURIComponent(
+ $scope.indexPattern.id
+ )}/${encodeURIComponent($scope.row._id)}`;
const globalFilters: any = getServices().filterManager.getGlobalFilters();
const appFilters: any = getServices().filterManager.getAppFilters();
const hash = $httpParamSerializer({
diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts
index e6b7a29e28d89..a2e2ba3543104 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts
@@ -24,8 +24,6 @@
* directly where they are needed.
*/
-// @ts-ignore
-export { KbnUrlProvider } from 'ui/url';
export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
export { wrapInI18nContext } from 'ui/i18n';
@@ -33,9 +31,6 @@ export { DashboardConstants } from '../dashboard/np_ready/dashboard_constants';
export { VisSavedObject, VISUALIZE_EMBEDDABLE_TYPE } from '../../../visualizations/public/';
export {
configureAppAngularModule,
- IPrivate,
migrateLegacyQuery,
- PrivateProvider,
- PromiseServiceCreator,
subscribeWithScope,
} from '../../../../../plugins/kibana_legacy/public';
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts
index c7c3286bb5c71..241397884c8fe 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts
@@ -21,13 +21,7 @@ import angular, { IModule } from 'angular';
import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
import { AppMountContext } from 'kibana/public';
-import {
- configureAppAngularModule,
- KbnUrlProvider,
- IPrivate,
- PrivateProvider,
- PromiseServiceCreator,
-} from '../legacy_imports';
+import { configureAppAngularModule } from '../legacy_imports';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../../plugins/navigation/public';
import {
createTopNavDirective,
@@ -82,36 +76,16 @@ function mountVisualizeApp(appBasePath: string, element: HTMLElement) {
function createLocalAngularModule(core: AppMountContext['core'], navigation: NavigationStart) {
createLocalI18nModule();
- createLocalPrivateModule();
- createLocalPromiseModule();
- createLocalKbnUrlModule();
createLocalTopNavModule(navigation);
const visualizeAngularModule: IModule = angular.module(moduleName, [
...thirdPartyAngularDependencies,
'app/visualize/I18n',
- 'app/visualize/Private',
'app/visualize/TopNav',
- 'app/visualize/KbnUrl',
- 'app/visualize/Promise',
]);
return visualizeAngularModule;
}
-function createLocalKbnUrlModule() {
- angular
- .module('app/visualize/KbnUrl', ['app/visualize/Private', 'ngRoute'])
- .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider));
-}
-
-function createLocalPromiseModule() {
- angular.module('app/visualize/Promise', []).service('Promise', PromiseServiceCreator);
-}
-
-function createLocalPrivateModule() {
- angular.module('app/visualize/Private', []).provider('Private', PrivateProvider);
-}
-
function createLocalTopNavModule(navigation: NavigationStart) {
angular
.module('app/visualize/TopNav', ['react'])
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js
index 1fab38027f65b..7d1c29fbf48da 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js
@@ -30,7 +30,7 @@ import { VisualizeConstants } from '../visualize_constants';
import { getEditBreadcrumbs } from '../breadcrumbs';
import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util';
-import { unhashUrl } from '../../../../../../../plugins/kibana_utils/public';
+import { unhashUrl, removeQueryParam } from '../../../../../../../plugins/kibana_utils/public';
import { MarkdownSimple, toMountPoint } from '../../../../../../../plugins/kibana_react/public';
import { addFatalError, kbnBaseUrl } from '../../../../../../../plugins/kibana_legacy/public';
import {
@@ -69,16 +69,7 @@ export function initEditorDirective(app, deps) {
initVisualizationDirective(app, deps);
}
-function VisualizeAppController(
- $scope,
- $route,
- $window,
- $injector,
- $timeout,
- kbnUrl,
- kbnUrlStateStorage,
- history
-) {
+function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlStateStorage, history) {
const {
indexPatterns,
localStorage,
@@ -421,7 +412,7 @@ function VisualizeAppController(
const addToDashMode =
$route.current.params[DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM];
- kbnUrl.removeParam(DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM);
+ removeQueryParam(history, DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM);
$scope.isAddToDashMode = () => addToDashMode;
@@ -639,10 +630,10 @@ function VisualizeAppController(
const savedVisualizationParsedUrl = new KibanaParsedUrl({
basePath: getBasePath(),
appId: kbnBaseUrl.slice('/app/'.length),
- appPath: kbnUrl.eval(`${VisualizeConstants.EDIT_PATH}/{{id}}`, { id: savedVis.id }),
+ appPath: `${VisualizeConstants.EDIT_PATH}/${encodeURIComponent(savedVis.id)}`,
});
// Manually insert a new url so the back button will open the saved visualization.
- $window.history.pushState({}, '', savedVisualizationParsedUrl.getRootRelativePath());
+ history.replace(savedVisualizationParsedUrl.appPath);
setActiveUrl(savedVisualizationParsedUrl.appPath);
const lastDashboardAbsoluteUrl = chrome.navLinks.get('kibana:dashboard').url;
@@ -658,7 +649,7 @@ function VisualizeAppController(
DashboardConstants.ADD_EMBEDDABLE_ID,
savedVis.id
);
- kbnUrl.change(dashboardParsedUrl.appPath);
+ history.push(dashboardParsedUrl.appPath);
} else if (savedVis.id === $route.current.params.id) {
chrome.docTitle.change(savedVis.lastSavedTitle);
chrome.setBreadcrumbs($injector.invoke(getEditBreadcrumbs));
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js
index 5a479a491395a..6c02afb672e4c 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js
@@ -34,7 +34,7 @@ export function initListingDirective(app) {
);
}
-export function VisualizeListingController($injector, $scope, createNewVis, kbnUrlStateStorage) {
+export function VisualizeListingController($scope, createNewVis, kbnUrlStateStorage, history) {
const {
addBasePath,
chrome,
@@ -46,7 +46,6 @@ export function VisualizeListingController($injector, $scope, createNewVis, kbnU
visualizations,
core: { docLinks, savedObjects },
} = getServices();
- const kbnUrl = $injector.get('kbnUrl');
// syncs `_g` portion of url with query services
const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl(
@@ -83,7 +82,11 @@ export function VisualizeListingController($injector, $scope, createNewVis, kbnU
this.closeNewVisModal = visualizations.showNewVisModal({
onClose: () => {
// In case the user came via a URL to this page, change the URL to the regular landing page URL after closing the modal
- kbnUrl.changePath(VisualizeConstants.LANDING_PAGE_PATH);
+ history.push({
+ // Should preserve querystring part so the global state is preserved.
+ ...history.location,
+ pathname: VisualizeConstants.LANDING_PAGE_PATH,
+ });
},
});
}
diff --git a/src/plugins/kibana_legacy/public/angular/angular_config.tsx b/src/plugins/kibana_legacy/public/angular/angular_config.tsx
index 67d62cab7409b..71cd57ef2d72e 100644
--- a/src/plugins/kibana_legacy/public/angular/angular_config.tsx
+++ b/src/plugins/kibana_legacy/public/angular/angular_config.tsx
@@ -226,7 +226,7 @@ const $setupUICapabilityRedirect = (newPlatform: CoreStart) => (
}
if (!get(newPlatform.application.capabilities, route.requireUICapability)) {
- $injector.get('kbnUrl').change('/home');
+ $injector.get('$location').url('/home');
event.preventDefault();
}
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx
index 3197c269fd90c..e0a188b4915a2 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx
@@ -57,6 +57,20 @@ function useCytoscape(options: cytoscape.CytoscapeOptions) {
return [ref, cy] as [React.MutableRefObject, cytoscape.Core | undefined];
}
+function rotatePoint(
+ { x, y }: { x: number; y: number },
+ degreesRotated: number
+) {
+ const radiansPerDegree = Math.PI / 180;
+ const θ = radiansPerDegree * degreesRotated;
+ const cosθ = Math.cos(θ);
+ const sinθ = Math.sin(θ);
+ return {
+ x: x * cosθ - y * sinθ,
+ y: x * sinθ + y * cosθ
+ };
+}
+
function getLayoutOptions(
selectedRoots: string[],
height: number,
@@ -71,10 +85,11 @@ function getLayoutOptions(
animate: true,
animationEasing: animationOptions.easing,
animationDuration: animationOptions.duration,
- // Rotate nodes from top -> bottom to display left -> right
// @ts-ignore
- transform: (node: any, { x, y }: cytoscape.Position) => ({ x: y, y: -x }),
- // swap width/height of boundingBox to compensation for the rotation
+ // Rotate nodes counter-clockwise to transform layout from top→bottom to left→right.
+ // The extra 5° achieves the effect of separating overlapping taxi-styled edges.
+ transform: (node: any, pos: cytoscape.Position) => rotatePoint(pos, -95),
+ // swap width/height of boundingBox to compensate for the rotation
boundingBox: { x1: 0, y1: 0, w: height, h: width }
};
}
@@ -109,20 +124,31 @@ export function Cytoscape({
// is required and can trigger rendering when changed.
const divStyle = { ...style, height };
- const dataHandler = useCallback(
- event => {
+ const resetConnectedEdgeStyle = useCallback(
+ (node?: cytoscape.NodeSingular) => {
if (cy) {
cy.edges().removeClass('highlight');
- if (serviceName) {
- const focusedNode = cy.getElementById(serviceName);
- focusedNode.connectedEdges().addClass('highlight');
+ if (node) {
+ node.connectedEdges().addClass('highlight');
}
+ }
+ },
+ [cy]
+ );
- // Add the "primary" class to the node if its id matches the serviceName.
- if (cy.nodes().length > 0 && serviceName) {
- cy.nodes().removeClass('primary');
- cy.getElementById(serviceName).addClass('primary');
+ const dataHandler = useCallback(
+ event => {
+ if (cy) {
+ if (serviceName) {
+ resetConnectedEdgeStyle(cy.getElementById(serviceName));
+ // Add the "primary" class to the node if its id matches the serviceName.
+ if (cy.nodes().length > 0) {
+ cy.nodes().removeClass('primary');
+ cy.getElementById(serviceName).addClass('primary');
+ }
+ } else {
+ resetConnectedEdgeStyle();
}
if (event.cy.elements().length > 0) {
const selectedRoots = selectRoots(event.cy);
@@ -141,7 +167,7 @@ export function Cytoscape({
}
}
},
- [cy, serviceName, height, width]
+ [cy, resetConnectedEdgeStyle, serviceName, height, width]
);
// Trigger a custom "data" event when data changes
@@ -162,12 +188,20 @@ export function Cytoscape({
event.target.removeClass('hover');
event.target.connectedEdges().removeClass('nodeHover');
};
+ const selectHandler: cytoscape.EventHandler = event => {
+ resetConnectedEdgeStyle(event.target);
+ };
+ const unselectHandler: cytoscape.EventHandler = event => {
+ resetConnectedEdgeStyle();
+ };
if (cy) {
cy.on('data', dataHandler);
cy.ready(dataHandler);
cy.on('mouseover', 'edge, node', mouseoverHandler);
cy.on('mouseout', 'edge, node', mouseoutHandler);
+ cy.on('select', 'node', selectHandler);
+ cy.on('unselect', 'node', unselectHandler);
}
return () => {
@@ -181,7 +215,7 @@ export function Cytoscape({
cy.removeListener('mouseout', 'edge, node', mouseoutHandler);
}
};
- }, [cy, dataHandler, serviceName]);
+ }, [cy, dataHandler, resetConnectedEdgeStyle, serviceName]);
return (
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.tsx
deleted file mode 100644
index 77f0b64ba0fb1..0000000000000
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.tsx
+++ /dev/null
@@ -1,74 +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 {
- EuiButton,
- EuiPanel,
- EuiFlexGroup,
- EuiFlexItem,
- EuiTitle,
- EuiText,
- EuiSpacer
-} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import React from 'react';
-import { invalidLicenseMessage } from '../../../../../../../plugins/apm/common/service_map';
-import { useKibanaUrl } from '../../../hooks/useKibanaUrl';
-
-export function PlatinumLicensePrompt() {
- // Set the height to give it some top margin
- const flexGroupStyle = { height: '60vh' };
- const flexItemStyle = { width: 600, textAlign: 'center' as const };
-
- const licensePageUrl = useKibanaUrl(
- '/app/kibana',
- '/management/elasticsearch/license_management/home'
- );
-
- return (
-
-
-
-
-
-
-
- {i18n.translate('xpack.apm.serviceMap.licensePromptTitle', {
- defaultMessage: 'Service maps is available in Platinum.'
- })}
-
-
-
-
-
{invalidLicenseMessage}
-
-
-
- {i18n.translate('xpack.apm.serviceMap.licensePromptButtonText', {
- defaultMessage: 'Start 30-day Platinum trial'
- })}
-
-
-
-
-
- );
-}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts
index 30b36b58cb001..e19cb8ae4b646 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts
@@ -121,15 +121,18 @@ const style: cytoscape.Stylesheet[] = [
{
selector: 'edge.nodeHover',
style: {
- width: 4,
+ width: 2,
// @ts-ignore
- 'z-index': zIndexEdgeHover
+ 'z-index': zIndexEdgeHover,
+ 'line-color': theme.euiColorDarkShade,
+ 'source-arrow-color': theme.euiColorDarkShade,
+ 'target-arrow-color': theme.euiColorDarkShade
}
},
{
selector: 'node.hover',
style: {
- 'border-width': 4
+ 'border-width': 2
}
},
{
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx
index 7040c27765a8d..4974553f6ca93 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx
@@ -4,22 +4,25 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import theme from '@elastic/eui/dist/eui_theme_light.json';
import React from 'react';
-import { isValidPlatinumLicense } from '../../../../../../../plugins/apm/common/service_map';
-import { useDeepObjectIdentity } from '../../../hooks/useDeepObjectIdentity';
+import {
+ invalidLicenseMessage,
+ isValidPlatinumLicense
+} from '../../../../../../../plugins/apm/common/service_map';
import { useFetcher } from '../../../hooks/useFetcher';
import { useLicense } from '../../../hooks/useLicense';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { callApmApi } from '../../../services/rest/createCallApmApi';
-import { BetaBadge } from './BetaBadge';
+import { LicensePrompt } from '../../shared/LicensePrompt';
import { Controls } from './Controls';
import { Cytoscape } from './Cytoscape';
import { cytoscapeDivStyle } from './cytoscapeOptions';
import { EmptyBanner } from './EmptyBanner';
-import { PlatinumLicensePrompt } from './PlatinumLicensePrompt';
import { Popover } from './Popover';
import { useRefDimensions } from './useRefDimensions';
+import { BetaBadge } from './BetaBadge';
interface ServiceMapProps {
serviceName?: string;
@@ -28,33 +31,27 @@ interface ServiceMapProps {
export function ServiceMap({ serviceName }: ServiceMapProps) {
const license = useLicense();
const { urlParams, uiFilters } = useUrlParams();
- const params = useDeepObjectIdentity({
- start: urlParams.start,
- end: urlParams.end,
- environment: urlParams.environment,
- serviceName,
- uiFilters: {
- ...uiFilters,
- environment: undefined
- }
- });
const { data } = useFetcher(() => {
- const { start, end } = params;
+ const { start, end, environment } = urlParams;
if (start && end) {
return callApmApi({
pathname: '/api/apm/service-map',
params: {
query: {
- ...params,
start,
end,
- uiFilters: JSON.stringify(params.uiFilters)
+ environment,
+ serviceName,
+ uiFilters: JSON.stringify({
+ ...uiFilters,
+ environment: undefined
+ })
}
}
});
}
- }, [params]);
+ }, [serviceName, uiFilters, urlParams]);
const { ref, height, width } = useRefDimensions();
@@ -81,6 +78,18 @@ export function ServiceMap({ serviceName }: ServiceMapProps) {
) : (
-
+
+
+
+
+
);
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/Documentation.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/Documentation.tsx
new file mode 100644
index 0000000000000..48a0288f11ae5
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/Documentation.tsx
@@ -0,0 +1,16 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React from 'react';
+import { ElasticDocsLink } from '../../../../../shared/Links/ElasticDocsLink';
+
+interface Props {
+ label: string;
+}
+export const Documentation = ({ label }: Props) => (
+
+ {label}
+
+);
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FiltersSection.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FiltersSection.tsx
index 69fecf25f5143..1c253b2fa8bff 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FiltersSection.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FiltersSection.tsx
@@ -16,12 +16,11 @@ import {
import { i18n } from '@kbn/i18n';
import { isEmpty } from 'lodash';
import React from 'react';
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { FilterOptions } from '../../../../../../../../../../plugins/apm/server/routes/settings/custom_link';
+import { FilterOptions } from '../../../../../../../../../../plugins/apm/common/custom_link_filter_options';
import {
DEFAULT_OPTION,
- Filters,
- filterSelectOptions,
+ FilterKeyValue,
+ FILTER_SELECT_OPTIONS,
getSelectOptions
} from './helper';
@@ -29,10 +28,10 @@ export const FiltersSection = ({
filters,
onChangeFilters
}: {
- filters: Filters;
- onChangeFilters: (filters: Filters) => void;
+ filters: FilterKeyValue[];
+ onChangeFilters: (filters: FilterKeyValue[]) => void;
}) => {
- const onChangeFilter = (filter: Filters[0], idx: number) => {
+ const onChangeFilter = (filter: FilterKeyValue, idx: number) => {
const newFilters = [...filters];
newFilters[idx] = filter;
onChangeFilters(newFilters);
@@ -40,7 +39,8 @@ export const FiltersSection = ({
const onRemoveFilter = (idx: number) => {
// remove without mutating original array
- const newFilters = [...filters].splice(idx, 1);
+ const newFilters = [...filters];
+ newFilters.splice(idx, 1);
// if there is only one item left it should not be removed
// but reset to empty
@@ -68,12 +68,12 @@ export const FiltersSection = ({
-
+
{i18n.translate(
'xpack.apm.settings.customizeUI.customLink.flyout.filters.subtitle',
{
defaultMessage:
- 'Add additional values within the same field by comma separating values.'
+ 'Use the filter options to scope them to only appear for specific services.'
}
)}
@@ -83,12 +83,12 @@ export const FiltersSection = ({
{filters.map((filter, idx) => {
const [key, value] = filter;
const filterId = `filter-${idx}`;
- const selectOptions = getSelectOptions(filters, idx);
+ const selectOptions = getSelectOptions(filters, key);
return (
onRemoveFilter(idx)}
- disabled={!key && filters.length === 1}
+ disabled={!value && !key && filters.length === 1}
/>
@@ -139,7 +140,7 @@ export const FiltersSection = ({
>
);
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.test.tsx
new file mode 100644
index 0000000000000..9b487cf916089
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.test.tsx
@@ -0,0 +1,51 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React from 'react';
+import { LinkPreview } from '../CustomLinkFlyout/LinkPreview';
+import { render, getNodeText, getByTestId } from '@testing-library/react';
+
+describe('LinkPreview', () => {
+ const getElementValue = (container: HTMLElement, id: string) =>
+ getNodeText(
+ ((getByTestId(container, id) as HTMLDivElement)
+ .children as HTMLCollection)[0] as HTMLDivElement
+ );
+
+ it('shows label and url default values', () => {
+ const { container } = render(
+
+ );
+ expect(getElementValue(container, 'preview-label')).toEqual('Elastic.co');
+ expect(getElementValue(container, 'preview-url')).toEqual(
+ 'https://www.elastic.co'
+ );
+ });
+
+ it('shows label and url values', () => {
+ const { container } = render(
+
+ );
+ expect(getElementValue(container, 'preview-label')).toEqual('foo');
+ expect(
+ (getByTestId(container, 'preview-link') as HTMLAnchorElement).text
+ ).toEqual('https://baz.co');
+ });
+
+ it('shows warning when couldnt replace context variables', () => {
+ const { container } = render(
+
+ );
+ expect(getElementValue(container, 'preview-label')).toEqual('foo');
+ expect(
+ (getByTestId(container, 'preview-link') as HTMLAnchorElement).text
+ ).toEqual('https://baz.co?service.name={{invalid}');
+ expect(getByTestId(container, 'preview-warning')).toBeInTheDocument();
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.tsx
new file mode 100644
index 0000000000000..0ad3455ab271f
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.tsx
@@ -0,0 +1,124 @@
+/*
+ * 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, useState } from 'react';
+import {
+ EuiPanel,
+ EuiText,
+ EuiSpacer,
+ EuiLink,
+ EuiToolTip,
+ EuiIcon,
+ EuiFlexGroup,
+ EuiFlexItem
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { debounce } from 'lodash';
+import { Transaction } from '../../../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction';
+import { callApmApi } from '../../../../../../services/rest/createCallApmApi';
+import {
+ FilterKeyValue,
+ convertFiltersToObject,
+ replaceTemplateVariables
+} from './helper';
+
+interface Props {
+ label: string;
+ url: string;
+ filters: FilterKeyValue[];
+}
+
+const fetchTransaction = debounce(
+ async (
+ filters: FilterKeyValue[],
+ callback: (transaction: Transaction) => void
+ ) => {
+ const transaction = await callApmApi({
+ pathname: '/api/apm/settings/custom_links/transaction',
+ params: { query: convertFiltersToObject(filters) }
+ });
+ callback(transaction);
+ },
+ 1000
+);
+
+const getTextColor = (value?: string) => (value ? 'default' : 'subdued');
+
+export const LinkPreview = ({ label, url, filters }: Props) => {
+ const [transaction, setTransaction] = useState();
+
+ useEffect(() => {
+ fetchTransaction(filters, setTransaction);
+ }, [filters]);
+
+ const { formattedUrl, error } = replaceTemplateVariables(url, transaction);
+
+ return (
+
+
+ {label
+ ? label
+ : i18n.translate(
+ 'xpack.apm.settings.customizeUI.customLink.default.label',
+ { defaultMessage: 'Elastic.co' }
+ )}
+
+
+
+ {url ? (
+
+ {formattedUrl}
+
+ ) : (
+ i18n.translate(
+ 'xpack.apm.settings.customizeUI.customLink.default.url',
+ { defaultMessage: 'https://www.elastic.co' }
+ )
+ )}
+
+
+
+
+
+ {i18n.translate(
+ 'xpack.apm.settings.customizeUI.customLink.linkPreview.descrition',
+ {
+ defaultMessage:
+ 'Test your link with values from an example transaction document based on the filters above.'
+ }
+ )}
+
+
+
+
+ {error && (
+
+
+
+ )}
+
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkSection.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkSection.tsx
index 89f55a6c682ca..8bcebc2aea09e 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkSection.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkSection.tsx
@@ -13,11 +13,12 @@ import {
import { i18n } from '@kbn/i18n';
import React from 'react';
import { CustomLink } from '../../../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types';
+import { Documentation } from './Documentation';
interface InputField {
name: keyof CustomLink;
label: string;
- helpText: string;
+ helpText: string | React.ReactNode;
placeholder: string;
onChange: (value: string) => void;
value?: string;
@@ -69,13 +70,25 @@ export const LinkSection = ({
defaultMessage: 'URL'
}
),
- helpText: i18n.translate(
- 'xpack.apm.settings.customizeUI.customLink.flyout.link.url.helpText',
- {
- defaultMessage:
- 'Add fieldname variables to your URL to apply values e.g. {sample}. TODO: Learn more in the docs.',
- values: { sample: '{{trace.id}}' }
- }
+ helpText: (
+ <>
+ {i18n.translate(
+ 'xpack.apm.settings.customizeUI.customLink.flyout.link.url.helpText',
+ {
+ defaultMessage:
+ 'Add field name variables to your URL to apply values e.g. {sample}.',
+ values: { sample: '{{trace.id}}' }
+ }
+ )}{' '}
+
+ >
),
placeholder: i18n.translate(
'xpack.apm.settings.customizeUI.customLink.flyout.link.url.placeholder',
@@ -125,7 +138,7 @@ export const LinkSection = ({
fullWidth
value={field.value}
onChange={e => field.onChange(e.target.value)}
- aria-label={field.name}
+ data-test-subj={field.name}
/>
);
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.test.ts b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.test.ts
new file mode 100644
index 0000000000000..ac01ee48f2fe5
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.test.ts
@@ -0,0 +1,205 @@
+/*
+ * 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 {
+ convertFiltersToArray,
+ convertFiltersToObject,
+ getSelectOptions,
+ replaceTemplateVariables
+} from '../CustomLinkFlyout/helper';
+import { CustomLink } from '../../../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types';
+import { Transaction } from '../../../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction';
+
+describe('Custom link helper', () => {
+ describe('convertFiltersToArray', () => {
+ it('returns array of tuple when custom link not defined', () => {
+ expect(convertFiltersToArray()).toEqual([['', '']]);
+ });
+ it('returns filters as array', () => {
+ expect(
+ convertFiltersToArray({
+ 'service.name': 'foo',
+ 'transaction.type': 'bar'
+ } as CustomLink)
+ ).toEqual([
+ ['service.name', 'foo'],
+ ['transaction.type', 'bar']
+ ]);
+ });
+ it('returns empty when no filter is added', () => {
+ expect(
+ convertFiltersToArray({
+ label: 'foo',
+ url: 'bar'
+ } as CustomLink)
+ ).toEqual([['', '']]);
+ });
+ });
+
+ describe('convertFiltersToObject', () => {
+ it('returns undefined when any filter is added', () => {
+ expect(convertFiltersToObject([['', '']])).toBeUndefined();
+ });
+ it('removes uncompleted filters', () => {
+ expect(
+ convertFiltersToObject([
+ ['service.name', ''],
+ ['', 'foo'],
+ ['transaction.type', 'bar']
+ ])
+ ).toEqual({ 'transaction.type': ['bar'] });
+ });
+ it('splits the value by comma', () => {
+ expect(
+ convertFiltersToObject([
+ ['service.name', 'foo'],
+ ['service.environment', 'foo, bar'],
+ ['transaction.type', 'foo, '],
+ ['transaction.name', 'foo,']
+ ])
+ ).toEqual({
+ 'service.name': ['foo'],
+ 'service.environment': ['foo', 'bar'],
+ 'transaction.type': ['foo'],
+ 'transaction.name': ['foo']
+ });
+ });
+ });
+
+ describe('getSelectOptions', () => {
+ it('returns all available options when no filters were selected', () => {
+ expect(
+ getSelectOptions(
+ [
+ ['', ''],
+ ['', ''],
+ ['', ''],
+ ['', '']
+ ],
+ ''
+ )
+ ).toEqual([
+ { value: 'DEFAULT', text: 'Select field...' },
+ { value: 'service.name', text: 'service.name' },
+ { value: 'service.environment', text: 'service.environment' },
+ { value: 'transaction.type', text: 'transaction.type' },
+ { value: 'transaction.name', text: 'transaction.name' }
+ ]);
+ });
+ it('removes item added in another filter', () => {
+ expect(
+ getSelectOptions(
+ [
+ ['service.name', 'foo'],
+ ['', ''],
+ ['', ''],
+ ['', '']
+ ],
+ ''
+ )
+ ).toEqual([
+ { value: 'DEFAULT', text: 'Select field...' },
+ { value: 'service.environment', text: 'service.environment' },
+ { value: 'transaction.type', text: 'transaction.type' },
+ { value: 'transaction.name', text: 'transaction.name' }
+ ]);
+ });
+ it('removes item added in another filter but keep the current selected', () => {
+ expect(
+ getSelectOptions(
+ [
+ ['service.name', 'foo'],
+ ['transaction.name', 'bar'],
+ ['', ''],
+ ['', '']
+ ],
+ 'transaction.name'
+ )
+ ).toEqual([
+ { value: 'DEFAULT', text: 'Select field...' },
+ { value: 'service.environment', text: 'service.environment' },
+ { value: 'transaction.type', text: 'transaction.type' },
+ { value: 'transaction.name', text: 'transaction.name' }
+ ]);
+ });
+ it('returns empty when all option were selected', () => {
+ expect(
+ getSelectOptions(
+ [
+ ['service.name', 'foo'],
+ ['transaction.name', 'bar'],
+ ['service.environment', 'baz'],
+ ['transaction.type', 'qux']
+ ],
+ ''
+ )
+ ).toEqual([{ value: 'DEFAULT', text: 'Select field...' }]);
+ });
+ });
+
+ describe('replaceTemplateVariables', () => {
+ const transaction = ({
+ service: { name: 'foo' },
+ trace: { id: '123' }
+ } as unknown) as Transaction;
+
+ it('replaces template variables', () => {
+ expect(
+ replaceTemplateVariables(
+ 'https://elastic.co?service.name={{service.name}}&trace.id={{trace.id}}',
+ transaction
+ )
+ ).toEqual({
+ error: undefined,
+ formattedUrl: 'https://elastic.co?service.name=foo&trace.id=123'
+ });
+ });
+
+ it('returns error when transaction is not defined', () => {
+ const expectedResult = {
+ error:
+ "We couldn't find a matching transaction document based on the defined filters.",
+ formattedUrl: 'https://elastic.co?service.name=&trace.id='
+ };
+ expect(
+ replaceTemplateVariables(
+ 'https://elastic.co?service.name={{service.name}}&trace.id={{trace.id}}'
+ )
+ ).toEqual(expectedResult);
+ expect(
+ replaceTemplateVariables(
+ 'https://elastic.co?service.name={{service.name}}&trace.id={{trace.id}}',
+ ({} as unknown) as Transaction
+ )
+ ).toEqual(expectedResult);
+ });
+
+ it('returns error when could not replace variables', () => {
+ expect(
+ replaceTemplateVariables(
+ 'https://elastic.co?service.name={{service.nam}}&trace.id={{trace.i}}',
+ transaction
+ )
+ ).toEqual({
+ error:
+ "We couldn't find a value match for {{service.nam}}, {{trace.i}} in the example transaction document.",
+ formattedUrl: 'https://elastic.co?service.name=&trace.id='
+ });
+ });
+
+ it('returns error when variable is invalid', () => {
+ expect(
+ replaceTemplateVariables(
+ 'https://elastic.co?service.name={{service.name}',
+ transaction
+ )
+ ).toEqual({
+ error:
+ "We couldn't find an example transaction document due to invalid variable(s) defined.",
+ formattedUrl: 'https://elastic.co?service.name={{service.name}'
+ });
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.ts b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.ts
index bb86a251594ab..df99c82c71b70 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.ts
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.ts
@@ -4,15 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
-import { isEmpty, pick } from 'lodash';
+import Mustache from 'mustache';
+import { isEmpty, pick, get } from 'lodash';
+import { Transaction } from '../../../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction';
import {
FilterOptions,
- filterOptions
- // eslint-disable-next-line @kbn/eslint/no-restricted-paths
-} from '../../../../../../../../../../plugins/apm/server/routes/settings/custom_link';
+ FILTER_OPTIONS
+} from '../../../../../../../../../../plugins/apm/common/custom_link_filter_options';
import { CustomLink } from '../../../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types';
-export type Filters = Array<[keyof FilterOptions | '', string]>;
+type FilterKey = keyof FilterOptions | '';
+type FilterValue = string;
+export type FilterKeyValue = [FilterKey, FilterValue];
interface FilterSelectOption {
value: 'DEFAULT' | keyof FilterOptions;
@@ -33,9 +36,13 @@ interface FilterSelectOption {
* results: [['service.name', 'opbeans-java'],['transaction.type', 'request']]
* @param customLink
*/
-export const convertFiltersToArray = (customLink?: CustomLink): Filters => {
+export const convertFiltersToArray = (
+ customLink?: CustomLink
+): FilterKeyValue[] => {
if (customLink) {
- const filters = Object.entries(pick(customLink, filterOptions)) as Filters;
+ const filters = Object.entries(
+ pick(customLink, FILTER_OPTIONS)
+ ) as FilterKeyValue[];
if (!isEmpty(filters)) {
return filters;
}
@@ -54,9 +61,18 @@ export const convertFiltersToArray = (customLink?: CustomLink): Filters => {
* }
* @param filters
*/
-export const convertFiltersToObject = (filters: Filters) => {
+export const convertFiltersToObject = (filters: FilterKeyValue[]) => {
const convertedFilters = Object.fromEntries(
- filters.filter(([key, value]) => !isEmpty(key) && !isEmpty(value))
+ filters
+ .filter(([key, value]) => !isEmpty(key) && !isEmpty(value))
+ .map(([key, value]) => [
+ key,
+ // Splits the value by comma, removes whitespace from both ends and filters out empty values
+ value
+ .split(',')
+ .map(v => v.trim())
+ .filter(v => v)
+ ])
);
if (!isEmpty(convertedFilters)) {
return convertedFilters;
@@ -71,9 +87,9 @@ export const DEFAULT_OPTION: FilterSelectOption = {
)
};
-export const filterSelectOptions: FilterSelectOption[] = [
+export const FILTER_SELECT_OPTIONS: FilterSelectOption[] = [
DEFAULT_OPTION,
- ...filterOptions.map(filter => ({
+ ...FILTER_OPTIONS.map(filter => ({
value: filter as keyof FilterOptions,
text: filter
}))
@@ -83,14 +99,76 @@ export const filterSelectOptions: FilterSelectOption[] = [
* Returns the options available, removing filters already added, but keeping the selected filter.
*
* @param filters
- * @param idx
+ * @param selectedKey
*/
-export const getSelectOptions = (filters: Filters, idx: number) => {
- return filterSelectOptions.filter(option => {
- const indexUsedFilter = filters.findIndex(
- filter => filter[0] === option.value
+export const getSelectOptions = (
+ filters: FilterKeyValue[],
+ selectedKey: FilterKey
+) => {
+ return FILTER_SELECT_OPTIONS.filter(
+ ({ value }) =>
+ !filters.some(
+ ([filterKey]) => filterKey === value && filterKey !== selectedKey
+ )
+ );
+};
+
+const getInvalidTemplateVariables = (
+ template: string,
+ transaction: Transaction
+) => {
+ return (Mustache.parse(template) as Array<[string, string]>)
+ .filter(([type]) => type === 'name')
+ .map(([, value]) => value)
+ .filter(templateVar => get(transaction, templateVar) == null);
+};
+
+const validateUrl = (url: string, transaction?: Transaction) => {
+ if (!transaction || isEmpty(transaction)) {
+ return i18n.translate(
+ 'xpack.apm.settings.customizeUI.customLink.preview.transaction.notFound',
+ {
+ defaultMessage:
+ "We couldn't find a matching transaction document based on the defined filters."
+ }
+ );
+ }
+ try {
+ const invalidVariables = getInvalidTemplateVariables(url, transaction);
+ if (!isEmpty(invalidVariables)) {
+ return i18n.translate(
+ 'xpack.apm.settings.customizeUI.customLink.preview.contextVariable.noMatch',
+ {
+ defaultMessage:
+ "We couldn't find a value match for {variables} in the example transaction document.",
+ values: {
+ variables: invalidVariables
+ .map(variable => `{{${variable}}}`)
+ .join(', ')
+ }
+ }
+ );
+ }
+ } catch (e) {
+ return i18n.translate(
+ 'xpack.apm.settings.customizeUI.customLink.preview.contextVariable.invalid',
+ {
+ defaultMessage:
+ "We couldn't find an example transaction document due to invalid variable(s) defined."
+ }
);
- // Filter out all items already added, besides the one selected in the current filter.
- return indexUsedFilter === -1 || idx === indexUsedFilter;
- });
+ }
+};
+
+export const replaceTemplateVariables = (
+ url: string,
+ transaction?: Transaction
+) => {
+ const error = validateUrl(url, transaction);
+ try {
+ return { formattedUrl: Mustache.render(url, transaction), error };
+ } catch (e) {
+ // errors will be caught on validateUrl function
+ return { formattedUrl: url, error };
+ }
};
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/index.tsx
index 88358c888160b..68755bad5f652 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/index.tsx
@@ -21,6 +21,8 @@ import { FlyoutFooter } from './FlyoutFooter';
import { LinkSection } from './LinkSection';
import { saveCustomLink } from './saveCustomLink';
import { convertFiltersToArray, convertFiltersToObject } from './helper';
+import { LinkPreview } from './LinkPreview';
+import { Documentation } from './Documentation';
interface Props {
onClose: () => void;
@@ -87,9 +89,17 @@ export const CustomLinkFlyout = ({
'xpack.apm.settings.customizeUI.customLink.flyout.label',
{
defaultMessage:
- 'Links will be available in the context of transaction details throughout the APM app. You can create an unlimited number of links and use the filter options to scope them to only appear for specific services. You can refer to dynamic variables by using any of the transaction metadata to fill in your URLs. TODO: Learn more about it in the docs.'
+ 'Links will be available in the context of transaction details throughout the APM app. You can create an unlimited number of links. You can refer to dynamic variables by using any of the transaction metadata to fill in your URLs. More information, including examples, are available in the'
}
- )}
+ )}{' '}
+
{
const { basePath } = useContext(UptimeSettingsContext);
return (
-
+
diff --git a/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx b/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx
new file mode 100644
index 0000000000000..85961003fce72
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx
@@ -0,0 +1,63 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { ChromeBreadcrumb } from 'kibana/public';
+import React from 'react';
+import { Route } from 'react-router-dom';
+import { mountWithRouter } from '../../lib';
+import { OVERVIEW_ROUTE } from '../../../common/constants';
+import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public';
+import { UptimeUrlParams, getSupportedUrlParams } from '../../lib/helper';
+import { makeBaseBreadcrumb, useBreadcrumbs } from '../../hooks/use_breadcrumbs';
+
+describe('useBreadcrumbs', () => {
+ it('sets the given breadcrumbs', () => {
+ const [getBreadcrumbs, core] = mockCore();
+
+ const expectedCrumbs: ChromeBreadcrumb[] = [
+ {
+ text: 'Crumb: ',
+ href: 'http://href.example.net',
+ },
+ {
+ text: 'Crumb II: Son of Crumb',
+ href: 'http://href2.example.net',
+ },
+ ];
+
+ const Component = () => {
+ useBreadcrumbs(expectedCrumbs);
+ return <>Hello>;
+ };
+
+ mountWithRouter(
+
+
+
+
+
+ );
+
+ const urlParams: UptimeUrlParams = getSupportedUrlParams({});
+ expect(getBreadcrumbs()).toStrictEqual([makeBaseBreadcrumb(urlParams)].concat(expectedCrumbs));
+ });
+});
+
+const mockCore: () => [() => ChromeBreadcrumb[], any] = () => {
+ let breadcrumbObj: ChromeBreadcrumb[] = [];
+ const get = () => {
+ return breadcrumbObj;
+ };
+ const core = {
+ chrome: {
+ setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => {
+ breadcrumbObj = newBreadcrumbs;
+ },
+ },
+ };
+
+ return [get, core];
+};
diff --git a/x-pack/legacy/plugins/uptime/public/hooks/use_breadcrumbs.ts b/x-pack/legacy/plugins/uptime/public/hooks/use_breadcrumbs.ts
new file mode 100644
index 0000000000000..d1cc8e1897386
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/hooks/use_breadcrumbs.ts
@@ -0,0 +1,41 @@
+/*
+ * 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 { ChromeBreadcrumb } from 'kibana/public';
+import { i18n } from '@kbn/i18n';
+import { useEffect } from 'react';
+import { UptimeUrlParams } from '../lib/helper';
+import { stringifyUrlParams } from '../lib/helper/stringify_url_params';
+import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
+import { useUrlParams } from '.';
+
+export const makeBaseBreadcrumb = (params?: UptimeUrlParams): ChromeBreadcrumb => {
+ let href = '#/';
+ if (params) {
+ const crumbParams: Partial = { ...params };
+ // We don't want to encode this values because they are often set to Date.now(), the relative
+ // values in dateRangeStart are better for a URL.
+ delete crumbParams.absoluteDateRangeStart;
+ delete crumbParams.absoluteDateRangeEnd;
+ href += stringifyUrlParams(crumbParams, true);
+ }
+ return {
+ text: i18n.translate('xpack.uptime.breadcrumbs.overviewBreadcrumbText', {
+ defaultMessage: 'Uptime',
+ }),
+ href,
+ };
+};
+
+export const useBreadcrumbs = (extraCrumbs: ChromeBreadcrumb[]) => {
+ const params = useUrlParams()[0]();
+ const setBreadcrumbs = useKibana().services.chrome?.setBreadcrumbs;
+ useEffect(() => {
+ if (setBreadcrumbs) {
+ setBreadcrumbs([makeBaseBreadcrumb(params)].concat(extraCrumbs));
+ }
+ }, [extraCrumbs, params, setBreadcrumbs]);
+};
diff --git a/x-pack/legacy/plugins/uptime/public/pages/__tests__/__snapshots__/page_header.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/pages/__tests__/__snapshots__/page_header.test.tsx.snap
index 30e15ba132996..646bfeba951dd 100644
--- a/x-pack/legacy/plugins/uptime/public/pages/__tests__/__snapshots__/page_header.test.tsx.snap
+++ b/x-pack/legacy/plugins/uptime/public/pages/__tests__/__snapshots__/page_header.test.tsx.snap
@@ -1,12 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`PageHeader shallow renders with breadcrumbs and the date picker: page_header_with_date_picker 1`] = `
+exports[`PageHeader shallow renders extra links: page_header_with_extra_links 1`] = `
Array [
-
-
-
-
-
-
-
-
+
+
-
-
+
-
-
+
+
- Refresh
+
+
+
+
+ Refresh
+
+
+
-
-
-
+
+
+
@@ -149,13 +197,13 @@ Array [
]
`;
-exports[`PageHeader shallow renders with breadcrumbs without the date picker: page_header_no_date_picker 1`] = `
+exports[`PageHeader shallow renders with the date picker: page_header_with_date_picker 1`] = `
Array [
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Last 15 minutes
+
+ Show dates
+
+
+
+
+
+
+
- Alerts
-
-
-
+
+
+
+
+
+ Refresh
+
+
+
+
+
+
+
@@ -202,3 +327,38 @@ Array [
/>,
]
`;
+
+exports[`PageHeader shallow renders without the date picker: page_header_no_date_picker 1`] = `
+Array [
+
+
+
+ TestingHeading
+
+
+
+
+
+
+
+
+
,
+ ,
+]
+`;
diff --git a/x-pack/legacy/plugins/uptime/public/pages/__tests__/page_header.test.tsx b/x-pack/legacy/plugins/uptime/public/pages/__tests__/page_header.test.tsx
index 92dceece3ef40..c9e4eef386764 100644
--- a/x-pack/legacy/plugins/uptime/public/pages/__tests__/page_header.test.tsx
+++ b/x-pack/legacy/plugins/uptime/public/pages/__tests__/page_header.test.tsx
@@ -5,67 +5,36 @@
*/
import React from 'react';
-import { Route } from 'react-router-dom';
-import { PageHeader, makeBaseBreadcrumb } from '../page_header';
-import { mountWithRouter, renderWithRouter } from '../../lib';
-import { OVERVIEW_ROUTE } from '../../../common/constants';
-import { ChromeBreadcrumb } from 'kibana/public';
-import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public';
-import { UptimeUrlParams, getSupportedUrlParams } from '../../lib/helper';
+import { PageHeader } from '../page_header';
+import { renderWithRouter } from '../../lib';
import { Provider } from 'react-redux';
describe('PageHeader', () => {
- const simpleBreadcrumbs: ChromeBreadcrumb[] = [
- { text: 'TestCrumb1', href: '#testHref1' },
- { text: 'TestCrumb2', href: '#testHref2' },
- ];
-
- it('shallow renders with breadcrumbs and the date picker', () => {
+ it('shallow renders with the date picker', () => {
const component = renderWithRouter(
-
+
);
expect(component).toMatchSnapshot('page_header_with_date_picker');
});
- it('shallow renders with breadcrumbs without the date picker', () => {
+ it('shallow renders without the date picker', () => {
const component = renderWithRouter(
-
+
);
expect(component).toMatchSnapshot('page_header_no_date_picker');
});
- it('sets the given breadcrumbs', () => {
- const [getBreadcrumbs, core] = mockCore();
- mountWithRouter(
-
-
-
-
-
-
-
- );
-
- const urlParams: UptimeUrlParams = getSupportedUrlParams({});
- expect(getBreadcrumbs()).toStrictEqual(
- [makeBaseBreadcrumb(urlParams)].concat(simpleBreadcrumbs)
+ it('shallow renders extra links', () => {
+ const component = renderWithRouter(
+
+
+
);
+ expect(component).toMatchSnapshot('page_header_with_extra_links');
});
});
@@ -81,19 +50,3 @@ const MockReduxProvider = ({ children }: { children: React.ReactElement }) => (
{children}
);
-
-const mockCore: () => [() => ChromeBreadcrumb[], any] = () => {
- let breadcrumbObj: ChromeBreadcrumb[] = [];
- const get = () => {
- return breadcrumbObj;
- };
- const core = {
- chrome: {
- setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => {
- breadcrumbObj = newBreadcrumbs;
- },
- },
- };
-
- return [get, core];
-};
diff --git a/x-pack/legacy/plugins/uptime/public/pages/index.ts b/x-pack/legacy/plugins/uptime/public/pages/index.ts
index 3f74bda79bd46..cea47d6ccf79c 100644
--- a/x-pack/legacy/plugins/uptime/public/pages/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/pages/index.ts
@@ -5,4 +5,5 @@
*/
export { MonitorPage } from './monitor';
+export { SettingsPage } from './settings';
export { NotFoundPage } from './not_found';
diff --git a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx
index b9d29ed017a05..5871783dffdeb 100644
--- a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx
+++ b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx
@@ -7,7 +7,6 @@
import { EuiSpacer } from '@elastic/eui';
import React, { useContext, useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
-import { ChromeBreadcrumb } from 'kibana/public';
import { connect, MapDispatchToPropsFunction, MapStateToPropsParam } from 'react-redux';
import { MonitorCharts, PingList } from '../components/functional';
import { UptimeRefreshContext } from '../contexts';
@@ -19,6 +18,7 @@ import { AppState } from '../state';
import { selectSelectedMonitor } from '../state/selectors';
import { getSelectedMonitorAction } from '../state/actions';
import { PageHeader } from './page_header';
+import { useBreadcrumbs } from '../hooks/use_breadcrumbs';
interface StateProps {
selectedMonitor: Ping | null;
@@ -65,10 +65,10 @@ export const MonitorPageComponent: React.FC = ({
useTrackPageview({ app: 'uptime', path: 'monitor', delay: 15000 });
const nameOrId = selectedMonitor?.monitor?.name || selectedMonitor?.monitor?.id || '';
- const breadcrumbs: ChromeBreadcrumb[] = [{ text: nameOrId }];
+ useBreadcrumbs([{ text: nameOrId }]);
return (
<>
-
+
diff --git a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx
index f9184e2a0587f..a8a35fd2681b6 100644
--- a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx
+++ b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx
@@ -21,6 +21,7 @@ import { UptimeThemeContext } from '../contexts';
import { EmptyState, FilterGroup, KueryBar } from '../components/connected';
import { useUpdateKueryString } from '../hooks';
import { PageHeader } from './page_header';
+import { useBreadcrumbs } from '../hooks/use_breadcrumbs';
interface OverviewPageProps {
autocomplete: DataPublicPluginSetup['autocomplete'];
@@ -77,9 +78,10 @@ export const OverviewPageComponent = ({ autocomplete, indexPattern, setEsKueryFi
description: `The text that will be displayed in the app's heading when the Overview page loads.`,
});
+ useBreadcrumbs([]); // No extra breadcrumbs on overview
return (
<>
-
+
diff --git a/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx b/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx
index 56d9ae2d5caa6..821a70c85dc7c 100644
--- a/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx
+++ b/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx
@@ -4,69 +4,63 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { useEffect } from 'react';
-import { ChromeBreadcrumb } from 'kibana/public';
-import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiSpacer } from '@elastic/eui';
+import React from 'react';
+import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiSpacer, EuiButtonEmpty } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
+import { Link } from 'react-router-dom';
import { UptimeDatePicker } from '../components/functional/uptime_date_picker';
-import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
-import { stringifyUrlParams } from '../lib/helper/stringify_url_params';
-import { useUrlParams } from '../hooks';
-import { UptimeUrlParams } from '../lib/helper';
+import { SETTINGS_ROUTE } from '../../common/constants';
import { ToggleAlertFlyoutButton } from '../components/connected';
interface PageHeaderProps {
headingText: string;
- breadcrumbs: ChromeBreadcrumb[];
- datePicker: boolean;
+ extraLinks?: boolean;
+ datePicker?: boolean;
}
-export const makeBaseBreadcrumb = (params?: UptimeUrlParams): ChromeBreadcrumb => {
- let href = '#/';
- if (params) {
- const crumbParams: Partial = { ...params };
- // We don't want to encode this values because they are often set to Date.now(), the relative
- // values in dateRangeStart are better for a URL.
- delete crumbParams.absoluteDateRangeStart;
- delete crumbParams.absoluteDateRangeEnd;
- href += stringifyUrlParams(crumbParams, true);
- }
- return {
- text: i18n.translate('xpack.uptime.breadcrumbs.overviewBreadcrumbText', {
- defaultMessage: 'Uptime',
- }),
- href,
- };
-};
-
-export const PageHeader = ({ headingText, breadcrumbs, datePicker = true }: PageHeaderProps) => {
- const setBreadcrumbs = useKibana().services.chrome?.setBreadcrumbs!;
-
- const params = useUrlParams()[0]();
- useEffect(() => {
- setBreadcrumbs([makeBaseBreadcrumb(params)].concat(breadcrumbs));
- }, [breadcrumbs, params, setBreadcrumbs]);
+export const PageHeader = React.memo(
+ ({ headingText, extraLinks = false, datePicker = true }: PageHeaderProps) => {
+ const datePickerComponent = datePicker ? (
+
+
+
+ ) : null;
- const datePickerComponent = datePicker ? (
-
-
-
- ) : null;
-
- return (
- <>
-
-
-
-