Merge branch 'master' of https://github.com/elastic/kibana into alerting/default-es-index-schema
1
.github/CODEOWNERS
vendored
|
@ -99,6 +99,7 @@
|
|||
/src/plugins/dashboard/ @elastic/kibana-presentation
|
||||
/src/plugins/input_control_vis/ @elastic/kibana-presentation
|
||||
/src/plugins/vis_type_markdown/ @elastic/kibana-presentation
|
||||
/src/plugins/presentation_util/ @elastic/kibana-presentation
|
||||
/test/functional/apps/dashboard/ @elastic/kibana-presentation
|
||||
/x-pack/plugins/canvas/ @elastic/kibana-presentation
|
||||
/x-pack/plugins/dashboard_enhanced/ @elastic/kibana-presentation
|
||||
|
|
|
@ -4581,7 +4581,7 @@
|
|||
"description": [],
|
||||
"source": {
|
||||
"path": "src/core/server/saved_objects/export/errors.ts",
|
||||
"lineNumber": 34
|
||||
"lineNumber": 36
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -4589,7 +4589,7 @@
|
|||
"returnComment": [],
|
||||
"source": {
|
||||
"path": "src/core/server/saved_objects/export/errors.ts",
|
||||
"lineNumber": 34
|
||||
"lineNumber": 36
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -4628,7 +4628,7 @@
|
|||
"description": [],
|
||||
"source": {
|
||||
"path": "src/core/server/saved_objects/export/errors.ts",
|
||||
"lineNumber": 43
|
||||
"lineNumber": 45
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -4641,7 +4641,7 @@
|
|||
"description": [],
|
||||
"source": {
|
||||
"path": "src/core/server/saved_objects/export/errors.ts",
|
||||
"lineNumber": 43
|
||||
"lineNumber": 45
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -4649,7 +4649,7 @@
|
|||
"returnComment": [],
|
||||
"source": {
|
||||
"path": "src/core/server/saved_objects/export/errors.ts",
|
||||
"lineNumber": 43
|
||||
"lineNumber": 45
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -4681,7 +4681,7 @@
|
|||
"description": [],
|
||||
"source": {
|
||||
"path": "src/core/server/saved_objects/export/errors.ts",
|
||||
"lineNumber": 58
|
||||
"lineNumber": 60
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -4689,7 +4689,7 @@
|
|||
"returnComment": [],
|
||||
"source": {
|
||||
"path": "src/core/server/saved_objects/export/errors.ts",
|
||||
"lineNumber": 58
|
||||
"lineNumber": 60
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -36,6 +36,9 @@ experimental[] Retrieve sets of saved objects that you want to import into {kib}
|
|||
|
||||
TIP: You must include `type` or `objects` in the request body.
|
||||
|
||||
NOTE: The <<savedObjects-maxImportExportSize, `savedObjects.maxImportExportSize`>> configuration setting
|
||||
limits the number of saved objects which may be exported.
|
||||
|
||||
[[saved-objects-api-export-request-response-body]]
|
||||
==== Response body
|
||||
|
||||
|
|
|
@ -53,6 +53,11 @@ The request body must include the multipart/form-data type.
|
|||
|
||||
`file`::
|
||||
A file exported using the export API.
|
||||
+
|
||||
NOTE: The <<savedObjects-maxImportExportSize, `savedObjects.maxImportExportSize`>> configuration setting
|
||||
limits the number of saved objects which may be included in this file. Similarly, the
|
||||
<<savedObjects-maxImportPayloadBytes, `savedObjects.maxImportPayloadBytes`>> setting limits the overall
|
||||
size of the file that can be imported.
|
||||
|
||||
[[saved-objects-api-import-response-body]]
|
||||
==== Response body
|
||||
|
|
|
@ -100,6 +100,8 @@ readonly links: {
|
|||
};
|
||||
readonly indexPatterns: {
|
||||
readonly introduction: string;
|
||||
readonly fieldFormattersNumber: string;
|
||||
readonly fieldFormattersString: string;
|
||||
};
|
||||
readonly addData: string;
|
||||
readonly kibana: string;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
```typescript
|
||||
esFilters: {
|
||||
FilterLabel: (props: import("./ui/filter_bar/filter_editor/lib/filter_label").FilterLabelProps) => JSX.Element;
|
||||
FilterItem: (props: import("./ui/filter_bar/filter_item").FilterItemProps) => JSX.Element;
|
||||
FILTERS: typeof FILTERS;
|
||||
FilterStateStore: typeof FilterStateStore;
|
||||
buildEmptyFilter: (isPinned: boolean, index?: string | undefined) => import("../common").Filter;
|
||||
|
|
|
@ -67,6 +67,12 @@ navigate to the NDJSON file that
|
|||
represents the objects to import. By default,
|
||||
saved objects already in {kib} are overwritten.
|
||||
|
||||
NOTE: The <<savedObjects-maxImportExportSize, `savedObjects.maxImportExportSize`>> configuration setting
|
||||
limits the number of saved objects which may be included in this file. Similarly, the
|
||||
<<savedObjects-maxImportPayloadBytes, `savedObjects.maxImportPayloadBytes`>> setting limits the overall
|
||||
size of the file that can be imported.
|
||||
|
||||
|
||||
[float]
|
||||
==== Export
|
||||
|
||||
|
@ -78,6 +84,10 @@ You have two options for exporting saved objects.
|
|||
This action creates an NDJSON with all your saved objects. By default, the NDJSON includes child objects that are related to the saved
|
||||
objects. Exported dashboards include their associated index patterns.
|
||||
|
||||
NOTE: The <<savedObjects-maxImportExportSize, `savedObjects.maxImportExportSize`>> configuration setting
|
||||
limits the number of saved objects which may be exported.
|
||||
|
||||
|
||||
[float]
|
||||
[role="xpack"]
|
||||
[[managing-saved-objects-copy-to-space]]
|
||||
|
|
|
@ -10,8 +10,8 @@ Numeral formatting patterns are used in multiple places in {kib}, including:
|
|||
|
||||
* <<advanced-options, Advanced settings>>
|
||||
* <<field-formatters-numeric, Index pattern formatters>>
|
||||
* <<tsvb-advanced-editor, TSVB>>
|
||||
* <<canvas, Canvas>>
|
||||
* <<tsvb, *TSVB*>>
|
||||
* <<canvas, *Canvas*>>
|
||||
|
||||
The simplest pattern format is `0`, and the default {kib} pattern is `0,0.[000]`.
|
||||
The numeral pattern syntax expresses:
|
||||
|
|
|
@ -163,11 +163,6 @@ This content has moved. See <<discover, **Discover**>>.
|
|||
|
||||
This content has moved. See <<discover, **Discover**>>.
|
||||
|
||||
[role="exclude",id="lens"]
|
||||
== Lens
|
||||
|
||||
This content has moved. See <<create-panels-with-lens>>.
|
||||
|
||||
[role="exclude",id="known-plugins"]
|
||||
== Known plugins
|
||||
|
||||
|
@ -241,7 +236,7 @@ This page has been moved. Refer to <<vega-tutorial-create-a-stacked-area-chart>>
|
|||
[[heatmap-chart]]
|
||||
=== Heatmap Chart
|
||||
|
||||
This page has been moved. Refer to <<types-of-visualization-panels>>.
|
||||
This page has been moved. Refer to <<types-of-visualizations>>.
|
||||
|
||||
[float]
|
||||
[[interface-overview]]
|
||||
|
@ -285,3 +280,9 @@ This content has moved. Refer to <<dashboard, **Dashboard**>>.
|
|||
== Ingest Node Pipelines
|
||||
|
||||
This content has moved. See {ref}/ingest.html[Ingest pipelines].
|
||||
|
||||
|
||||
[role="exclude",id="create-panels-with-timelion"]
|
||||
== Timelion
|
||||
|
||||
This content has moved. refer to <<timelion>>.
|
||||
|
|
35
docs/settings/banners-settings.asciidoc
Normal file
|
@ -0,0 +1,35 @@
|
|||
[role="xpack"]
|
||||
[[banners-settings-kb]]
|
||||
=== Banner settings in {kib}
|
||||
++++
|
||||
<titleabbrev>Banners settings</titleabbrev>
|
||||
++++
|
||||
|
||||
Banners are disabled by default. You need to manually configure them in order to use the feature.
|
||||
|
||||
You can configure the `xpack.banners` settings in your `kibana.yml` file.
|
||||
|
||||
[[general-banners-settings-kb]]
|
||||
==== General banner settings
|
||||
|
||||
[cols="2*<"]
|
||||
|===
|
||||
|
||||
| `xpack.banners.placement`
|
||||
| Set to `header` to enable the header banner. Defaults to `disabled`.
|
||||
|
||||
| `xpack.banners.textContent`
|
||||
| The text to display inside the banner, either plain text or Markdown.
|
||||
|
||||
| `xpack.banners.textColor`
|
||||
| The color for the banner text. Defaults to `#8A6A0A`.
|
||||
|
||||
| `xpack.banners.backgroundColor`
|
||||
| The color of the banner background. Defaults to `#FFF9E8`.
|
||||
|
||||
|===
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The `banners` plugin is a https://www.elastic.co/subscriptions[subscription feature]
|
||||
====
|
|
@ -12,6 +12,7 @@ For more {kib} configuration settings, see <<settings>>.
|
|||
|
||||
include::alert-action-settings.asciidoc[]
|
||||
include::apm-settings.asciidoc[]
|
||||
include::banners-settings.asciidoc[]
|
||||
include::dev-settings.asciidoc[]
|
||||
include::graph-settings.asciidoc[]
|
||||
include::infrastructure-ui-settings.asciidoc[]
|
||||
|
|
|
@ -455,6 +455,20 @@ manner that is inconsistent with `/proc/self/cgroup`.
|
|||
| Override for cgroup cpuacct path when mounted
|
||||
in a manner that is inconsistent with `/proc/self/cgroup`.
|
||||
|
||||
|[[savedObjects-maxImportExportSize]] `savedObjects.maxImportExportSize:`
|
||||
| The maximum count of saved objects that can be imported or exported.
|
||||
This setting exists to prevent the {kib} server from runnning out of memory when handling
|
||||
large numbers of saved objects. It is recommended to only raise this setting if you are
|
||||
confident your server can hold this many objects in memory.
|
||||
*Default: `10000`*
|
||||
|
||||
|[[savedObjects-maxImportPayloadBytes]] `savedObjects.maxImportPayloadBytes:`
|
||||
| The maximum byte size of a saved objects import that the {kib} server will accept.
|
||||
This setting exists to prevent the {kib} server from runnning out of memory when handling
|
||||
a large import payload. Note that this setting overrides the more general
|
||||
<<server-maxPayloadBytes, `server.maxPayloadBytes`>> for saved object imports only.
|
||||
*Default: `26214400`*
|
||||
|
||||
|[[server-basePath]] `server.basePath:`
|
||||
| Enables you to specify a path to mount {kib} at if you are
|
||||
running behind a proxy. Use the <<server-rewriteBasePath, `server.rewriteBasePath`>> setting to tell {kib}
|
||||
|
@ -495,7 +509,7 @@ back end server. To allow remote users to connect, set the value to the IP addre
|
|||
| The number of milliseconds to wait for additional data before restarting
|
||||
the <<server-socketTimeout, `server.socketTimeout`>> counter. *Default: `"120000"`*
|
||||
|
||||
| `server.maxPayloadBytes:`
|
||||
|[[server-maxPayloadBytes]] `server.maxPayloadBytes:`
|
||||
| The maximum payload size in bytes
|
||||
for incoming server requests. *Default: `1048576`*
|
||||
|
||||
|
@ -671,6 +685,7 @@ Valid locales are: `en`, `zh-CN`, `ja-JP`. *Default: `en`*
|
|||
|
||||
include::{kib-repo-dir}/settings/alert-action-settings.asciidoc[]
|
||||
include::{kib-repo-dir}/settings/apm-settings.asciidoc[]
|
||||
include::{kib-repo-dir}/settings/banners-settings.asciidoc[]
|
||||
include::{kib-repo-dir}/settings/dev-settings.asciidoc[]
|
||||
include::{kib-repo-dir}/settings/graph-settings.asciidoc[]
|
||||
include::{kib-repo-dir}/settings/fleet-settings.asciidoc[]
|
||||
|
|
|
@ -126,7 +126,7 @@ image::images/canvas-element-select.gif[Canvas elements]
|
|||
* *{es} documents* — Access your data in {es} without using aggregations. To use, select an index and fields, and optionally enter a query using the <<lucene-query,Lucene Query Syntax>>.
|
||||
Use the *{es} documents* data source when you have low volume datasets, to view raw documents, or to plot exact, non-aggregated values on a chart.
|
||||
|
||||
* *Timelion* — Access your time series data using <<create-panels-with-timelion,*Timelion*>> queries. To use *Timelion* queries, you can enter a query using the <<lucene-query,Lucene Query Syntax>>.
|
||||
* *Timelion* — Access your time series data using <<timelion,*Timelion*>> queries. To use *Timelion* queries, you can enter a query using the <<lucene-query,Lucene Query Syntax>>.
|
||||
+
|
||||
Each element can display a different data source, and pages and workpads often contain multiple data sources.
|
||||
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
[[add-panels-with-advanced-editors]]
|
||||
== Create panels with the advanced editors
|
||||
|
||||
{kib} provides you with three advanced editors that you can use to manually create dashboard panels.
|
||||
|
||||
[float]
|
||||
[[tsvb-advanced-editor]]
|
||||
=== TSVB
|
||||
|
||||
*TSVB* is a time series data visualization editor that allows you to use the full power of the {es} aggregation framework.
|
||||
|
||||
With *TSVB*, you can:
|
||||
|
||||
* Combine an infinite number of <<aggregation-reference,aggregations>> to display your data.
|
||||
* Annotate time series data with timestamped events from an {es} index.
|
||||
* View the data in several types of visualizations, including charts, data tables, and markdown panels.
|
||||
* Display multiple <<index-patterns, index patterns>> in each visualization.
|
||||
* Customize the data with labels and colors.
|
||||
|
||||
image::images/tsvb.png[TSVB UI]
|
||||
|
||||
[float]
|
||||
[[vega-advanced-editor]]
|
||||
=== Custom visualizations
|
||||
|
||||
*Vega* and *Vega-Lite* are visualization grammars that are integrated into {kib} for custom visualizations.
|
||||
|
||||
* *Vega-Lite* — A high-level grammar for rapid analysis
|
||||
|
||||
* *Vega* — A declarative language with support for interactivity
|
||||
|
||||
*Vega* and *Vega-Lite* panels can display one or more data sources, including {es}, Elastic Map Service,
|
||||
URL, or static data, and support <<reference-for-kibana-extensions,{kib} extensions>> that allow you to embed the panels on your dashboard and add interactive tools.
|
||||
|
||||
Use *Vega* or *Vega-Lite* when you want to create visualizations with:
|
||||
|
||||
* Aggregations that use `nested` or `parent/child` mapping
|
||||
* Aggregations without an index pattern
|
||||
* Queries that use custom time filters
|
||||
* Complex calculations
|
||||
* Extracted data from _source instead of aggregations
|
||||
* Scatter charts, sankey charts, and custom maps
|
||||
* An unsupported visual theme
|
||||
|
||||
These grammars have some limitations: they do not support tables, and can't run queries conditionally.
|
||||
|
||||
image::images/vega.png[Vega UI]
|
||||
|
||||
For detailed *Vega* and *Vega-Lite* information and examples, refer to <<resources-and-examples,Resources and examples>>.
|
||||
|
||||
[float]
|
||||
[[timelion-advanced-editor]]
|
||||
=== Timelion
|
||||
|
||||
*Timelion* is driven by a simple expression language that you use to:
|
||||
|
||||
* Retrieve time series data from one or more indices
|
||||
* Perform math across two or more time series
|
||||
* Visualize the results
|
||||
|
||||
image:dashboard/images/timelion.png[Timelion]
|
||||
|
||||
include::tsvb.asciidoc[]
|
||||
include::vega.asciidoc[]
|
||||
include::timelion.asciidoc[]
|
|
@ -1,32 +1,14 @@
|
|||
[[add-aggregation-based-visualization-panels]]
|
||||
== Create aggregation-based visualization panels
|
||||
=== Aggregation-based
|
||||
|
||||
Aggregation-based visualizations are the core {kib} panels, and are not optimized
|
||||
for a specific use case. If you are new to {kib}, <<create-panels-with-lens,Lens>> is recommended as a
|
||||
simpler way to get started.
|
||||
|
||||
The main features that these panel types have compared to other {kib} panel types are:
|
||||
|
||||
* Support for heat map, tag cloud, gauge, and goal chart types
|
||||
* Support for split charts at up to 3 levels of aggregation, more than *Lens* and *TSVB*
|
||||
* Time series data is not required
|
||||
* Ability to use a <<save-open-search,saved search>> as an input
|
||||
* Data table can be sorted, also supports summary row and percentage column features
|
||||
* Can assign specific colors to series
|
||||
* Ability for plugin authors to extend the features
|
||||
|
||||
These panel types also have some limitations:
|
||||
|
||||
* Not as simple as *Lens*
|
||||
* Limited styling options
|
||||
* No support for math
|
||||
* No support for multiple indices
|
||||
for a specific use case.
|
||||
|
||||
[float]
|
||||
[[types-of-visualization-panels]]
|
||||
=== Types of aggregation-based panels
|
||||
[[types-of-visualizations]]
|
||||
==== Types of aggregation-based visualizations
|
||||
|
||||
{kib} supports the following types of aggregation-based panels.
|
||||
{kib} supports the following types of aggregation-based visualizations.
|
||||
|
||||
[cols="50, 50"]
|
||||
|===
|
||||
|
@ -106,13 +88,13 @@ create visual art for a specific topic.
|
|||
|
||||
[float]
|
||||
[[create-aggregation-based-panel]]
|
||||
=== Create an aggregation-based panel
|
||||
==== Create an aggregation-based visualization panel
|
||||
|
||||
Choose the type of panel you want to create, then use the editor to configure the options. Each panel type supports different options.
|
||||
Choose the type of visualization you want to create, then use the editor to configure the options.
|
||||
|
||||
. From the dashboard, click *Create panel*, then click *Aggregation based* on the *New visualization* window.
|
||||
|
||||
.. Click the type of panel you want to create.
|
||||
.. Click the type of visualization you want to create.
|
||||
|
||||
.. Click the data source you want to visualize.
|
||||
|
||||
|
@ -132,13 +114,13 @@ image:images/aggregation-based-color-picker.png[Color picker]
|
|||
|
||||
[float]
|
||||
[[try-it-aggregation-based-panel]]
|
||||
=== Try it: Create an aggregation-based bar chart
|
||||
==== Try it: Create an aggregation-based bar chart
|
||||
|
||||
You collected data from your web server, and you want to visualize and analyze the data on a dashboard. To create a dashboard panel of the data, create
|
||||
a bar chart that displays the top five log traffic sources for every three hours.
|
||||
|
||||
[float]
|
||||
==== Add the data and create the dashboard
|
||||
===== Add the data and create the dashboard
|
||||
|
||||
Add the sample web logs data that you'll use to create the bar chart, then create the dashboard.
|
||||
|
||||
|
@ -151,7 +133,7 @@ Add the sample web logs data that you'll use to create the bar chart, then creat
|
|||
. On the *Dashboards* page, click *Create dashboard*.
|
||||
|
||||
[float]
|
||||
==== Open and set up the aggregation-based bar chart
|
||||
===== Open and set up the aggregation-based bar chart
|
||||
|
||||
Open the bar chart visualization builder and change the time range.
|
||||
|
||||
|
@ -165,7 +147,7 @@ Open the bar chart visualization builder and change the time range.
|
|||
|
||||
[float]
|
||||
[[tutorial-configure-the-bar-chart]]
|
||||
==== Create the bar chart
|
||||
===== Create the bar chart
|
||||
|
||||
To create the bar chart, add a <<bucket-aggregations,bucket aggregation>>, then add the terms sub-aggregation to display the top values.
|
||||
|
||||
|
@ -196,7 +178,7 @@ TIP: Aggregation-based panels support a maximum of three *Split series*.
|
|||
image:images/bar-chart-tutorial-2.png[Bar chart with sample logs data]
|
||||
|
||||
[float]
|
||||
==== Save the panel
|
||||
===== Save the panel
|
||||
|
||||
Save and add the visualization panel to the dashboard.
|
||||
|
||||
|
|
131
docs/user/dashboard/create-panels-with-editors.asciidoc
Normal file
|
@ -0,0 +1,131 @@
|
|||
[[create-panels-with-editors]]
|
||||
== Create panels with editors
|
||||
|
||||
{kib} provides several editors that you can use to create dashboard panels.
|
||||
|
||||
[cols="2"]
|
||||
|===
|
||||
|
||||
| <<lens,*Lens*>>
|
||||
| Create visualizations with the drag and drop editor. *Lens* is recommended for most users.
|
||||
|
||||
| <<maps,*Maps*>>
|
||||
| Create visualizations with your geographical data.
|
||||
|
||||
| <<tsvb,*TSVB*>>
|
||||
| Create visualizations with your time series data.
|
||||
|
||||
| <<vega,*Vega*>>
|
||||
| Create custom visualizations with the *Vega* and *Vega-Lite* grammars.
|
||||
|
||||
| <<add-aggregation-based-visualization-panels,*Aggregation based*>>
|
||||
| Build most visualization types using {es} <<aggregation-reference,aggregations>>.
|
||||
|
||||
| <<timelion,*Timelion*>>
|
||||
| Create visualizations with your time series data using a simple expression language.
|
||||
|
||||
|===
|
||||
|
||||
[float]
|
||||
[[lens-editor]]
|
||||
=== Lens
|
||||
|
||||
*Lens* is the drag and drop editor that creates visualizations of your data.
|
||||
|
||||
With *Lens*, you can:
|
||||
|
||||
* Use the automatically generated suggestions to change the visualization type.
|
||||
* Create visualizations with multiple layers and indices.
|
||||
* Change the aggregation and labels to customize the data.
|
||||
|
||||
[role="screenshot"]
|
||||
image:dashboard/images/lens_advanced_1_1.png[Lens]
|
||||
|
||||
[float]
|
||||
[[tsvb-editor]]
|
||||
=== TSVB
|
||||
|
||||
*TSVB* is a time series data visualization editor that allows you to use the full power of the {es} aggregation framework.
|
||||
|
||||
With *TSVB*, you can:
|
||||
|
||||
* Combine an infinite number of <<aggregation-reference,aggregations>> to display your data.
|
||||
* Annotate time series data with timestamped events from an {es} index.
|
||||
* View the data in several types of visualizations, including charts, data tables, and markdown panels.
|
||||
* Display multiple <<index-patterns, index patterns>> in each visualization.
|
||||
* Customize the data with labels and colors.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/tsvb.png[TSVB UI]
|
||||
|
||||
[float]
|
||||
[[custom-visualizations]]
|
||||
=== Custom visualizations
|
||||
|
||||
*Vega* and *Vega-Lite* are visualization grammars that are integrated into {kib} for custom visualizations.
|
||||
|
||||
* *Vega-Lite* — A high-level grammar for rapid analysis.
|
||||
|
||||
* *Vega* — A declarative language with support for interactivity.
|
||||
|
||||
*Vega* and *Vega-Lite* panels can display one or more data sources, including {es}, Elastic Map Service,
|
||||
URL, or static data, and support <<reference-for-kibana-extensions,{kib} extensions>> that allow you to embed the panels on your dashboard and add interactive tools.
|
||||
|
||||
Use *Vega* or *Vega-Lite* when you want to create visualizations with:
|
||||
|
||||
* Aggregations that use `nested` or `parent/child` mapping
|
||||
* Aggregations without an index pattern
|
||||
* Queries that use custom time filters
|
||||
* Complex calculations
|
||||
* Extracted data from _source instead of aggregations
|
||||
* Scatter charts, sankey charts, and custom maps
|
||||
* An unsupported visual theme
|
||||
|
||||
These grammars have some limitations: they do not support tables, and can't run queries conditionally.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/vega.png[Vega UI]
|
||||
|
||||
For detailed *Vega* and *Vega-Lite* information and examples, refer to <<resources-and-examples,Resources and examples>>.
|
||||
|
||||
[float]
|
||||
[[aggregation-based]]
|
||||
=== Aggregation-based
|
||||
|
||||
With aggregation-based visualizations, you can:
|
||||
|
||||
* Create heat map, tag cloud, gauge, and goal visualizations
|
||||
* Split charts up to three aggregation levels, which is more than *Lens* and *TSVB*
|
||||
* Time series data is not required
|
||||
* Use a <<save-open-search,saved search>> as an input
|
||||
* Sort data tables and use the summary row and percentage column features
|
||||
* Assign colors to series
|
||||
* Extend features with plugins
|
||||
|
||||
[role="screenshot"]
|
||||
image:dashboard/images/aggregation_based.png[Aggregation-based editor]
|
||||
|
||||
Aggregation-based visualizations include the following limitations:
|
||||
|
||||
* Limited styling options
|
||||
* Math is unsupported
|
||||
* Multiple indices is unsupported
|
||||
|
||||
[float]
|
||||
[[timelion-editor]]
|
||||
=== Timelion
|
||||
|
||||
*Timelion* is driven by a simple expression language that you use to:
|
||||
|
||||
* Retrieve time series data from one or more indices
|
||||
* Perform math across two or more time series
|
||||
* Visualize the results
|
||||
|
||||
[role="screenshot"]
|
||||
image:dashboard/images/timelion.png[Timelion]
|
||||
|
||||
include::lens.asciidoc[]
|
||||
include::tsvb.asciidoc[]
|
||||
include::vega.asciidoc[]
|
||||
include::aggregation-based.asciidoc[]
|
||||
include::timelion.asciidoc[]
|
|
@ -12,25 +12,18 @@ then compare the panels side-by-side to identify the patterns and connections in
|
|||
[role="screenshot"]
|
||||
image:images/Dashboard_example.png[Example dashboard]
|
||||
|
||||
[[tsvb]]
|
||||
|
||||
Dashboards support many types of panels, and provide several editors that you can use to create panels.
|
||||
|
||||
[cols="2"]
|
||||
|===
|
||||
|
||||
| <<create-panels-with-lens,Lens>>
|
||||
| The drag and drop editor that creates visualizations of your data. *Lens* is recommended for most users.
|
||||
| <<create-panels-with-editors,Visualization editors>>
|
||||
| Use the *Lens*, *TSVB*, *Vega*, and *Timelion* editors to help you create visualizations of your data, or create aggregation-based visualizations using {es} <<aggregation-reference,aggregations>>.
|
||||
*Lens* is recommended for most users.
|
||||
|
||||
| <<maps,Maps>>
|
||||
| Create beautiful displays of your geographical data.
|
||||
|
||||
| <<add-panels-with-advanced-editors,Advanced editors>>
|
||||
| Visualize time series data with *TSVB* or *Timelion*, or create a custom visualization using *Vega* or *Vega-Lite*.
|
||||
|
||||
| <<add-aggregation-based-visualization-panels,Aggregation-based visualization panels>>
|
||||
| Build most visualization types using {es} <<aggregation-reference,aggregations>>.
|
||||
|
||||
| <<enhance-dashboards,Tools>>
|
||||
| Add context to your panels with <<add-text,text>>, or add dynamic filters with <<add-controls,*Controls*>>.
|
||||
|
||||
|
@ -152,6 +145,8 @@ Add a panel that displays the results from machine learning anomaly detection jo
|
|||
|
||||
. On the *Add from library* flyout, click *Create new*, then select *ML Anomaly Swim Lane*.
|
||||
|
||||
[[tsvb]]
|
||||
|
||||
[float]
|
||||
[[arrange-panels]]
|
||||
[[moving-containers]]
|
||||
|
@ -332,11 +327,16 @@ for *Lens* panels.
|
|||
[role="xpack"]
|
||||
To download *Lens* panel data in a CSV file:
|
||||
|
||||
Open the *Lens* panel menu, then select *More > Download as CSV*.
|
||||
. Open the *Lens* panel menu.
|
||||
|
||||
. Select *More > Download as CSV*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/download_csv_context_menu.png[Download as CSV from panel context menu]
|
||||
|
||||
Each layer produces a single CSV file with columns.
|
||||
When you download multiple layers, the file names combine the visualization and layer index names.
|
||||
|
||||
To download all other panel data in a CSV file:
|
||||
|
||||
. Open the panel menu, then select *Inspect*.
|
||||
|
@ -385,11 +385,11 @@ log in using their {kib} credentials, via reverse proxy, or enable <<anonymous-a
|
|||
To automate {kib}, you can export dashboards as JSON using the <<dashboard-api,import and export dashboard APIs>>. It is important to export dashboards with all references needed.
|
||||
|
||||
--
|
||||
include::lens.asciidoc[]
|
||||
include::tutorial-create-a-dashboard-of-lens-panels.asciidoc[]
|
||||
|
||||
include::advanced-editors.asciidoc[]
|
||||
include::lens-advanced.asciidoc[]
|
||||
|
||||
include::aggregation-based.asciidoc[]
|
||||
include::create-panels-with-editors.asciidoc[]
|
||||
|
||||
include::enhance-dashboards.asciidoc[]
|
||||
|
||||
|
|
BIN
docs/user/dashboard/images/aggregation_based.png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
docs/user/dashboard/images/lens.png
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
docs/user/dashboard/images/lens_advanced_1_1.png
Normal file
After Width: | Height: | Size: 276 KiB |
BIN
docs/user/dashboard/images/lens_advanced_1_1_2.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
docs/user/dashboard/images/lens_advanced_1_2.png
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
docs/user/dashboard/images/lens_advanced_2_1.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
docs/user/dashboard/images/lens_advanced_2_1_1.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
docs/user/dashboard/images/lens_advanced_2_2.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
docs/user/dashboard/images/lens_advanced_2_2_1.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
docs/user/dashboard/images/lens_advanced_3_1.gif
Normal file
After Width: | Height: | Size: 451 KiB |
BIN
docs/user/dashboard/images/lens_advanced_3_1_1.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
docs/user/dashboard/images/lens_advanced_3_2.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
docs/user/dashboard/images/lens_advanced_3_3.png
Normal file
After Width: | Height: | Size: 183 KiB |
BIN
docs/user/dashboard/images/lens_advanced_4_1.png
Normal file
After Width: | Height: | Size: 152 KiB |
BIN
docs/user/dashboard/images/lens_advanced_4_2.png
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
docs/user/dashboard/images/lens_advanced_result.png
Normal file
After Width: | Height: | Size: 458 KiB |
BIN
docs/user/dashboard/images/lens_area_percentage.png
Normal file
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 633 KiB |
BIN
docs/user/dashboard/images/lens_drag_drop_1.gif
Normal file
After Width: | Height: | Size: 8.7 MiB |
BIN
docs/user/dashboard/images/lens_drag_drop_1.png
Normal file
After Width: | Height: | Size: 501 KiB |
BIN
docs/user/dashboard/images/lens_drag_drop_2.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/user/dashboard/images/lens_drag_drop_3.gif
Normal file
After Width: | Height: | Size: 268 KiB |
BIN
docs/user/dashboard/images/lens_fields_indexpattern.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
docs/user/dashboard/images/lens_ip_mixed_sorting.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
docs/user/dashboard/images/lens_ipv4_sorting.png
Normal file
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 347 KiB |
BIN
docs/user/dashboard/images/lens_value_labels_xychart_toggle.png
Normal file
After Width: | Height: | Size: 215 KiB |
259
docs/user/dashboard/lens-advanced.asciidoc
Normal file
|
@ -0,0 +1,259 @@
|
|||
[[create-a-dashboard-of-panels-with-ecommerce-data]]
|
||||
== Tutorial: Create a dashboard of panels with ecommerce sales data
|
||||
|
||||
You collected sales data from your store, and you want to visualize and analyze the data on a dashboard.
|
||||
To create dashboard panels of the data, open the *Lens* visualization builder, then
|
||||
create the visualization panels that best display the data.
|
||||
|
||||
When you've completed the tutorial, you'll have a dashboard that provides you with a complete overview of your ecommerce sales data.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_result.png[Dashboard view]
|
||||
|
||||
[discrete]
|
||||
[[add-the-data-and-create-the-dashboard-advanced]]
|
||||
=== Add the data and create the dashboard
|
||||
|
||||
To create visualizations of the data from your store, add the data set, then create the dashboard.
|
||||
|
||||
. From the {kib} *Home* page, click *Try our sample data*.
|
||||
|
||||
. From *Sample eCommerce orders*, click *Add data*.
|
||||
|
||||
. Open the main menu, then click *Dashboard*.
|
||||
|
||||
. On the *Dashboards* page, click *Create dashboard*.
|
||||
|
||||
[float]
|
||||
[[open-and-set-up-lens-advanced]]
|
||||
=== Open and set up Lens
|
||||
|
||||
Open the *Lens* editor, then make sure the correct fields appear.
|
||||
|
||||
. From the dashboard, click *Create panel*.
|
||||
|
||||
. On the *New visualization* window, click *Lens*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_1_1.png[New visualization popover]
|
||||
|
||||
. Make sure the *kibana_sample_data_ecommerce_* index appears.
|
||||
|
||||
[discrete]
|
||||
[[view-the-number-of-transactions-per-day]]
|
||||
=== View the number of transactions per hour
|
||||
|
||||
To determine the number of orders made every hour, create a bar chart, then add the chart to the dashboard.
|
||||
|
||||
. Set the <<set-time-filter,time filter>> to *Last 30 days*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *Records* to the visualization builder.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_1_1.png[Added records to the workspace]
|
||||
|
||||
. Change the *Vertical axis* title and display the number of orders per day.
|
||||
|
||||
.. In the editor, click *Count of Records*.
|
||||
|
||||
.. In the *Display name* field, enter `Number of orders`.
|
||||
|
||||
.. Click *Add advanced options > Normalize by unit*.
|
||||
|
||||
.. From the *Normalize by unit* dropdown, select *per hour*, then click *Close*.
|
||||
|
||||
. To hide the *Horizontal axis* label, open the *Bottom Axis* menu, then deselect *Show*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_1_1_2.png[Bottom axis menu]
|
||||
+
|
||||
You have a bar chart that shows you how many orders were made at your store every hour.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_1_2.png[Orders per day]
|
||||
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
[[view-the-cumulative-number-of-products-sold-over-time]]
|
||||
=== View the cumulative number of products sold on weekends
|
||||
|
||||
To determine the number of orders made only on Saturday and Sunday, create an area chart, then add it to the dashboard.
|
||||
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Area*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_2_1_1.png[Chart type menu with Area selected]
|
||||
|
||||
. Configure the cumulative sum of the store orders.
|
||||
|
||||
.. From the *Available fields* list, drag and drop *Records* to the visualization builder.
|
||||
|
||||
.. From the editor, click *Count of Records*.
|
||||
|
||||
.. From *Select a function*, click *Cumulative sum*.
|
||||
|
||||
.. In the *Display name* field, enter `Cumulative orders during weekend days`, then click *Close*.
|
||||
|
||||
. Filter the results to display the data for only Saturday and Sunday.
|
||||
|
||||
.. From the editor, click the *Drop a field or click to add* field for *Break down by*.
|
||||
|
||||
.. From *Select a function*, click *Filters*.
|
||||
|
||||
.. Click *All records*.
|
||||
|
||||
.. In the *KQL* field, enter `day_of_week : "Saturday" or day_of_week : "Sunday"`, then press Return.
|
||||
+
|
||||
The <<kuery-query,KQL filter>> displays all documents where `day_of_week` matches `Saturday` or `Sunday`.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_2_1.png[Filter aggregation to filter weekend days]
|
||||
|
||||
. To hide the legend, open the *Legend* menu, then click *Hide*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_2_2_1.png[Legend menu]
|
||||
+
|
||||
You have an area chart that shows you how many orders your store received during the weekend.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_2_2.png[Line chart with cumulative sum of orders made on the weekend]
|
||||
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
[[add-a-data-layer-advanced]]
|
||||
=== Create multiple key percentiles of product prices
|
||||
|
||||
To view the price distribution of products sold over time, create a percentile chart, then add it to the dashboard.
|
||||
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Line*.
|
||||
|
||||
. From the *Available fields* list, drag and drop the data fields to the *Drop a field or click to add* fields in the editor.
|
||||
|
||||
* Drag and drop *products.price* to the *Vertical axis* field.
|
||||
|
||||
* Drag and drop *order_date* to the *Horizontal axis* field.
|
||||
|
||||
. Create the 95th percentile.
|
||||
|
||||
.. In the editor, click *Median of products.price*.
|
||||
|
||||
.. From *Select a function*, click *Percentile*.
|
||||
|
||||
.. In the *Display name* field, enter `95th`, then click *Close*.
|
||||
|
||||
. To create the 90th percentile, duplicate the `95th` percentile.
|
||||
|
||||
.. Drag and drop *95th* to *Drop a field or click to add*.
|
||||
|
||||
.. Click *95th [1]*, then enter `90` in the *Percentile* field.
|
||||
|
||||
.. In the *Display name* field enter `90th`, then click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_3_1.gif[Easily duplicate the items with drag and drop]
|
||||
|
||||
. Create the 50th percentile.
|
||||
|
||||
.. Drag and drop *90th* to *Drop a field or click to add*.
|
||||
|
||||
.. Click *90th [1]*, then enter `50` in the *Percentile* field.
|
||||
|
||||
.. In the *Display name* field enter `50th`, then click *Close*.
|
||||
|
||||
. Create the 10th percentile.
|
||||
|
||||
.. Drag and drop *50th* to *Drop a field or click to add*.
|
||||
|
||||
.. Click *50th [1]*, then enter `10` in the *Percentile* field.
|
||||
|
||||
.. In the *Display name* field enter `10th`, then click *Close*.
|
||||
|
||||
. To change the left axis label, open the *Left Axis* menu, then enter `Percentiles for product prices` in the *Axis name* field.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_3_1_1.png[Left Axis menu]
|
||||
+
|
||||
You have a line chart that shows you the price distribution of products sold over time.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_3_3.png[Percentiles for product prices chart]
|
||||
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
[[add-the-response-code-filters-advanced]]
|
||||
=== View the moving average of inventory prices
|
||||
|
||||
To view and analyze the prices of shoes, accessories, and clothing in the store inventory, create a line chart.
|
||||
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Line*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *products.price* to the visualization builder.
|
||||
|
||||
. In the editor, click the *Drop a field or click to add* field for *Break down by*.
|
||||
|
||||
. From *Select a function*, click *Filters*.
|
||||
|
||||
. Add a filter for shoes.
|
||||
|
||||
.. Click *All records*.
|
||||
|
||||
.. In the *KQL* field, enter `category.keyword : *Shoes*`.
|
||||
|
||||
.. In the *Label* field, enter `Shoes`, then press Return.
|
||||
|
||||
. Add a filter for accessories.
|
||||
|
||||
.. Click *Add a filter*.
|
||||
|
||||
.. In the *KQL* field, enter `category.keyword : *Accessories*`.
|
||||
|
||||
.. In the *Label* field, enter `Accessories`, then press Return.
|
||||
|
||||
. Add a filter for clothing.
|
||||
|
||||
.. Click *Add a filter*.
|
||||
|
||||
.. In the *KQL* field, enter `category.keyword : *Clothing*`.
|
||||
|
||||
.. In the *Label* field, enter `Clothing`, then press Return.
|
||||
|
||||
. Click *Close*
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_4_1.png[Median prices chart for different categories]
|
||||
|
||||
[discrete]
|
||||
[[add-the-moving-average]]
|
||||
==== Add the moving average
|
||||
|
||||
To focus on the general trends rather than on the peaks in the data, add the moving average, then add the visualization to the dashboard.
|
||||
|
||||
. In the editor, click the *Median of products.price*.
|
||||
|
||||
. From *Select a function*, click *Moving average*.
|
||||
|
||||
. In the *Window size* field, enter `7`, then click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_advanced_4_2.png[Moving average prices chart for different categories]
|
||||
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
=== Save the dashboard
|
||||
|
||||
Now that you have a complete overview of your ecommerce sales data, save the dashboard.
|
||||
|
||||
. In the toolbar, click *Save*.
|
||||
|
||||
. On the *Save dashboard* window, enter `Ecommerce sales data`, then click *Save*.
|
Before Width: | Height: | Size: 190 KiB |
Before Width: | Height: | Size: 67 KiB |
|
@ -1,436 +1,222 @@
|
|||
[[create-a-dashboard-of-panels-with-web-server-data]]
|
||||
== Tutorial: Create a dashboard of panels with web server data
|
||||
[[lens]]
|
||||
=== Lens
|
||||
|
||||
You collected data from your web server, and you want to visualize and analyze the data on a dashboard. To create dashboard panels of the data, open the *Lens* visualization builder, then
|
||||
create the visualization panels that best display the data.
|
||||
To create visualizations with *Lens*, you drag and drop data fields onto the visualization builder,
|
||||
then *Lens* uses heuristics to apply each field.
|
||||
|
||||
[discrete]
|
||||
[[add-the-data-and-create-the-dashboard]]
|
||||
=== Add the data and create the dashboard
|
||||
|
||||
To create visualizations of the data from the web server, add the data set, then create the dashboard.
|
||||
|
||||
. From the {kib} *Home* page, click *Try our sample data*.
|
||||
|
||||
. From *Sample web logs*, click *Add data*.
|
||||
|
||||
. Open the main menu, click *Dashboard*.
|
||||
|
||||
. Click *Create dashboard*.
|
||||
[role="screenshot"]
|
||||
image:dashboard/images/lens.png[Lens]
|
||||
|
||||
[float]
|
||||
[[open-and-set-up-lens]]
|
||||
=== Open and set up Lens
|
||||
[[lens-required-choices]]
|
||||
==== Open and set up Lens
|
||||
|
||||
With *Lens*, you identify the data fields you want to visualize, drag and drop the fields, then watch as
|
||||
*Lens* uses heuristics to apply the fields and create a visualization for you.
|
||||
Open *Lens*, then explore the fields in your data. The list of fields are determined by the index pattern and time filter.
|
||||
|
||||
. From the dashboard, click *Create panel*.
|
||||
. On the dashboard, click *Create panel*.
|
||||
|
||||
. On the *New visualization* window, click *Lens*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_1_1.png[New visualization popover]
|
||||
|
||||
. Make sure the *kibana_sample_data_logs* index appears.
|
||||
. <<set-time-filter,Set the time filter>>.
|
||||
|
||||
. To view the fields in the a different index pattern, click the index pattern, then select a different index pattern from the dropdown.
|
||||
|
||||
. Scan through the list of fields to see what’s in your data.
|
||||
+
|
||||
The list of fields are dependent on the <<index-patterns,index pattern>>, <<set-time-filter,time filter>>, and field filters.
|
||||
TIP: For sparse datasets, *Empty fields* can contain data, which you can use to create visualizations.
|
||||
|
||||
. To filter the data fields, use the following options:
|
||||
|
||||
* Enter the field name in the *Search field names* field.
|
||||
|
||||
* Click *Field by type*, then select the filter. To show all fields in the index pattern, deselect *Only show fields with data*.
|
||||
|
||||
[float]
|
||||
[[view-the-data-summaries]]
|
||||
=== View the data summaries
|
||||
===== View the data summaries
|
||||
|
||||
For each field, *Lens* shows a summary depending on the type of data. Date fields show the time distribution, string fields show the top 10 values,
|
||||
and numeric fields show a detailed summary with the top 10 values and a value distribution.
|
||||
For each field, *Lens* displays a summary depending on the type of data. To analyze the fields, *Lens* uses a sample of 5,000 documents.
|
||||
Each summary displays the percentage of sampled documents over all available documents.
|
||||
|
||||
To view the data summary for a field, click *i* next to the field.
|
||||
To view a data summary, click *i* next to the field.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/lens_data_info_documents.png[Data summary analyzed documents]
|
||||
|
||||
*Lens* uses a sample of 5,000 documents to perform the field analysis. The bottom line of the summary shows the percentage of sampled documents over all available documents.
|
||||
Each data type display the following summaries:
|
||||
|
||||
When *Lens* presents the top 10 values distribution, it also shows the percentage of *Other* values. For array value fields, the percentage distribution considers each value in the array as separate.
|
||||
* *Date* — Displays the time distribution.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/lens_data_info.png[Data summary window with Other]
|
||||
* *String* — Displays the top 10 values.
|
||||
|
||||
NOTE: The sum of all the *Other* fields can equal more than 100% by a small amount.
|
||||
* *Numeric* — Displays the top 10 values and a value distribution. When *Lens* displays the top 10 values distribution, the percentage of *Other* values is also displayed.
|
||||
For array value fields, the percentage distribution considers each value in the array as separate.
|
||||
|
||||
[discrete]
|
||||
[[view-the-number-of-website-visitors]]
|
||||
=== View the number of website visitors
|
||||
|
||||
To determine how many users have visited your website within the last 90 days, create a metric visualization, then add it to the dashboard.
|
||||
|
||||
. Set the <<set-time-filter,time filter>> to *Last 90 days*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Metric*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_1_2_1.png[Chart Type dropdown with Metric selected]
|
||||
|
||||
. From the *Available fields* list, drag and drop *clientip* to the visualization builder.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_1_3.png[Changed type and dropped clientip field]
|
||||
|
||||
. From the editor, click *Unique count of clientip*.
|
||||
|
||||
.. In the *Display name* field, enter `Unique visitors`.
|
||||
|
||||
.. Click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_1_4.png[Flyout config open]
|
||||
|
||||
. *Save* the panel, enter `Unique visitors` in the *Title* field, then add the panel to the dashboard.
|
||||
|
||||
[discrete]
|
||||
[[view-the-distribution-of-visitors-by-operating-system]]
|
||||
=== View the distribution of visitors by operating system
|
||||
|
||||
To determine the operating systems you should continue to support, and the importance of mobile traffic from iOS devices,
|
||||
create a donut chart that displays the top operating systems that your visitors used to access your website within the last 90 days.
|
||||
|
||||
. Open *Lens*, then set the <<set-time-filter,time filter>> to *Last 90 days*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Donut*.
|
||||
|
||||
. From the *Available fields* list, drag and drop the data fields to the *Drop a field or click to add* fields in the editor.
|
||||
|
||||
.. Drag and drop *clientip* to the *Size by* field.
|
||||
|
||||
.. Drag and drop *machine.os.keyword* to the *Slice by* field.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_2_1_1.png[Donut chart with clientip and machine.os.keyword fields]
|
||||
|
||||
. Change the color palette.
|
||||
|
||||
.. From the editor, click *Top values of machine.os.keyword*.
|
||||
|
||||
.. From the *Color palette* dropdown, select *Compatibility*.
|
||||
|
||||
.. Click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_2_1.png[Donut chart with open config panel]
|
||||
|
||||
. *Save* the panel, enter `Visitors by OS` in the *Title* field, then add the panel to the dashboard.
|
||||
|
||||
[discrete]
|
||||
[[mixed-multiaxis]]
|
||||
=== View the average of bytes transfer per day
|
||||
|
||||
To prevent potential server failures, and optimize the cost of website maintenance, create an area chart that displays the average of bytes transfer. To compare
|
||||
the data to the number of visitors to your website, add a line chart layer.
|
||||
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *bytes* to the visualization builder.
|
||||
|
||||
. To zoom in on the data you want to view, click and drag your cursor across the bars.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_1_1.gif[Zoom in on the data]
|
||||
|
||||
. Change the *timestamp* interval.
|
||||
|
||||
.. From the editor, click *timestamp*.
|
||||
|
||||
.. Select *Customize time interval*.
|
||||
|
||||
.. Change the *Minimum interval* to `1 days`, then click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_1.png[Customize time interval]
|
||||
|
||||
. From the *Chart Type* dropdown, select *Area*.
|
||||
|
||||
[discrete]
|
||||
[[add-a-data-layer]]
|
||||
==== Add the line chart layer
|
||||
|
||||
To compare the average of bytes transfer to the number of users that visit your website, add a line chart layer.
|
||||
|
||||
. From the editor, click *+*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_2.png[Add new layer button]
|
||||
|
||||
. From the new layer editor, click the *Chart type* dropdown, then click the line chart.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_3.png[Change layer type]
|
||||
+
|
||||
The chart type for the visualization changes to *Mixed XY*.
|
||||
|
||||
. From the *Available fields* list, drag and drop the data fields to the *Drop a field or click to add* fields in the editor.
|
||||
|
||||
.. Drag and drop *timestamp* to the *Horizontal axis* field.
|
||||
|
||||
.. Drag and drop *clientip* to the *Vertical axis* field.
|
||||
|
||||
. Change the *timestamp* interval.
|
||||
|
||||
.. From the editor, click *timestamp* in the line chart layer.
|
||||
|
||||
.. Select *Customize time interval*.
|
||||
|
||||
.. Change the *Minimum interval* to `1 days`, then click *Close*.
|
||||
|
||||
. Change the *Unique count of clientip* label and color.
|
||||
|
||||
.. From the editor, click *Unique count of clientip*.
|
||||
|
||||
.. In the *Display name* field, enter `Unique visitors` in the line chart layer.
|
||||
|
||||
.. In the *Series color* field, enter *#CA8EAE*, then click *Close*.
|
||||
|
||||
[discrete]
|
||||
[[configure-the-multiaxis-chart]]
|
||||
==== Configure the y-axes
|
||||
|
||||
There is a significant difference between the *timestamp per day* and *Unique visitors* data, which makes the *Unique visitors* data difficult to read. To improve the readability,
|
||||
display the *Unique visitors* data along a second y-axis, then change the formatting. When functions contain multiple formats, separate axes are created by default.
|
||||
|
||||
. From the editor, click *Unique visitors* in the line chart layer.
|
||||
|
||||
. For *Axis side*, click *Right*, then click *Close*.
|
||||
TIP: *Other* can equal more than 100% by a small amount.
|
||||
|
||||
[float]
|
||||
[[change-the-visualization-type]]
|
||||
==== Change the visualization type
|
||||
[[create-the-visualization-panel]]
|
||||
==== Create the visualization panel
|
||||
|
||||
. From the editor, click *Average of bytes* in the area chart layer.
|
||||
Drag and drop the fields on to the visualization builder, then
|
||||
|
||||
. From the *Value format* dropdown, select *Bytes (1024)*, then click *Close*.
|
||||
. Drag and drop the fields to the visualization builder.
|
||||
|
||||
. To change the visualization type, use the following options:
|
||||
|
||||
* Click the *Suggestions*.
|
||||
|
||||
* From the *Chart Type* dropdown, click the visualization.
|
||||
|
||||
. To configure the data, use the editor, then click *Close*.
|
||||
|
||||
. To configure the visualization, use the dropdown menus.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_4.png[Multiaxis chart]
|
||||
|
||||
[discrete]
|
||||
[[lens-legend-position]]
|
||||
==== Change the legend position
|
||||
|
||||
The visualization is done, but the legend uses a lot of space. Change the legend position to the top of the chart.
|
||||
|
||||
. From the *Legend* dropdown, select the top position.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_5.png[legend position]
|
||||
|
||||
. *Save* the panel, enter `Average Bytes vs. Unique Visitors` in the *Title* field, then add the panel to the dashboard.
|
||||
|
||||
[discrete]
|
||||
[[percentage-stacked-area]]
|
||||
=== View the health of your website
|
||||
|
||||
To detect unusual traffic, bad website links, and server errors, create a percentage stacked area chart that displays the associated response codes.
|
||||
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Available fields* list, drag and drop the data fields to the *Drop a field or click to add* fields in the editor.
|
||||
|
||||
.. Drag and drop *Records* to the *Vertical axis* field.
|
||||
|
||||
.. Drag and drop *@timestamp* to the *Horizontal axis* field.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Percentage bar*.
|
||||
|
||||
. To remove the vertical axis label, click *Left axis*, then deselect *Show*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_4_3.png[Turn off axis name]
|
||||
|
||||
[discrete]
|
||||
[[add-the-response-code-filters]]
|
||||
==== Add the response code filters
|
||||
|
||||
For each response code that you want to display, create a filter.
|
||||
|
||||
. From the editor, click the *Drop a field or click to add* field for *Break down by*.
|
||||
|
||||
. From *Select a function*, click *Filters*.
|
||||
|
||||
. Add the filter for the successful response codes.
|
||||
|
||||
.. Click *All records*.
|
||||
|
||||
.. In the *KQL* field, enter `response.keyword>=200 AND response.keyword<300`.
|
||||
|
||||
.. In the *Label* field, enter `2XX`, then press Return.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_4_1.png[First filter in filters aggregation]
|
||||
|
||||
. Add the filter for the redirect codes.
|
||||
|
||||
.. Click *Add a filter*.
|
||||
|
||||
.. In the *KQL* field, enter `response.keyword>=300 AND response.keyword<400`.
|
||||
|
||||
.. In the *Label* field, enter `3XX`, then press Return.
|
||||
|
||||
. Add the filter for the client error codes.
|
||||
|
||||
.. Click *Add a filter*.
|
||||
|
||||
.. In the *KQL* field, enter `response.keyword>=400 AND response.keyword<500`.
|
||||
|
||||
.. In the *Label* field, enter `4XX`, then press Return.
|
||||
|
||||
. Add the filter for the server error codes.
|
||||
|
||||
.. Click *Add a filter*.
|
||||
|
||||
.. In the *KQL* field, enter `response.keyword>=500 AND response.keyword<600`.
|
||||
|
||||
.. In the *Label* field, enter `5XX`, then press Return.
|
||||
|
||||
. To change the color palette, select *Status* from the *Color palette* dropdown, then click *Close*.
|
||||
|
||||
. *Save* the panel, enter `Response Codes Over Time` in the *Title* field, then add the panel to the dashboard.
|
||||
|
||||
[discrete]
|
||||
[[histogram]]
|
||||
=== View the traffic for your website by the hour
|
||||
|
||||
To find the best time to shut down your website for maintenance, create a histogram that displays the traffic for your website by the hour.
|
||||
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *bytes* to *Vertical axis* in the editor, then configure the options.
|
||||
|
||||
.. Click *Average of bytes*.
|
||||
|
||||
.. From *Select a function*, click *Sum*.
|
||||
|
||||
.. In the *Display name* field, enter `Transferred bytes`.
|
||||
|
||||
.. From the *Value format* dropdown, select `Bytes (1024)`, then click *Close*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *hour_of_day* to *Horizontal axis* in the editor, then configure the options.
|
||||
|
||||
.. Click *hour_of_day*.
|
||||
|
||||
.. Click and slide the *Intervals granularity* slider until the horizontal axis displays hourly intervals.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_5_2.png[Create custom ranges]
|
||||
|
||||
. *Save* the panel, enter `Hourly Traffic Distribution` in the *Title* field, then add the panel to the dashboard.
|
||||
|
||||
[discrete]
|
||||
[[custom-ranges]]
|
||||
=== View the percent of small versus large transferred files
|
||||
|
||||
To determine if your users transfer more small files versus large files, create a pie chart that displays the percentage of each size.
|
||||
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *bytes* to *Vertical axis* in the editor, then configure the options.
|
||||
|
||||
.. Click *Average of bytes*.
|
||||
|
||||
.. From *Select a function*, click *Sum*, then click *Close*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *bytes* to *Break down by* in the editor, then specify the file size ranges.
|
||||
|
||||
.. Click *bytes*.
|
||||
|
||||
.. Click *Create custom ranges*, enter the following, then press Return:
|
||||
|
||||
* *Ranges* — `0` -> `10240`
|
||||
|
||||
* *Label* — `Below 10KB`
|
||||
|
||||
.. Click *Add range*, enter the following, then press Return:
|
||||
|
||||
* *Ranges* — `10240` -> `+∞`
|
||||
|
||||
* *Label* — `Above 10KB`
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_6_1.png[Custom ranges configuration]
|
||||
|
||||
.. From the *Value format* dropdown, select *Bytes (1024)*, then click *Close*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Pie*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_6_2.png[Files size distribution]
|
||||
|
||||
. *Save* the panel, enter `File size distribution` in the *Title* field, then add the panel to the dashboard.
|
||||
|
||||
[discrete]
|
||||
[[treemap]]
|
||||
=== View the top sources of website traffic
|
||||
|
||||
To determine how users find out about your website and where your users are located, create a treemap that displays the percentage of users that
|
||||
enter your website from specific social media websites, and the top countries where users are located.
|
||||
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Treemap*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *Records* to the *Size by* field in the editor.
|
||||
|
||||
. From the editor, click the *Drop a field or click to add* field for *Group by*, then create a filter for each website traffic source.
|
||||
|
||||
.. From *Select a function*, click *Filters*.
|
||||
|
||||
.. Click *All records*, enter the following, then press Return:
|
||||
|
||||
* *KQL* — `referer : *facebook.com*`
|
||||
|
||||
* *Label* — `Facebook`
|
||||
|
||||
.. Click *Add a filter*, enter the following, then press Return:
|
||||
|
||||
* *KQL* — `referer : *twitter.com*`
|
||||
|
||||
* *Label* — `Twitter`
|
||||
|
||||
.. Click *Add a filter*, enter the following, then press Return:
|
||||
|
||||
* *KQL* — `NOT referer : *twitter* OR NOT referer: *facebook.com*`
|
||||
|
||||
* *Label* — `Other`
|
||||
|
||||
.. Click *Close*.
|
||||
|
||||
[discrete]
|
||||
[[add-the-countries]]
|
||||
==== Add the geographic data
|
||||
|
||||
To determine the top countries where users are located, add the geographic data.
|
||||
|
||||
Compare the top sources of website traffic data to the top three countries.
|
||||
|
||||
. From the *Available fields* list, drag and drop *geo.src* to the visualization builder.
|
||||
|
||||
. To change the *Group by* order, click and drag *Top values of geo.src* so that it appears first in the editor.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_7_2.png[Treemap vis]
|
||||
|
||||
. To view only the Facebook and Twitter data, remove the *Other* category.
|
||||
|
||||
.. From the editor, click *Top values of geo.src*.
|
||||
|
||||
.. From the *Advanced* dropdown, deselect *Group other values as "Other"*, then click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_7_3.png[Group other values as Other]
|
||||
|
||||
. *Save* the panel, enter `Traffic Source For Top 3 Countries` in the *Title* field, then add the panel to the dashboard.
|
||||
image::images/lens_value_labels_xychart_toggle.png[Lens Bar chart value labels menu]
|
||||
|
||||
[float]
|
||||
== What's next?
|
||||
[[drag-and-drop-keyboard-navigation]]
|
||||
===== Create visualization panels with keyboard navigation
|
||||
|
||||
Your dashboard is complete and provides you with an overall picture of the data from your web server.
|
||||
*Lens* has a fully accessible, continuously improved drag and drop system, which allows you to use a keyboard instead of a mouse.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_dashboard.png[Final dashboard vis]
|
||||
image::images/lens_drag_drop_1.gif[Presented Lens drag and drop]
|
||||
|
||||
. Set a focus on the chosen item. Most of the draggable elements have two focus states. The inner focus state opens a panel with detailed information or options.
|
||||
The outer focus state allows you to drag an item. Tab through the page until you get the outer focus state on the chosen item:
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_drag_drop_2.png[Lens drag and drop focus state]
|
||||
|
||||
. Complete the following actions:
|
||||
|
||||
* To start dragging an item, press Space bar.
|
||||
|
||||
* To select where you want to drop the item, use the Left and Right arrows.
|
||||
|
||||
* To reorder the fields in the group, use Up and Down arrows.
|
||||
|
||||
* To duplicate an operation, use the Left and Right arrows to select the `Drop a field or click to add` in the same group.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_drag_drop_3.gif[Using drag and drop to reorder]
|
||||
|
||||
. Press Space bar to confirm, or to cancel, press Esc.
|
||||
|
||||
[float]
|
||||
[[lens-faq]]
|
||||
==== Frequently asked questions
|
||||
|
||||
For the answers to common *Lens* questions, review the following.
|
||||
|
||||
[float]
|
||||
[[kql-]]
|
||||
===== When should I use the Filter function instead of KQL filters?
|
||||
|
||||
The easiest way to apply KQL filters is to use <<semi-structured-search>>, but you can also use the *Filters* function in the following scenarios:
|
||||
|
||||
* When you want to apply more than one KQL filter to the visualization.
|
||||
|
||||
* When you want to apply the KQL filter to a single layer, which allows you to visualize filtered and unfiltered data.
|
||||
|
||||
[float]
|
||||
[[when-should-i-normalize-the-data-by-unit-or-use-a-custom-interval]]
|
||||
===== When should I normalize the data by unit or use a custom interval?
|
||||
|
||||
* *Normalize by unit* — Calculates the average for the specified interval. When you normalize the data by unit, the data appears less granular, but *Lens* is able to calculate the data faster.
|
||||
|
||||
* *Customize time interval* — Creates a bucket for each specified interval. When you customize the time interval, you can use a large time range, but *Lens* calculates the data slower.
|
||||
|
||||
To normalize the interval:
|
||||
|
||||
. In the editor, click a field.
|
||||
|
||||
. Click *Add advanced options > Normalize by unit*.
|
||||
|
||||
. From the *Normalize by unit* dropdown, select an option, then click *Close*.
|
||||
|
||||
To create a custom interval:
|
||||
|
||||
. In the editor, click a field.
|
||||
|
||||
. Select *Customize time interval*.
|
||||
|
||||
. Change the *Minimum interval*, then click *Close*.
|
||||
|
||||
[float]
|
||||
[[can-i-show-value-labels-for-my-chart]]
|
||||
===== How do I display value labels?
|
||||
|
||||
A subset of *Lens* visualizations support value labels.
|
||||
|
||||
* *Bar* and *Horizontal Bar*
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_value_labels_xychart_toggle.png[Lens Bar chart value labels menu]
|
||||
|
||||
* *Pie*, *Donut*, and *Treemap*
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_value_labels_partition_toggle.png[Lens Pie chart value labels menu]
|
||||
|
||||
[float]
|
||||
[[what-is-the-other-category]]
|
||||
===== What data is categorized as Other?
|
||||
|
||||
The *Other* category contains all of the documents that do not match the specified criteria or filters.
|
||||
Use *Other* when you want to compare a value, or multiple values, to a whole.
|
||||
By default, *Group other values as "Other"* is enabled when you select the *Top values* function.
|
||||
|
||||
To disable *Group other values as "Other"*:
|
||||
|
||||
. In the editor, click *Advanced*.
|
||||
|
||||
. Deselect *Group other values as "Other"*.
|
||||
|
||||
[float]
|
||||
[[how-can-i-include-documents-without-the-field-in-the-operation]]
|
||||
===== How can I include documents without the field?
|
||||
|
||||
By default, *Lens* retrieves only the documents from the specified field.
|
||||
For bucket aggregations, such as *Top values*, you can choose to include documents that do not contain the specified field,
|
||||
which is helpful when you want to compare to the whole documentation set.
|
||||
|
||||
. In the editor, click *Advanced*.
|
||||
|
||||
. Select *Include documents without this field*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_bucketed_aggregation_advanced_dropdown.png[Lens Advanced options for bucketed aggregations]
|
||||
|
||||
[float]
|
||||
[[is-it-possible-to-select-color-for-specific-bar-or-point]]
|
||||
===== How do I change the color for a single data point?
|
||||
|
||||
*Lens* provides you with color pallettes that you can apply to the entire visualization, but you are unable to change the color for a single data point, such as a bar or line.
|
||||
|
||||
[float]
|
||||
[[can-i-sort-by-multiple-columns]]
|
||||
===== How do I sort by multiple columns?
|
||||
|
||||
Multiple column sorting is unsupported in *Lens*, but is supported in *Discover*. For information on how to sort multiple columns in *Discover*,
|
||||
refer to <<explore-fields-in-your-data,Explore the fields in your data>>.
|
||||
|
||||
[float]
|
||||
[[is-it-possible-to-sort-dimensions-in-a-chart]]
|
||||
===== How do I sort the dimensions in a chart?
|
||||
|
||||
Sorting dimensions in visualizations is unsupported in *Lens*.
|
||||
|
||||
[float]
|
||||
[[is-it-possible-to-use-saved-serches-in-lens]]
|
||||
===== How do I visualize saved searches?
|
||||
|
||||
Visualizing saved searches in unsupported in *Lens*.
|
||||
|
||||
[float]
|
||||
[[is-it-possible-to-decrease-or-increase-the-number-of-suggestions]]
|
||||
===== How do I change the number of suggestions?
|
||||
|
||||
Configuring the *Suggestions* that *Lens* automatically populates is unsupported.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[[create-panels-with-timelion]]
|
||||
[[timelion]]
|
||||
=== Timelion
|
||||
|
||||
Instead of using a visual editor to create charts, you define a graph by chaining functions together, using the *Timelion*-specific syntax.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[[TSVB]]
|
||||
[[tsvb]]
|
||||
=== TSVB
|
||||
|
||||
*TSVB* enables you to visualize the data from multiple data series, supports <<aggregation-reference,
|
||||
|
@ -135,7 +135,7 @@ current time is 9:41, *TSVB* displays only the last 10 minutes — from 9:30
|
|||
[float]
|
||||
===== How do I calculate the difference between two data series?
|
||||
|
||||
Performing math across data series is unsupported in *TSVB*. To calculate the difference between two data series, use <<create-panels-with-timelion, Timelion>> or <<vega, Vega>>.
|
||||
Performing math across data series is unsupported in *TSVB*. To calculate the difference between two data series, use <<timelion, *Timelion*>> or <<vega, *Vega*>>.
|
||||
|
||||
[float]
|
||||
===== How do I compare the current versus previous month?
|
||||
|
@ -156,7 +156,7 @@ The ability to calculate a month over month change is not fully supported in *TS
|
|||
time filter is set to 3 months or more _and_ the *Interval* is `1m`. Use the *Derivative* to get the absolute monthly change. To convert to a percent,
|
||||
add the *Math* function with the `params.current / (params.current - params.derivative)` formula, then select *Percent* from the *Data Formatter* dropdown.
|
||||
|
||||
For other types of month over month calculations, use <<create-panels-with-timelion, Timelion>> or <<vega, Vega>>.
|
||||
For other types of month over month calculations, use <<timelion, *Timelion*>> or <<vega, *Vega*>>.
|
||||
|
||||
[float]
|
||||
===== How do I calculate the duration between the start and end of an event?
|
||||
|
|
|
@ -1,43 +1,81 @@
|
|||
[float]
|
||||
[[lens-end-to-end]]
|
||||
== Tutorial: Analyze website data on a dashboard
|
||||
[[create-a-dashboard-of-panels-with-web-server-data]]
|
||||
== Tutorial: Create a dashboard of panels with web server data
|
||||
|
||||
Most dashboards use similar types of analysis to answer key questions. In this tutorial you will base your analysis off of {kib} sample data which resembles logs from the Apache web server.
|
||||
You collected data from your web server, and you want to visualize and analyze the data on a dashboard. To create dashboard panels of the data, open the *Lens* visualization builder, then
|
||||
create the visualization panels that best display the data.
|
||||
|
||||
When you're finished creating the dashboard, you'll be able to answer the following questions:
|
||||
When you've completed the tutorial, you'll have a dashboard that provides you with a complete overview of your web server data.
|
||||
|
||||
* How many users have visited your website?
|
||||
* What is the distribution of visitors by operating system?
|
||||
* What is the average of bytes transfer per day?
|
||||
* What is the health of your website?
|
||||
* What is the traffic for your website by the hour?
|
||||
* What is the percentage of small compared to large transferred files?
|
||||
* What are the top social media sources of website traffic, and from what countries?
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_dashboard.png[Final dashboard vis]
|
||||
|
||||
[discrete]
|
||||
[[add-the-sample-web-logs-data]]
|
||||
[[add-the-data-and-create-the-dashboard]]
|
||||
=== Add the data and create the dashboard
|
||||
|
||||
To create visualizations of the website traffic data, add the data set, then create the dashboard.
|
||||
To create visualizations of the data from the web server, add the data set, then create the dashboard.
|
||||
|
||||
. From the *Home* page, click *Try our sample data*.
|
||||
. From the {kib} *Home* page, click *Try our sample data*.
|
||||
|
||||
. From *Sample web logs*, click *Add data*.
|
||||
|
||||
. Open the main menu, click *Dashboard*.
|
||||
|
||||
. On the *Dashboards* page, click *Create dashboard*.
|
||||
. Click *Create dashboard*.
|
||||
|
||||
[float]
|
||||
[[open-and-set-up-lens]]
|
||||
=== Open and set up Lens
|
||||
|
||||
With *Lens*, you identify the data fields you want to visualize, drag and drop the fields, then watch as
|
||||
*Lens* uses heuristics to apply the fields and create a visualization for you.
|
||||
|
||||
. From the dashboard, click *Create panel*.
|
||||
|
||||
. On the *New visualization* window, click *Lens*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_1_1.png[New visualization popover]
|
||||
|
||||
. Make sure the *kibana_sample_data_logs* index appears.
|
||||
|
||||
[discrete]
|
||||
[[donut-vis]]
|
||||
[[view-the-number-of-website-visitors]]
|
||||
=== View the number of website visitors
|
||||
|
||||
To determine how many users have visited your website within the last 90 days, create a metric visualization, then add it to the dashboard.
|
||||
|
||||
. Set the <<set-time-filter,time filter>> to *Last 90 days*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Metric*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_1_2_1.png[Chart Type dropdown with Metric selected]
|
||||
|
||||
. From the *Available fields* list, drag and drop *clientip* to the visualization builder.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_1_3.png[Changed type and dropped clientip field]
|
||||
|
||||
. In the editor, click *Unique count of clientip*.
|
||||
|
||||
.. In the *Display name* field, enter `Unique visitors`.
|
||||
|
||||
.. Click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_1_4.png[Flyout config open]
|
||||
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
[[view-the-distribution-of-visitors-by-operating-system]]
|
||||
=== View the distribution of visitors by operating system
|
||||
|
||||
To determine the operating systems you should continue to support, and the importance of mobile traffic from iOS devices,
|
||||
create a donut chart that displays the top operating systems that your visitors use to access your webiste.
|
||||
create a donut chart that displays the top operating systems that your visitors used to access your website within the last 90 days.
|
||||
|
||||
. From the dashboard, click *Create panel*, then click *Lens* on the *New visualization* window.
|
||||
|
||||
. Make sure the *kibana_sample_data_logs* index appears, and the <<set-time-filter,time filter>> is set to *Last 90 days*.
|
||||
. Open *Lens*, then set the <<set-time-filter,time filter>> to *Last 90 days*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Donut*.
|
||||
|
||||
|
@ -52,35 +90,25 @@ image::images/lens_end_to_end_2_1_1.png[Donut chart with clientip and machine.os
|
|||
|
||||
. Change the color palette.
|
||||
|
||||
.. From the editor, click *Top values of machine.os.keyword*.
|
||||
.. In the editor, click *Top values of machine.os.keyword*.
|
||||
|
||||
.. From the *Color palette* dropdown, select *Compability*.
|
||||
.. From the *Color palette* dropdown, select *Compatibility*.
|
||||
|
||||
.. Click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_2_1.png[Donut chart with open config panel]
|
||||
|
||||
. Save the visualization, then add it to the dashboard.
|
||||
|
||||
.. From the toolbar, click *Save*.
|
||||
|
||||
.. In the *Title* field, enter `Visitors by OS`.
|
||||
|
||||
.. Select *Add to dashboard after saving*.
|
||||
|
||||
.. Click *Save and return*.
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
[[mixed-multiaxis]]
|
||||
=== View the average of bytes transfer per day
|
||||
|
||||
To prevent potential server failures and optimize the cost of website maintenance, create an area chart that displays the average of bytes transfer,
|
||||
then add a line chart layer to compare the data to the number of visitors to your website.
|
||||
To prevent potential server failures, and optimize the cost of website maintenance, create an area chart that displays the average of bytes transfer. To compare
|
||||
the data to the number of visitors to your website, add a line chart layer.
|
||||
|
||||
. From the dashboard, click *Create panel*, then click *Lens* on the *New visualization* window.
|
||||
|
||||
. Make sure the *kibana_sample_data_logs* index appears.
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *bytes* to the visualization builder.
|
||||
|
||||
|
@ -91,17 +119,15 @@ image::images/lens_end_to_end_3_1_1.gif[Zoom in on the data]
|
|||
|
||||
. Change the *timestamp* interval.
|
||||
|
||||
.. From the editor, click *timestamp*.
|
||||
.. In the editor, click *timestamp*.
|
||||
|
||||
.. Select *Customize time interval*.
|
||||
|
||||
.. Change the *Minimum interval* to `1 days`.
|
||||
.. Change the *Minimum interval* to `1 days`, then click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_1.png[Customize time interval]
|
||||
|
||||
.. Click *Close*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Area*.
|
||||
|
||||
[discrete]
|
||||
|
@ -110,7 +136,7 @@ image::images/lens_end_to_end_3_1.png[Customize time interval]
|
|||
|
||||
To compare the average of bytes transfer to the number of users that visit your website, add a line chart layer.
|
||||
|
||||
. From the editor, click *+*.
|
||||
. In the editor, click *+*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_2.png[Add new layer button]
|
||||
|
@ -130,23 +156,19 @@ The chart type for the visualization changes to *Mixed XY*.
|
|||
|
||||
. Change the *timestamp* interval.
|
||||
|
||||
.. From the editor, click *timestamp* in the line chart layer.
|
||||
.. In the editor, click *timestamp* in the line chart layer.
|
||||
|
||||
.. Select *Customize time interval*.
|
||||
|
||||
.. Change the *Minimum interval* to `1 days`.
|
||||
|
||||
.. Click *Close*.
|
||||
.. Change the *Minimum interval* to `1 days`, then click *Close*.
|
||||
|
||||
. Change the *Unique count of clientip* label and color.
|
||||
|
||||
.. From the editor, click *Unique count of clientip*.
|
||||
.. In the editor, click *Unique count of clientip*.
|
||||
|
||||
.. In the *Display name* field, enter `Unique visitors` in the line chart layer.
|
||||
|
||||
.. In the *Series color* field, enter *#CA8EAE*.
|
||||
|
||||
.. Click *Close*.
|
||||
.. In the *Series color* field, enter *#CA8EAE*, then click *Close*.
|
||||
|
||||
[discrete]
|
||||
[[configure-the-multiaxis-chart]]
|
||||
|
@ -155,41 +177,33 @@ The chart type for the visualization changes to *Mixed XY*.
|
|||
There is a significant difference between the *timestamp per day* and *Unique visitors* data, which makes the *Unique visitors* data difficult to read. To improve the readability,
|
||||
display the *Unique visitors* data along a second y-axis, then change the formatting. When functions contain multiple formats, separate axes are created by default.
|
||||
|
||||
. From the editor, click *Unique visitors* in the line chart layer.
|
||||
. In the editor, click *Unique visitors* in the line chart layer.
|
||||
|
||||
.. For *Axis side*, click *Right*.
|
||||
. For *Axis side*, click *Right*, then click *Close*.
|
||||
|
||||
.. Click *Close*.
|
||||
[float]
|
||||
[[change-the-visualization-type]]
|
||||
==== Change the visualization type
|
||||
|
||||
. From the editor, click *Average of bytes* in the area chart layer.
|
||||
. In the editor, click *Average of bytes* in the area chart layer.
|
||||
|
||||
.. From the *Value format* dropdown, select *Bytes (1024)*.
|
||||
. From the *Value format* dropdown, select *Bytes (1024)*, then click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_4.png[Multiaxis chart]
|
||||
|
||||
.. Click *Close*.
|
||||
|
||||
[discrete]
|
||||
[[lens-legend-position]]
|
||||
==== Change the legend position and save the visualization
|
||||
==== Change the legend position
|
||||
|
||||
The visualization is done, but the legend uses a lot of space. Change the legend position to the top of the chart, then save the visualization and add it to the dashboard.
|
||||
The visualization is done, but the legend uses a lot of space. Change the legend position to the top of the chart.
|
||||
|
||||
. From the *Legend* dropdown, select the top position.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_3_5.png[legend position]
|
||||
|
||||
. Save the visualization, then add it to the dashboard.
|
||||
|
||||
.. From the toolbar, click *Save*.
|
||||
|
||||
.. In the *Title* field, enter `Average Bytes vs. Unique Visitors`.
|
||||
|
||||
.. Select *Add to dashboard after saving*.
|
||||
|
||||
.. Click *Save and return*.
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
[[percentage-stacked-area]]
|
||||
|
@ -197,9 +211,7 @@ image::images/lens_end_to_end_3_5.png[legend position]
|
|||
|
||||
To detect unusual traffic, bad website links, and server errors, create a percentage stacked area chart that displays the associated response codes.
|
||||
|
||||
. From the dashboard, click *Create panel*, then click *Lens* on the *New visualization* window.
|
||||
|
||||
. Make sure the *kibana_sample_data_logs* index appears.
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Available fields* list, drag and drop the data fields to the *Drop a field or click to add* fields in the editor.
|
||||
|
||||
|
@ -220,7 +232,7 @@ image::images/lens_end_to_end_4_3.png[Turn off axis name]
|
|||
|
||||
For each response code that you want to display, create a filter.
|
||||
|
||||
. From the editor, click the *Drop a field or click to add* field for *Break down by*.
|
||||
. In the editor, click the *Drop a field or click to add* field for *Break down by*.
|
||||
|
||||
. From *Select a function*, click *Filters*.
|
||||
|
||||
|
@ -230,13 +242,11 @@ For each response code that you want to display, create a filter.
|
|||
|
||||
.. In the *KQL* field, enter `response.keyword>=200 AND response.keyword<300`.
|
||||
|
||||
.. In the *Label* field, enter `2XX`.
|
||||
.. In the *Label* field, enter `2XX`, then press Return.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_4_1.png[First filter in filters aggregation]
|
||||
|
||||
.. Press Return.
|
||||
|
||||
. Add the filter for the redirect codes.
|
||||
|
||||
.. Click *Add a filter*.
|
||||
|
@ -261,19 +271,9 @@ image::images/lens_end_to_end_4_1.png[First filter in filters aggregation]
|
|||
|
||||
.. In the *Label* field, enter `5XX`, then press Return.
|
||||
|
||||
. To change the color pallette, select *Status* from the *Color palette* dropdown.
|
||||
. To change the color palette, select *Status* from the *Color palette* dropdown, then click *Close*.
|
||||
|
||||
.. Click *Close*.
|
||||
|
||||
. Save the visualization, then add it to the dashboard.
|
||||
|
||||
.. From the toolbar, click *Save*.
|
||||
|
||||
.. In the *Title* field, enter `Response Codes Over Time`.
|
||||
|
||||
.. Select *Add to dashboard after saving*.
|
||||
|
||||
.. Click *Save and return*.
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
[[histogram]]
|
||||
|
@ -281,9 +281,7 @@ image::images/lens_end_to_end_4_1.png[First filter in filters aggregation]
|
|||
|
||||
To find the best time to shut down your website for maintenance, create a histogram that displays the traffic for your website by the hour.
|
||||
|
||||
. From the dashboard, click *Create panel*, then click *Lens* on the *New visualization* window.
|
||||
|
||||
. Make sure the *kibana_sample_data_logs* index appears.
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *bytes* to *Vertical axis* in the editor, then configure the options.
|
||||
|
||||
|
@ -293,9 +291,7 @@ To find the best time to shut down your website for maintenance, create a histog
|
|||
|
||||
.. In the *Display name* field, enter `Transferred bytes`.
|
||||
|
||||
.. From the *Value format* dropdown, select `Bytes (1024)`.
|
||||
|
||||
.. Click *Close*.
|
||||
.. From the *Value format* dropdown, select `Bytes (1024)`, then click *Close*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *hour_of_day* to *Horizontal axis* in the editor, then configure the options.
|
||||
|
||||
|
@ -306,15 +302,7 @@ To find the best time to shut down your website for maintenance, create a histog
|
|||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_5_2.png[Create custom ranges]
|
||||
|
||||
. Save the visualization, then add it to the dashboard.
|
||||
|
||||
.. From the toolbar, click *Save*.
|
||||
|
||||
.. In the *Title* field, enter `Hourly Traffic Distribution`.
|
||||
|
||||
.. Select *Add to dashboard after saving*.
|
||||
|
||||
.. Click *Save and return*.
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
[[custom-ranges]]
|
||||
|
@ -322,17 +310,13 @@ image::images/lens_end_to_end_5_2.png[Create custom ranges]
|
|||
|
||||
To determine if your users transfer more small files versus large files, create a pie chart that displays the percentage of each size.
|
||||
|
||||
. From the dashboard, click *Create panel*, then click *Lens* on the *New visualization* window.
|
||||
|
||||
. Make sure the *kibana_sample_data_logs* index appears.
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *bytes* to *Vertical axis* in the editor, then configure the options.
|
||||
|
||||
.. Click *Average of bytes*.
|
||||
|
||||
.. From *Select a function*, click *Sum*.
|
||||
|
||||
.. Click *Close*.
|
||||
.. From *Select a function*, click *Sum*, then click *Close*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *bytes* to *Break down by* in the editor, then specify the file size ranges.
|
||||
|
||||
|
@ -353,24 +337,14 @@ To determine if your users transfer more small files versus large files, create
|
|||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_6_1.png[Custom ranges configuration]
|
||||
|
||||
.. From the *Value format* dropdown, select *Bytes (1024)*.
|
||||
|
||||
.. Click *Close*.
|
||||
.. From the *Value format* dropdown, select *Bytes (1024)*, then click *Close*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Pie*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_6_2.png[Files size distribution]
|
||||
|
||||
. Save the visualization, then add it to the dashboard.
|
||||
|
||||
.. From the toolbar, click *Save*.
|
||||
|
||||
.. In the *Title* field, enter `File size distribution`.
|
||||
|
||||
.. Select *Add to dashboard after saving*.
|
||||
|
||||
.. Click *Save and return*.
|
||||
. Click *Save and return*.
|
||||
|
||||
[discrete]
|
||||
[[treemap]]
|
||||
|
@ -379,15 +353,13 @@ image::images/lens_end_to_end_6_2.png[Files size distribution]
|
|||
To determine how users find out about your website and where your users are located, create a treemap that displays the percentage of users that
|
||||
enter your website from specific social media websites, and the top countries where users are located.
|
||||
|
||||
. From the dashboard, click *Create panel*, then click *Lens* on the *New visualization* window.
|
||||
|
||||
. Make sure the *kibana_sample_data_logs* index appears.
|
||||
. Open *Lens*.
|
||||
|
||||
. From the *Chart Type* dropdown, select *Treemap*.
|
||||
|
||||
. From the *Available fields* list, drag and drop *Records* to the *Size by* field in the editor.
|
||||
|
||||
. From the editor, click the *Drop a field or click to add* field for *Group by*, then create a filter for each website traffic source.
|
||||
. In the editor, click the *Drop a field or click to add* field for *Group by*, then create a filter for each website traffic source.
|
||||
|
||||
.. From *Select a function*, click *Filters*.
|
||||
|
||||
|
@ -415,7 +387,7 @@ enter your website from specific social media websites, and the top countries wh
|
|||
[[add-the-countries]]
|
||||
==== Add the geographic data
|
||||
|
||||
To determine the top countries where users are located, add the geographic data, then save and add the visualization to the dashboard.
|
||||
To determine the top countries where users are located, add the geographic data.
|
||||
|
||||
Compare the top sources of website traffic data to the top three countries.
|
||||
|
||||
|
@ -428,26 +400,20 @@ image::images/lens_end_to_end_7_2.png[Treemap vis]
|
|||
|
||||
. To view only the Facebook and Twitter data, remove the *Other* category.
|
||||
|
||||
.. From the editor, click *Top values of geo.src*.
|
||||
.. In the editor, click *Top values of geo.src*.
|
||||
|
||||
.. From the *Advanced* dropdown, deselect *Group other values as "Other"*.
|
||||
.. From the *Advanced* dropdown, deselect *Group other values as "Other"*, then click *Close*.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_7_3.png[Group other values as Other]
|
||||
|
||||
.. Click *Close*.
|
||||
. Click *Save and return*.
|
||||
|
||||
. Save the visualization, then add it to the dashboard.
|
||||
[discrete]
|
||||
=== Save the dashboard
|
||||
|
||||
.. From the toolbar, click *Save*.
|
||||
Now that you have a complete overview of your web server data, save the dashboard.
|
||||
|
||||
.. In the *Title* field, enter `Traffic Source For Top 3 Countries`.
|
||||
. In the toolbar, click *Save*.
|
||||
|
||||
.. Select *Add to dashboard after saving*.
|
||||
|
||||
.. Click *Save and return*.
|
||||
|
||||
That's it! You've created a dashboard that provides you with a complete picture of your website data.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/lens_end_to_end_dashboard.png[Final dashboard vis]
|
||||
. On the *Save dashboard* window, enter `Web server data`, then click *Save*.
|
|
@ -108,4 +108,3 @@ pageLoadAssetSize:
|
|||
fileUpload: 25664
|
||||
banners: 17946
|
||||
mapsEms: 26072
|
||||
cases: 102558
|
||||
|
|
|
@ -270,7 +270,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker:
|
|||
extractComments: false,
|
||||
parallel: false,
|
||||
terserOptions: {
|
||||
compress: false,
|
||||
compress: true,
|
||||
mangle: false,
|
||||
},
|
||||
}),
|
||||
|
|
|
@ -122,6 +122,7 @@ export class DocLinksService {
|
|||
},
|
||||
indexPatterns: {
|
||||
introduction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/index-patterns.html`,
|
||||
fieldFormattersNumber: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/numeral.html`,
|
||||
fieldFormattersString: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/field-formatters-string.html`,
|
||||
},
|
||||
addData: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/connect-to-elasticsearch.html`,
|
||||
|
@ -391,6 +392,8 @@ export interface DocLinksStart {
|
|||
};
|
||||
readonly indexPatterns: {
|
||||
readonly introduction: string;
|
||||
readonly fieldFormattersNumber: string;
|
||||
readonly fieldFormattersString: string;
|
||||
};
|
||||
readonly addData: string;
|
||||
readonly kibana: string;
|
||||
|
|
|
@ -571,6 +571,8 @@ export interface DocLinksStart {
|
|||
};
|
||||
readonly indexPatterns: {
|
||||
readonly introduction: string;
|
||||
readonly fieldFormattersNumber: string;
|
||||
readonly fieldFormattersString: string;
|
||||
};
|
||||
readonly addData: string;
|
||||
readonly kibana: string;
|
||||
|
|
|
@ -106,7 +106,7 @@ const createStartContractMock = () => {
|
|||
},
|
||||
savedObjects: {
|
||||
customIndex: false,
|
||||
maxImportExportSizeBytes: 10000,
|
||||
maxImportExportSize: 10000,
|
||||
maxImportPayloadBytes: 26214400,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -239,7 +239,7 @@ describe('CoreUsageDataService', () => {
|
|||
},
|
||||
"savedObjects": Object {
|
||||
"customIndex": false,
|
||||
"maxImportExportSizeBytes": 10000,
|
||||
"maxImportExportSize": 10000,
|
||||
"maxImportPayloadBytes": 26214400,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -235,7 +235,7 @@ export class CoreUsageDataService implements CoreService<CoreUsageDataSetup, Cor
|
|||
savedObjects: {
|
||||
customIndex: isCustomIndex(this.kibanaConfig!.index),
|
||||
maxImportPayloadBytes: this.soConfig.maxImportPayloadBytes.getValueInBytes(),
|
||||
maxImportExportSizeBytes: this.soConfig.maxImportExportSize.getValueInBytes(),
|
||||
maxImportExportSize: this.soConfig.maxImportExportSize,
|
||||
},
|
||||
},
|
||||
environment: {
|
||||
|
|
|
@ -229,7 +229,7 @@ export interface CoreConfigUsageData {
|
|||
savedObjects: {
|
||||
customIndex: boolean;
|
||||
maxImportPayloadBytes: number;
|
||||
maxImportExportSizeBytes: number;
|
||||
maxImportExportSize: number;
|
||||
};
|
||||
|
||||
// uiSettings: {
|
||||
|
|
|
@ -27,7 +27,9 @@ export class SavedObjectsExportError extends Error {
|
|||
static exportSizeExceeded(limit: number) {
|
||||
return new SavedObjectsExportError(
|
||||
'export-size-exceeded',
|
||||
`Can't export more than ${limit} objects`
|
||||
`Can't export more than ${limit} objects. ` +
|
||||
'If your server has enough memory, this limit can be increased ' +
|
||||
'by adjusting the "savedObjects.maxImportExportSize" setting.'
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -877,7 +877,9 @@ describe('getSortedObjectsForExport()', () => {
|
|||
request,
|
||||
types: ['index-pattern', 'search'],
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"Can't export more than 1 objects"`);
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Can't export more than 1 objects. If your server has enough memory, this limit can be increased by adjusting the \\"savedObjects.maxImportExportSize\\" setting."`
|
||||
);
|
||||
expect(savedObjectsClient.closePointInTime).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
|
@ -1112,7 +1114,7 @@ describe('getSortedObjectsForExport()', () => {
|
|||
],
|
||||
};
|
||||
await expect(exporter.exportByObjects(exportOpts)).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Can't export more than 1 objects"`
|
||||
`"Can't export more than 1 objects. If your server has enough memory, this limit can be increased by adjusting the \\"savedObjects.maxImportExportSize\\" setting."`
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ export const savedObjectsConfig = {
|
|||
path: 'savedObjects',
|
||||
schema: schema.object({
|
||||
maxImportPayloadBytes: schema.byteSize({ defaultValue: 26214400 }),
|
||||
maxImportExportSize: schema.byteSize({ defaultValue: 10000 }),
|
||||
maxImportExportSize: schema.number({ defaultValue: 10000 }),
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -43,7 +43,7 @@ export class SavedObjectConfig {
|
|||
rawMigrationConfig: SavedObjectsMigrationConfigType
|
||||
) {
|
||||
this.maxImportPayloadBytes = rawConfig.maxImportPayloadBytes.getValueInBytes();
|
||||
this.maxImportExportSize = rawConfig.maxImportExportSize.getValueInBytes();
|
||||
this.maxImportExportSize = rawConfig.maxImportExportSize;
|
||||
this.migration = rawMigrationConfig;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ describe('SavedObjectsService', () => {
|
|||
}
|
||||
return new BehaviorSubject({
|
||||
maxImportPayloadBytes: new ByteSizeValue(0),
|
||||
maxImportExportSize: new ByteSizeValue(0),
|
||||
maxImportExportSize: 10000,
|
||||
});
|
||||
});
|
||||
return mockCoreContext.create({ configService, env });
|
||||
|
|
|
@ -452,7 +452,7 @@ export interface CoreConfigUsageData {
|
|||
savedObjects: {
|
||||
customIndex: boolean;
|
||||
maxImportPayloadBytes: number;
|
||||
maxImportExportSizeBytes: number;
|
||||
maxImportExportSize: number;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ import {
|
|||
} from '../common';
|
||||
|
||||
import { FilterLabel } from './ui';
|
||||
import { FilterItem } from './ui/filter_bar';
|
||||
|
||||
import {
|
||||
generateFilters,
|
||||
|
@ -54,6 +55,7 @@ import {
|
|||
// Filter helpers namespace:
|
||||
export const esFilters = {
|
||||
FilterLabel,
|
||||
FilterItem,
|
||||
|
||||
FILTERS,
|
||||
FilterStateStore,
|
||||
|
@ -92,7 +94,7 @@ export const esFilters = {
|
|||
extractTimeRange,
|
||||
};
|
||||
|
||||
export {
|
||||
export type {
|
||||
RangeFilter,
|
||||
RangeFilterMeta,
|
||||
RangeFilterParams,
|
||||
|
|
|
@ -727,6 +727,7 @@ export type EsdslExpressionFunctionDefinition = ExpressionFunctionDefinition_2<t
|
|||
// @public (undocumented)
|
||||
export const esFilters: {
|
||||
FilterLabel: (props: import("./ui/filter_bar/filter_editor/lib/filter_label").FilterLabelProps) => JSX.Element;
|
||||
FilterItem: (props: import("./ui/filter_bar/filter_item").FilterItemProps) => JSX.Element;
|
||||
FILTERS: typeof FILTERS;
|
||||
FilterStateStore: typeof FilterStateStore;
|
||||
buildEmptyFilter: (isPinned: boolean, index?: string | undefined) => import("../common").Filter;
|
||||
|
@ -2650,53 +2651,53 @@ export const UI_SETTINGS: {
|
|||
// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:169:7 - (ae-forgotten-export) The symbol "RuntimeField" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/search/aggs/types.ts:139:51 - (ae-forgotten-export) The symbol "AggTypesRegistryStart" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/field_formats/field_formats_service.ts:56:3 - (ae-forgotten-export) The symbol "FormatFactory" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:55:23 - (ae-forgotten-export) The symbol "FILTERS" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:55:23 - (ae-forgotten-export) The symbol "getDisplayValueFromFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:55:23 - (ae-forgotten-export) The symbol "generateFilters" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:55:23 - (ae-forgotten-export) The symbol "changeTimeFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:55:23 - (ae-forgotten-export) The symbol "convertRangeFilterToTimeRangeString" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:55:23 - (ae-forgotten-export) The symbol "extractTimeFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:55:23 - (ae-forgotten-export) The symbol "extractTimeRange" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:127:21 - (ae-forgotten-export) The symbol "buildEsQuery" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:127:21 - (ae-forgotten-export) The symbol "getEsQueryConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:127:21 - (ae-forgotten-export) The symbol "luceneStringToDsl" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:127:21 - (ae-forgotten-export) The symbol "decorateQuery" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "FieldFormatsRegistry" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "BoolFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "BytesFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "ColorFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "DurationFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "IpFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "NumberFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "PercentFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "RelativeDateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "SourceFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "StaticLookupFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "UrlFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "StringFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:168:26 - (ae-forgotten-export) The symbol "HistogramFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:211:23 - (ae-forgotten-export) The symbol "datatableToCSV" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:401:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:401:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:401:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:401:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:403:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:404:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:414:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:415:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:420:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:421:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:425:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:428:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:56:23 - (ae-forgotten-export) The symbol "FILTERS" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:56:23 - (ae-forgotten-export) The symbol "getDisplayValueFromFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:56:23 - (ae-forgotten-export) The symbol "generateFilters" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:56:23 - (ae-forgotten-export) The symbol "changeTimeFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:56:23 - (ae-forgotten-export) The symbol "convertRangeFilterToTimeRangeString" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:56:23 - (ae-forgotten-export) The symbol "extractTimeFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:56:23 - (ae-forgotten-export) The symbol "extractTimeRange" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:129:21 - (ae-forgotten-export) The symbol "buildEsQuery" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:129:21 - (ae-forgotten-export) The symbol "getEsQueryConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:129:21 - (ae-forgotten-export) The symbol "luceneStringToDsl" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:129:21 - (ae-forgotten-export) The symbol "decorateQuery" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "FieldFormatsRegistry" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "BoolFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "BytesFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "ColorFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "DurationFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "IpFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "NumberFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "PercentFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "RelativeDateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "SourceFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "StaticLookupFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "UrlFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "StringFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "HistogramFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:213:23 - (ae-forgotten-export) The symbol "datatableToCSV" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:403:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:403:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:403:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:403:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:415:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:418:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:422:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:426:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:427:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:430:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/search/session/session_service.ts:55:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts
|
||||
|
||||
|
|
|
@ -25,7 +25,9 @@ import {
|
|||
} from '../../../common';
|
||||
import { getIndexPatterns } from '../../services';
|
||||
|
||||
interface Props {
|
||||
type PanelOptions = 'pinFilter' | 'editFilter' | 'negateFilter' | 'disableFilter' | 'deleteFilter';
|
||||
|
||||
export interface FilterItemProps {
|
||||
id: string;
|
||||
filter: Filter;
|
||||
indexPatterns: IIndexPattern[];
|
||||
|
@ -34,6 +36,7 @@ interface Props {
|
|||
onRemove: () => void;
|
||||
intl: InjectedIntl;
|
||||
uiSettings: IUiSettingsClient;
|
||||
hiddenPanelOptions?: PanelOptions[];
|
||||
}
|
||||
|
||||
interface LabelOptions {
|
||||
|
@ -53,10 +56,10 @@ export type FilterLabelStatus =
|
|||
|
||||
export const FILTER_EDITOR_WIDTH = 800;
|
||||
|
||||
export function FilterItem(props: Props) {
|
||||
export function FilterItem(props: FilterItemProps) {
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
|
||||
const [indexPatternExists, setIndexPatternExists] = useState<boolean | undefined>(undefined);
|
||||
const { id, filter, indexPatterns } = props;
|
||||
const { id, filter, indexPatterns, hiddenPanelOptions } = props;
|
||||
|
||||
useEffect(() => {
|
||||
const index = props.filter.meta.index;
|
||||
|
@ -154,83 +157,90 @@ export function FilterItem(props: Props) {
|
|||
|
||||
function getPanels() {
|
||||
const { negate, disabled } = filter.meta;
|
||||
let mainPanelItems = [
|
||||
{
|
||||
name: isFilterPinned(filter)
|
||||
? props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.unpinFilterButtonLabel',
|
||||
defaultMessage: 'Unpin',
|
||||
})
|
||||
: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.pinFilterButtonLabel',
|
||||
defaultMessage: 'Pin across all apps',
|
||||
}),
|
||||
icon: 'pin',
|
||||
onClick: () => {
|
||||
setIsPopoverOpen(false);
|
||||
onTogglePinned();
|
||||
},
|
||||
'data-test-subj': 'pinFilter',
|
||||
},
|
||||
{
|
||||
name: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.editFilterButtonLabel',
|
||||
defaultMessage: 'Edit filter',
|
||||
}),
|
||||
icon: 'pencil',
|
||||
panel: 1,
|
||||
'data-test-subj': 'editFilter',
|
||||
},
|
||||
{
|
||||
name: negate
|
||||
? props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.includeFilterButtonLabel',
|
||||
defaultMessage: 'Include results',
|
||||
})
|
||||
: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.excludeFilterButtonLabel',
|
||||
defaultMessage: 'Exclude results',
|
||||
}),
|
||||
icon: negate ? 'plusInCircle' : 'minusInCircle',
|
||||
onClick: () => {
|
||||
setIsPopoverOpen(false);
|
||||
onToggleNegated();
|
||||
},
|
||||
'data-test-subj': 'negateFilter',
|
||||
},
|
||||
{
|
||||
name: disabled
|
||||
? props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.enableFilterButtonLabel',
|
||||
defaultMessage: 'Re-enable',
|
||||
})
|
||||
: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.disableFilterButtonLabel',
|
||||
defaultMessage: 'Temporarily disable',
|
||||
}),
|
||||
icon: `${disabled ? 'eye' : 'eyeClosed'}`,
|
||||
onClick: () => {
|
||||
setIsPopoverOpen(false);
|
||||
onToggleDisabled();
|
||||
},
|
||||
'data-test-subj': 'disableFilter',
|
||||
},
|
||||
{
|
||||
name: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.deleteFilterButtonLabel',
|
||||
defaultMessage: 'Delete',
|
||||
}),
|
||||
icon: 'trash',
|
||||
onClick: () => {
|
||||
setIsPopoverOpen(false);
|
||||
props.onRemove();
|
||||
},
|
||||
'data-test-subj': 'deleteFilter',
|
||||
},
|
||||
];
|
||||
|
||||
if (hiddenPanelOptions && hiddenPanelOptions.length > 0) {
|
||||
mainPanelItems = mainPanelItems.filter(
|
||||
(pItem) => !hiddenPanelOptions.includes(pItem['data-test-subj'] as PanelOptions)
|
||||
);
|
||||
}
|
||||
return [
|
||||
{
|
||||
id: 0,
|
||||
items: [
|
||||
{
|
||||
name: isFilterPinned(filter)
|
||||
? props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.unpinFilterButtonLabel',
|
||||
defaultMessage: 'Unpin',
|
||||
})
|
||||
: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.pinFilterButtonLabel',
|
||||
defaultMessage: 'Pin across all apps',
|
||||
}),
|
||||
icon: 'pin',
|
||||
onClick: () => {
|
||||
setIsPopoverOpen(false);
|
||||
onTogglePinned();
|
||||
},
|
||||
'data-test-subj': 'pinFilter',
|
||||
},
|
||||
{
|
||||
name: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.editFilterButtonLabel',
|
||||
defaultMessage: 'Edit filter',
|
||||
}),
|
||||
icon: 'pencil',
|
||||
panel: 1,
|
||||
'data-test-subj': 'editFilter',
|
||||
},
|
||||
{
|
||||
name: negate
|
||||
? props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.includeFilterButtonLabel',
|
||||
defaultMessage: 'Include results',
|
||||
})
|
||||
: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.excludeFilterButtonLabel',
|
||||
defaultMessage: 'Exclude results',
|
||||
}),
|
||||
icon: negate ? 'plusInCircle' : 'minusInCircle',
|
||||
onClick: () => {
|
||||
setIsPopoverOpen(false);
|
||||
onToggleNegated();
|
||||
},
|
||||
'data-test-subj': 'negateFilter',
|
||||
},
|
||||
{
|
||||
name: disabled
|
||||
? props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.enableFilterButtonLabel',
|
||||
defaultMessage: 'Re-enable',
|
||||
})
|
||||
: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.disableFilterButtonLabel',
|
||||
defaultMessage: 'Temporarily disable',
|
||||
}),
|
||||
icon: `${disabled ? 'eye' : 'eyeClosed'}`,
|
||||
onClick: () => {
|
||||
setIsPopoverOpen(false);
|
||||
onToggleDisabled();
|
||||
},
|
||||
'data-test-subj': 'disableFilter',
|
||||
},
|
||||
{
|
||||
name: props.intl.formatMessage({
|
||||
id: 'data.filter.filterBar.deleteFilterButtonLabel',
|
||||
defaultMessage: 'Delete',
|
||||
}),
|
||||
icon: 'trash',
|
||||
onClick: () => {
|
||||
setIsPopoverOpen(false);
|
||||
props.onRemove();
|
||||
},
|
||||
'data-test-subj': 'deleteFilter',
|
||||
},
|
||||
],
|
||||
items: mainPanelItems,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
|
@ -363,3 +373,6 @@ export function FilterItem(props: Props) {
|
|||
</EuiPopover>
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default FilterItem;
|
||||
|
|
|
@ -27,6 +27,8 @@ interface State {
|
|||
}
|
||||
|
||||
class FilterOptionsUI extends Component<Props, State> {
|
||||
private buttonRef = React.createRef<HTMLButtonElement>();
|
||||
|
||||
public state: State = {
|
||||
isPopoverOpen: false,
|
||||
};
|
||||
|
@ -39,6 +41,7 @@ class FilterOptionsUI extends Component<Props, State> {
|
|||
|
||||
public closePopover = () => {
|
||||
this.setState({ isPopoverOpen: false });
|
||||
this.buttonRef.current?.focus();
|
||||
};
|
||||
|
||||
public render() {
|
||||
|
@ -151,6 +154,7 @@ class FilterOptionsUI extends Component<Props, State> {
|
|||
defaultMessage: 'Change all filters',
|
||||
})}
|
||||
data-test-subj="showFilterActions"
|
||||
buttonRef={this.buttonRef}
|
||||
/>
|
||||
}
|
||||
anchorPosition="rightUp"
|
||||
|
|
|
@ -17,3 +17,12 @@ export const FilterLabel = (props: FilterLabelProps) => (
|
|||
<LazyFilterLabel {...props} />
|
||||
</React.Suspense>
|
||||
);
|
||||
|
||||
import type { FilterItemProps } from './filter_item';
|
||||
|
||||
const LazyFilterItem = React.lazy(() => import('./filter_item'));
|
||||
export const FilterItem = (props: FilterItemProps) => (
|
||||
<React.Suspense fallback={<Fallback />}>
|
||||
<LazyFilterItem {...props} />
|
||||
</React.Suspense>
|
||||
);
|
||||
|
|
|
@ -417,7 +417,7 @@ export function getUiSettings(): Record<string, UiSettingsParams<unknown>> {
|
|||
'data.advancedSettings.format.numberFormat.numeralFormatLinkText',
|
||||
values: {
|
||||
numeralFormatLink:
|
||||
'<a href="http://numeraljs.com/" target="_blank" rel="noopener noreferrer">' +
|
||||
'<a href="https://www.elastic.co/guide/en/kibana/current/numeral.html" target="_blank" rel="noopener">' +
|
||||
i18n.translate('data.advancedSettings.format.numberFormat.numeralFormatLinkText', {
|
||||
defaultMessage: 'numeral format',
|
||||
}) +
|
||||
|
@ -439,7 +439,7 @@ export function getUiSettings(): Record<string, UiSettingsParams<unknown>> {
|
|||
'data.advancedSettings.format.percentFormat.numeralFormatLinkText',
|
||||
values: {
|
||||
numeralFormatLink:
|
||||
'<a href="http://numeraljs.com/" target="_blank" rel="noopener noreferrer">' +
|
||||
'<a href="https://www.elastic.co/guide/en/kibana/current/numeral.html" target="_blank" rel="noopener">' +
|
||||
i18n.translate('data.advancedSettings.format.percentFormat.numeralFormatLinkText', {
|
||||
defaultMessage: 'numeral format',
|
||||
}) +
|
||||
|
@ -461,7 +461,7 @@ export function getUiSettings(): Record<string, UiSettingsParams<unknown>> {
|
|||
'data.advancedSettings.format.bytesFormat.numeralFormatLinkText',
|
||||
values: {
|
||||
numeralFormatLink:
|
||||
'<a href="http://numeraljs.com/" target="_blank" rel="noopener noreferrer">' +
|
||||
'<a href="https://www.elastic.co/guide/en/kibana/current/numeral.html" target="_blank" rel="noopener">' +
|
||||
i18n.translate('data.advancedSettings.format.bytesFormat.numeralFormatLinkText', {
|
||||
defaultMessage: 'numeral format',
|
||||
}) +
|
||||
|
@ -483,7 +483,7 @@ export function getUiSettings(): Record<string, UiSettingsParams<unknown>> {
|
|||
'data.advancedSettings.format.currencyFormat.numeralFormatLinkText',
|
||||
values: {
|
||||
numeralFormatLink:
|
||||
'<a href="http://numeraljs.com/" target="_blank" rel="noopener noreferrer">' +
|
||||
'<a href="https://www.elastic.co/guide/en/kibana/current/numeral.html" target="_blank" rel="noopener">' +
|
||||
i18n.translate('data.advancedSettings.format.currencyFormat.numeralFormatLinkText', {
|
||||
defaultMessage: 'numeral format',
|
||||
}) +
|
||||
|
@ -509,7 +509,7 @@ export function getUiSettings(): Record<string, UiSettingsParams<unknown>> {
|
|||
'data.advancedSettings.format.formattingLocaleText',
|
||||
values: {
|
||||
numeralLanguageLink:
|
||||
'<a href="http://numeraljs.com/" target="_blank" rel="noopener noreferrer">' +
|
||||
'<a href="https://www.elastic.co/guide/en/kibana/current/numeral.html" target="_blank" rel="noopener">' +
|
||||
i18n.translate(
|
||||
'data.advancedSettings.format.formattingLocale.numeralLanguageLinkText',
|
||||
{
|
||||
|
|
|
@ -23,7 +23,7 @@ export const getSavedObjects = (): SavedObject[] => [
|
|||
defaultMessage: '[eCommerce] Sales by Category',
|
||||
}),
|
||||
visState:
|
||||
'{"title":"[eCommerce] Sales by Category","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Sum of total_quantity"}}],"seriesParams":[{"show":"true","type":"area","mode":"stacked","data":{"label":"Sum of total_quantity","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"top","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"sum","schema":"metric","params":{"field":"total_quantity"}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"order_date","interval":"auto","drop_partials":false,"min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"category.keyword","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
|
||||
'{"title":"[eCommerce] Sales by Category","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Sum of total_quantity"}}],"seriesParams":[{"show":"true","type":"area","mode":"stacked","data":{"label":"Sum of total_quantity","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"top","times":[],"addTimeMarker":false,"detailedTooltip":true,"palette":{"type":"palette","name":"default"}},"aggs":[{"id":"1","enabled":true,"type":"sum","schema":"metric","params":{"field":"total_quantity"}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"order_date","interval":"auto","drop_partials":false,"min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"category.keyword","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
|
||||
uiStateJSON: '{}',
|
||||
description: '',
|
||||
version: 1,
|
||||
|
|
|
@ -45,7 +45,7 @@ export const getSavedObjects = (): SavedObject[] => [
|
|||
defaultMessage: '[Flights] Flight Count and Average Ticket Price',
|
||||
}),
|
||||
visState:
|
||||
'{"title":"[Flights] Flight Count and Average Ticket Price","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Average Ticket Price"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Flight Count"}}],"seriesParams":[{"show":true,"mode":"stacked","type":"area","drawLinesBetweenPoints":true,"showCircles":false,"interpolate":"linear","lineWidth":2,"data":{"id":"5","label":"Flight Count"},"valueAxis":"ValueAxis-2"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"4","label":"Average Ticket Price"},"valueAxis":"ValueAxis-1","lineWidth":2}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":13,"detailedTooltip":true},"aggs":[{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"5","enabled":true,"type":"count","schema":"metric","params":{"customLabel":"Flight Count"}},{"id":"4","enabled":true,"type":"avg","schema":"metric","params":{"field":"AvgTicketPrice","customLabel":"Average Ticket Price"}},{"id":"2","enabled":true,"type":"avg","schema":"radius","params":{"field":"AvgTicketPrice"}}]}',
|
||||
'{"title":"[Flights] Flight Count and Average Ticket Price","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Average Ticket Price"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Flight Count"}}],"seriesParams":[{"show":true,"mode":"stacked","type":"area","drawLinesBetweenPoints":true,"showCircles":false,"interpolate":"linear","lineWidth":2,"data":{"id":"5","label":"Flight Count"},"valueAxis":"ValueAxis-2"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"4","label":"Average Ticket Price"},"valueAxis":"ValueAxis-1","lineWidth":2}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":13,"detailedTooltip":true,"palette":{"type":"palette","name":"default"}},"aggs":[{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"5","enabled":true,"type":"count","schema":"metric","params":{"customLabel":"Flight Count"}},{"id":"4","enabled":true,"type":"avg","schema":"metric","params":{"field":"AvgTicketPrice","customLabel":"Average Ticket Price"}},{"id":"2","enabled":true,"type":"avg","schema":"radius","params":{"field":"AvgTicketPrice"}}]}',
|
||||
uiStateJSON:
|
||||
'{"vis":{"legendOpen":true,"colors":{"Average Ticket Price":"#629E51","Flight Count":"#AEA2E0"}}}',
|
||||
description: '',
|
||||
|
@ -122,7 +122,7 @@ export const getSavedObjects = (): SavedObject[] => [
|
|||
defaultMessage: '[Flights] Delay Type',
|
||||
}),
|
||||
visState:
|
||||
'{"title":"[Flights] Delay Type","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"cardinal","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"FlightDelayType","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
|
||||
'{"title":"[Flights] Delay Type","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"cardinal","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true,"palette":{"type":"palette","name":"default"}},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"FlightDelayType","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
|
||||
uiStateJSON: '{}',
|
||||
description: '',
|
||||
version: 1,
|
||||
|
@ -165,7 +165,7 @@ export const getSavedObjects = (): SavedObject[] => [
|
|||
defaultMessage: '[Flights] Delay Buckets',
|
||||
}),
|
||||
visState:
|
||||
'{"title":"[Flights] Delay Buckets","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"histogram","schema":"segment","params":{"field":"FlightDelayMin","interval":30,"extended_bounds":{},"customLabel":"Flight Delay Minutes"}}]}',
|
||||
'{"title":"[Flights] Delay Buckets","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true,"palette":{"type":"palette","name":"default"}},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"histogram","schema":"segment","params":{"field":"FlightDelayMin","interval":30,"extended_bounds":{},"customLabel":"Flight Delay Minutes"}}]}',
|
||||
uiStateJSON: '{"vis":{"legendOpen":false}}',
|
||||
description: '',
|
||||
version: 1,
|
||||
|
@ -187,7 +187,7 @@ export const getSavedObjects = (): SavedObject[] => [
|
|||
defaultMessage: '[Flights] Flight Delays',
|
||||
}),
|
||||
visState:
|
||||
'{"title":"[Flights] Flight Delays","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"FlightDelay","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Delays"}}]}',
|
||||
'{"title":"[Flights] Flight Delays","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true,"palette":{"type":"palette","name":"default"}},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"FlightDelay","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Delays"}}]}',
|
||||
uiStateJSON: '{}',
|
||||
description: '',
|
||||
version: 1,
|
||||
|
@ -209,7 +209,7 @@ export const getSavedObjects = (): SavedObject[] => [
|
|||
defaultMessage: '[Flights] Flight Cancellations',
|
||||
}),
|
||||
visState:
|
||||
'{"title":"[Flights] Flight Cancellations","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"Cancelled","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Cancellations"}}]}',
|
||||
'{"title":"[Flights] Flight Cancellations","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true,"palette":{"type":"palette","name":"default"}},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"Cancelled","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Cancellations"}}]}',
|
||||
uiStateJSON: '{}',
|
||||
description: '',
|
||||
version: 1,
|
||||
|
|
|
@ -22,7 +22,7 @@ export const getSavedObjects = (): SavedObject[] => [
|
|||
defaultMessage: '[Logs] Unique Visitors vs. Average Bytes',
|
||||
}),
|
||||
visState:
|
||||
'{"title":"[Logs] Unique Visitors vs. Average Bytes","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Avg. Bytes"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Unique Visitors"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Avg. Bytes","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"2","label":"Unique Visitors"},"valueAxis":"ValueAxis-2"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":17,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"avg","schema":"metric","params":{"field":"bytes","customLabel":"Avg. Bytes"}},{"id":"2","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"clientip","customLabel":"Unique Visitors"}},{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"4","enabled":true,"type":"count","schema":"radius","params":{}}]}',
|
||||
'{"title":"[Logs] Unique Visitors vs. Average Bytes","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Avg. Bytes"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Unique Visitors"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Avg. Bytes","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"2","label":"Unique Visitors"},"valueAxis":"ValueAxis-2"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":17,"detailedTooltip":true,"palette":{"type":"palette","name":"default"}},"aggs":[{"id":"1","enabled":true,"type":"avg","schema":"metric","params":{"field":"bytes","customLabel":"Avg. Bytes"}},{"id":"2","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"clientip","customLabel":"Unique Visitors"}},{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"4","enabled":true,"type":"count","schema":"radius","params":{}}]}',
|
||||
uiStateJSON: '{"vis":{"colors":{"Avg. Bytes":"#70DBED","Unique Visitors":"#0A437C"}}}',
|
||||
description: '',
|
||||
version: 1,
|
||||
|
|
|
@ -11,7 +11,7 @@ exports[`BytesFormatEditor should render normally 1`] = `
|
|||
helpText={
|
||||
<span>
|
||||
<EuiLink
|
||||
href="https://adamwdraper.github.io/Numeral-js/"
|
||||
href="https://www.elastic.co/guide/en/kibana/mocked-test-branch/numeral.html"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -8,9 +8,13 @@
|
|||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { coreMock } from 'src/core/public/mocks';
|
||||
import { createKibanaReactContext } from '../../../../../../kibana_react/public';
|
||||
import { FieldFormat } from 'src/plugins/data/public';
|
||||
|
||||
import { BytesFormatEditor } from './bytes';
|
||||
import { FieldFormat } from 'src/plugins/data/public';
|
||||
|
||||
type BytesFormatEditorProps = React.ComponentProps<typeof BytesFormatEditor>;
|
||||
|
||||
const fieldType = 'number';
|
||||
const format = {
|
||||
|
@ -25,7 +29,20 @@ const formatParams = {
|
|||
const onChange = jest.fn();
|
||||
const onError = jest.fn();
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext(
|
||||
coreMock.createStart({ basePath: 'my-base-path' })
|
||||
);
|
||||
|
||||
describe('BytesFormatEditor', () => {
|
||||
beforeAll(() => {
|
||||
// Enzyme does not support the new Context API in shallow rendering.
|
||||
// @see https://github.com/enzymejs/enzyme/issues/2189
|
||||
(BytesFormatEditor as React.ComponentType<BytesFormatEditorProps>).contextTypes = {
|
||||
services: () => null,
|
||||
};
|
||||
delete (BytesFormatEditor as Partial<typeof BytesFormatEditor>).contextType;
|
||||
});
|
||||
|
||||
it('should have a formatId', () => {
|
||||
expect(BytesFormatEditor.formatId).toEqual('bytes');
|
||||
});
|
||||
|
@ -38,7 +55,8 @@ describe('BytesFormatEditor', () => {
|
|||
formatParams={formatParams}
|
||||
onChange={onChange}
|
||||
onError={onError}
|
||||
/>
|
||||
/>,
|
||||
{ context: KibanaReactContext.value }
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ exports[`NumberFormatEditor should render normally 1`] = `
|
|||
helpText={
|
||||
<span>
|
||||
<EuiLink
|
||||
href="https://adamwdraper.github.io/Numeral-js/"
|
||||
href="https://www.elastic.co/guide/en/kibana/mocked-test-branch/numeral.html"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -8,10 +8,14 @@
|
|||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { coreMock } from 'src/core/public/mocks';
|
||||
import { createKibanaReactContext } from '../../../../../../kibana_react/public';
|
||||
import { FieldFormat } from 'src/plugins/data/public';
|
||||
|
||||
import { NumberFormatEditor } from './number';
|
||||
|
||||
type NumberFormatEditorProps = React.ComponentProps<typeof NumberFormatEditor>;
|
||||
|
||||
const fieldType = 'number';
|
||||
const format = {
|
||||
getConverterFor: jest.fn().mockImplementation(() => (input: number) => input * 2),
|
||||
|
@ -25,7 +29,20 @@ const formatParams = {
|
|||
const onChange = jest.fn();
|
||||
const onError = jest.fn();
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext(
|
||||
coreMock.createStart({ basePath: 'my-base-path' })
|
||||
);
|
||||
|
||||
describe('NumberFormatEditor', () => {
|
||||
beforeAll(() => {
|
||||
// Enzyme does not support the new Context API in shallow rendering.
|
||||
// @see https://github.com/enzymejs/enzyme/issues/2189
|
||||
(NumberFormatEditor as React.ComponentType<NumberFormatEditorProps>).contextTypes = {
|
||||
services: () => null,
|
||||
};
|
||||
delete (NumberFormatEditor as Partial<typeof NumberFormatEditor>).contextType;
|
||||
});
|
||||
|
||||
it('should have a formatId', () => {
|
||||
expect(NumberFormatEditor.formatId).toEqual('number');
|
||||
});
|
||||
|
@ -38,7 +55,8 @@ describe('NumberFormatEditor', () => {
|
|||
formatParams={formatParams}
|
||||
onChange={onChange}
|
||||
onError={onError}
|
||||
/>
|
||||
/>,
|
||||
{ context: KibanaReactContext.value }
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -15,12 +15,17 @@ import { DefaultFormatEditor, defaultState } from '../default';
|
|||
|
||||
import { FormatEditorSamples } from '../../samples';
|
||||
|
||||
import { context as contextType } from '../../../../../../kibana_react/public';
|
||||
|
||||
export interface NumberFormatEditorParams {
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
export class NumberFormatEditor extends DefaultFormatEditor<NumberFormatEditorParams> {
|
||||
static contextType = contextType;
|
||||
static formatId = 'number';
|
||||
|
||||
context!: React.ContextType<typeof contextType>;
|
||||
state = {
|
||||
...defaultState,
|
||||
sampleInputs: [10000, 12.345678, -1, -999, 0.52],
|
||||
|
@ -43,7 +48,10 @@ export class NumberFormatEditor extends DefaultFormatEditor<NumberFormatEditorPa
|
|||
}
|
||||
helpText={
|
||||
<span>
|
||||
<EuiLink target="_blank" href="https://adamwdraper.github.io/Numeral-js/">
|
||||
<EuiLink
|
||||
target="_blank"
|
||||
href={this.context.services.docLinks?.links.indexPatterns.fieldFormattersNumber}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="indexPatternFieldEditor.number.documentationLabel"
|
||||
defaultMessage="Documentation"
|
||||
|
|
|
@ -11,7 +11,7 @@ exports[`PercentFormatEditor should render normally 1`] = `
|
|||
helpText={
|
||||
<span>
|
||||
<EuiLink
|
||||
href="https://adamwdraper.github.io/Numeral-js/"
|
||||
href="https://www.elastic.co/guide/en/kibana/mocked-test-branch/numeral.html"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -8,10 +8,14 @@
|
|||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { coreMock } from 'src/core/public/mocks';
|
||||
import { createKibanaReactContext } from '../../../../../../kibana_react/public';
|
||||
import { FieldFormat } from 'src/plugins/data/public';
|
||||
|
||||
import { PercentFormatEditor } from './percent';
|
||||
|
||||
type PercentFormatEditorProps = React.ComponentProps<typeof PercentFormatEditor>;
|
||||
|
||||
const fieldType = 'number';
|
||||
const format = {
|
||||
getConverterFor: jest.fn().mockImplementation(() => (input: number) => input * 2),
|
||||
|
@ -25,7 +29,20 @@ const formatParams = {
|
|||
const onChange = jest.fn();
|
||||
const onError = jest.fn();
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext(
|
||||
coreMock.createStart({ basePath: 'my-base-path' })
|
||||
);
|
||||
|
||||
describe('PercentFormatEditor', () => {
|
||||
beforeAll(() => {
|
||||
// Enzyme does not support the new Context API in shallow rendering.
|
||||
// @see https://github.com/enzymejs/enzyme/issues/2189
|
||||
(PercentFormatEditor as React.ComponentType<PercentFormatEditorProps>).contextTypes = {
|
||||
services: () => null,
|
||||
};
|
||||
delete (PercentFormatEditor as Partial<typeof PercentFormatEditor>).contextType;
|
||||
});
|
||||
|
||||
it('should have a formatId', () => {
|
||||
expect(PercentFormatEditor.formatId).toEqual('percent');
|
||||
});
|
||||
|
@ -38,7 +55,8 @@ describe('PercentFormatEditor', () => {
|
|||
formatParams={formatParams}
|
||||
onChange={onChange}
|
||||
onError={onError}
|
||||
/>
|
||||
/>,
|
||||
{ context: KibanaReactContext.value }
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -1,5 +1,29 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Table render name 1`] = `
|
||||
<span>
|
||||
customer
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Table render name 2`] = `
|
||||
<span>
|
||||
customer
|
||||
<span>
|
||||
|
||||
<EuiIconTip
|
||||
content={
|
||||
<span>
|
||||
This field exists on the index pattern only.
|
||||
</span>
|
||||
}
|
||||
title="Runtime field"
|
||||
type="indexSettings"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Table should render conflicting type 1`] = `
|
||||
<span>
|
||||
conflict
|
||||
|
@ -142,6 +166,15 @@ exports[`Table should render normally 1`] = `
|
|||
"name": "conflictingField",
|
||||
"type": "text, long",
|
||||
},
|
||||
Object {
|
||||
"displayName": "customer",
|
||||
"excluded": false,
|
||||
"info": Array [],
|
||||
"isMapped": false,
|
||||
"kbnType": "text",
|
||||
"name": "customer",
|
||||
"type": "keyword",
|
||||
},
|
||||
]
|
||||
}
|
||||
pagination={
|
||||
|
|
|
@ -10,7 +10,7 @@ import React from 'react';
|
|||
import { shallow } from 'enzyme';
|
||||
import { IIndexPattern } from 'src/plugins/data/public';
|
||||
import { IndexedFieldItem } from '../../types';
|
||||
import { Table } from './table';
|
||||
import { Table, renderFieldName } from './table';
|
||||
|
||||
const indexPattern = {
|
||||
timeFieldName: 'timestamp',
|
||||
|
@ -48,6 +48,15 @@ const items: IndexedFieldItem[] = [
|
|||
format: '',
|
||||
isMapped: true,
|
||||
},
|
||||
{
|
||||
name: 'customer',
|
||||
displayName: 'customer',
|
||||
type: 'keyword',
|
||||
kbnType: 'text',
|
||||
info: [],
|
||||
excluded: false,
|
||||
isMapped: false,
|
||||
},
|
||||
];
|
||||
|
||||
const renderTable = (
|
||||
|
@ -103,4 +112,28 @@ describe('Table', () => {
|
|||
renderTable({ editField }).prop('columns')[6].actions[0].onClick();
|
||||
expect(editField).toBeCalled();
|
||||
});
|
||||
|
||||
test('render name', () => {
|
||||
const mappedField = {
|
||||
name: 'customer',
|
||||
info: [],
|
||||
excluded: false,
|
||||
kbnType: 'string',
|
||||
type: 'keyword',
|
||||
isMapped: true,
|
||||
};
|
||||
|
||||
expect(renderFieldName(mappedField)).toMatchSnapshot();
|
||||
|
||||
const runtimeField = {
|
||||
name: 'customer',
|
||||
info: [],
|
||||
excluded: false,
|
||||
kbnType: 'string',
|
||||
type: 'keyword',
|
||||
isMapped: false,
|
||||
};
|
||||
|
||||
expect(renderFieldName(runtimeField)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -157,6 +157,16 @@ const labelDescription = i18n.translate(
|
|||
{ defaultMessage: 'A custom label for the field.' }
|
||||
);
|
||||
|
||||
const runtimeIconTipTitle = i18n.translate(
|
||||
'indexPatternManagement.editIndexPattern.fields.table.runtimeIconTipTitle',
|
||||
{ defaultMessage: 'Runtime field' }
|
||||
);
|
||||
|
||||
const runtimeIconTipText = i18n.translate(
|
||||
'indexPatternManagement.editIndexPattern.fields.table.runtimeIconTipText',
|
||||
{ defaultMessage: 'This field exists on the index pattern only.' }
|
||||
);
|
||||
|
||||
interface IndexedFieldProps {
|
||||
indexPattern: IIndexPattern;
|
||||
items: IndexedFieldItem[];
|
||||
|
@ -164,54 +174,60 @@ interface IndexedFieldProps {
|
|||
deleteField: (fieldName: string) => void;
|
||||
}
|
||||
|
||||
export const renderFieldName = (field: IndexedFieldItem, timeFieldName?: string) => (
|
||||
<span>
|
||||
{field.name}
|
||||
{field.info && field.info.length ? (
|
||||
<span>
|
||||
|
||||
<EuiIconTip
|
||||
type="questionInCircle"
|
||||
color="primary"
|
||||
aria-label={additionalInfoAriaLabel}
|
||||
content={field.info.map((info: string, i: number) => (
|
||||
<div key={i}>{info}</div>
|
||||
))}
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
{timeFieldName === field.name ? (
|
||||
<span>
|
||||
|
||||
<EuiIconTip
|
||||
type="clock"
|
||||
color="primary"
|
||||
aria-label={primaryTimeAriaLabel}
|
||||
content={primaryTimeTooltip}
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
{!field.isMapped ? (
|
||||
<span>
|
||||
|
||||
<EuiIconTip
|
||||
type="indexSettings"
|
||||
title={runtimeIconTipTitle}
|
||||
content={<span>{runtimeIconTipText}</span>}
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
{field.customLabel && field.customLabel !== field.name ? (
|
||||
<div>
|
||||
<EuiToolTip content={labelDescription}>
|
||||
<EuiBadge iconType="flag" iconSide="left">
|
||||
{field.customLabel}
|
||||
</EuiBadge>
|
||||
</EuiToolTip>
|
||||
</div>
|
||||
) : null}
|
||||
</span>
|
||||
);
|
||||
|
||||
export class Table extends PureComponent<IndexedFieldProps> {
|
||||
renderBooleanTemplate(value: string, arialLabel: string) {
|
||||
return value ? <EuiIcon type="dot" color="secondary" aria-label={arialLabel} /> : <span />;
|
||||
}
|
||||
|
||||
renderFieldName(name: string, field: IndexedFieldItem) {
|
||||
const { indexPattern } = this.props;
|
||||
|
||||
return (
|
||||
<span>
|
||||
{field.name}
|
||||
{field.info && field.info.length ? (
|
||||
<span>
|
||||
|
||||
<EuiIconTip
|
||||
type="questionInCircle"
|
||||
color="primary"
|
||||
aria-label={additionalInfoAriaLabel}
|
||||
content={field.info.map((info: string, i: number) => (
|
||||
<div key={i}>{info}</div>
|
||||
))}
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
{indexPattern.timeFieldName === name ? (
|
||||
<span>
|
||||
|
||||
<EuiIconTip
|
||||
type="clock"
|
||||
color="primary"
|
||||
aria-label={primaryTimeAriaLabel}
|
||||
content={primaryTimeTooltip}
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
{field.customLabel && field.customLabel !== field.name ? (
|
||||
<div>
|
||||
<EuiToolTip content={labelDescription}>
|
||||
<EuiBadge iconType="flag" iconSide="left">
|
||||
{field.customLabel}
|
||||
</EuiBadge>
|
||||
</EuiToolTip>
|
||||
</div>
|
||||
) : null}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
renderFieldType(type: string, isConflict: boolean) {
|
||||
return (
|
||||
<span>
|
||||
|
@ -234,7 +250,7 @@ export class Table extends PureComponent<IndexedFieldProps> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { items, editField, deleteField } = this.props;
|
||||
const { items, editField, deleteField, indexPattern } = this.props;
|
||||
|
||||
const pagination = {
|
||||
initialPageSize: 10,
|
||||
|
@ -248,7 +264,7 @@ export class Table extends PureComponent<IndexedFieldProps> {
|
|||
dataType: 'string',
|
||||
sortable: true,
|
||||
render: (value: string, field: IndexedFieldItem) => {
|
||||
return this.renderFieldName(value, field);
|
||||
return renderFieldName(field, indexPattern.timeFieldName);
|
||||
},
|
||||
width: '38%',
|
||||
'data-test-subj': 'indexedFieldName',
|
||||
|
|
|
@ -269,11 +269,10 @@ export function getCoreUsageCollector(
|
|||
'Maximum size of the payload in bytes of saved objects that can be imported.',
|
||||
},
|
||||
},
|
||||
maxImportExportSizeBytes: {
|
||||
maxImportExportSize: {
|
||||
type: 'long',
|
||||
_meta: {
|
||||
description:
|
||||
'Maximum size in bytes of saved object that can be imported or exported.',
|
||||
description: 'Maximum count of saved objects that can be imported or exported.',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -30,7 +30,7 @@ export interface SaveModalDashboardProps {
|
|||
documentInfo: SaveModalDocumentInfo;
|
||||
objectType: string;
|
||||
onClose: () => void;
|
||||
onSave: (props: OnSaveProps & { dashboardId: string | null }) => void;
|
||||
onSave: (props: OnSaveProps & { dashboardId: string | null; addToLibrary: boolean }) => void;
|
||||
tagOptions?: React.ReactNode | ((state: SaveModalState) => React.ReactNode);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,9 @@ export function SavedObjectSaveModalDashboard(props: SaveModalDashboardProps) {
|
|||
const [dashboardOption, setDashboardOption] = useState<'new' | 'existing' | null>(
|
||||
documentId || disableDashboardOptions ? null : 'existing'
|
||||
);
|
||||
const [isAddToLibrarySelected, setAddToLibrary] = useState<boolean>(
|
||||
!initialCopyOnSave || disableDashboardOptions
|
||||
);
|
||||
const [selectedDashboard, setSelectedDashboard] = useState<{ id: string; name: string } | null>(
|
||||
null
|
||||
);
|
||||
|
@ -62,12 +65,13 @@ export function SavedObjectSaveModalDashboard(props: SaveModalDashboardProps) {
|
|||
onChange={(option) => {
|
||||
setDashboardOption(option);
|
||||
}}
|
||||
{...{ copyOnSave, documentId, dashboardOption }}
|
||||
{...{ copyOnSave, documentId, dashboardOption, setAddToLibrary, isAddToLibrarySelected }}
|
||||
/>
|
||||
)
|
||||
: null;
|
||||
|
||||
const onCopyOnSaveChange = (newCopyOnSave: boolean) => {
|
||||
setAddToLibrary(true);
|
||||
setDashboardOption(null);
|
||||
setCopyOnSave(newCopyOnSave);
|
||||
};
|
||||
|
@ -85,7 +89,7 @@ export function SavedObjectSaveModalDashboard(props: SaveModalDashboardProps) {
|
|||
}
|
||||
}
|
||||
|
||||
props.onSave({ ...onSaveProps, dashboardId });
|
||||
props.onSave({ ...onSaveProps, dashboardId, addToLibrary: isAddToLibrarySelected });
|
||||
};
|
||||
|
||||
const saveLibraryLabel =
|
||||
|
@ -113,7 +117,7 @@ export function SavedObjectSaveModalDashboard(props: SaveModalDashboardProps) {
|
|||
onSave={onModalSave}
|
||||
title={documentInfo.title}
|
||||
showCopyOnSave={documentId ? true : false}
|
||||
options={dashboardOption === null ? tagOptions : undefined} // Show tags when not adding to dashboard
|
||||
options={isAddToLibrarySelected ? tagOptions : undefined} // Show tags when not adding to dashboard
|
||||
description={documentInfo.description}
|
||||
showDescription={true}
|
||||
{...{
|
||||
|
|
|
@ -44,6 +44,7 @@ export function Example({
|
|||
hasDocumentId: boolean;
|
||||
} & StorybookParams) {
|
||||
const [dashboardOption, setDashboardOption] = useState<'new' | 'existing' | null>('existing');
|
||||
const [isAddToLibrarySelected, setAddToLibrary] = useState(false);
|
||||
|
||||
return (
|
||||
<SaveModalDashboardSelector
|
||||
|
@ -52,6 +53,8 @@ export function Example({
|
|||
dashboardOption={dashboardOption}
|
||||
copyOnSave={copyOnSave}
|
||||
documentId={hasDocumentId ? 'abc' : undefined}
|
||||
isAddToLibrarySelected={isAddToLibrarySelected}
|
||||
setAddToLibrary={setAddToLibrary}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
EuiIconTip,
|
||||
EuiPanel,
|
||||
EuiSpacer,
|
||||
EuiCheckbox,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { DashboardPicker, DashboardPickerProps } from './dashboard_picker';
|
||||
|
@ -29,24 +30,105 @@ export interface SaveModalDashboardSelectorProps {
|
|||
copyOnSave: boolean;
|
||||
documentId?: string;
|
||||
onSelectDashboard: DashboardPickerProps['onChange'];
|
||||
|
||||
setAddToLibrary: (selected: boolean) => void;
|
||||
isAddToLibrarySelected: boolean;
|
||||
dashboardOption: 'new' | 'existing' | null;
|
||||
onChange: (dashboardOption: 'new' | 'existing' | null) => void;
|
||||
}
|
||||
|
||||
export function SaveModalDashboardSelector(props: SaveModalDashboardSelectorProps) {
|
||||
const { documentId, onSelectDashboard, dashboardOption, onChange, copyOnSave } = props;
|
||||
const {
|
||||
documentId,
|
||||
onSelectDashboard,
|
||||
setAddToLibrary,
|
||||
isAddToLibrarySelected,
|
||||
dashboardOption,
|
||||
onChange,
|
||||
copyOnSave,
|
||||
} = props;
|
||||
const isDisabled = !copyOnSave && !!documentId;
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="presentationUtil.saveModalDashboard.addToDashboardLabel"
|
||||
defaultMessage="Add to dashboard"
|
||||
/>
|
||||
}
|
||||
hasChildLabel={false}
|
||||
>
|
||||
<>
|
||||
<EuiPanel color="subdued" hasShadow={false} data-test-subj="add-to-dashboard-options">
|
||||
<div>
|
||||
<>
|
||||
<EuiRadio
|
||||
checked={dashboardOption === 'existing'}
|
||||
id="existing-dashboard-option"
|
||||
name="dashboard-option"
|
||||
label={i18n.translate(
|
||||
'presentationUtil.saveModalDashboard.existingDashboardOptionLabel',
|
||||
{
|
||||
defaultMessage: 'Existing',
|
||||
}
|
||||
)}
|
||||
onChange={() => onChange('existing')}
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
<div className="savAddDashboard__searchDashboards">
|
||||
<DashboardPicker
|
||||
isDisabled={dashboardOption !== 'existing'}
|
||||
onChange={onSelectDashboard}
|
||||
/>
|
||||
</div>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
<>
|
||||
<EuiRadio
|
||||
checked={dashboardOption === 'new'}
|
||||
id="new-dashboard-option"
|
||||
name="dashboard-option"
|
||||
label={i18n.translate(
|
||||
'presentationUtil.saveModalDashboard.newDashboardOptionLabel',
|
||||
{
|
||||
defaultMessage: 'New',
|
||||
}
|
||||
)}
|
||||
onChange={() => onChange('new')}
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
<EuiRadio
|
||||
checked={dashboardOption === null}
|
||||
id="add-to-library-option"
|
||||
name="dashboard-option"
|
||||
label={i18n.translate(
|
||||
'presentationUtil.saveModalDashboard.noDashboardOptionLabel',
|
||||
{
|
||||
defaultMessage: 'None',
|
||||
}
|
||||
)}
|
||||
onChange={() => {
|
||||
setAddToLibrary(true);
|
||||
onChange(null);
|
||||
}}
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage
|
||||
id="presentationUtil.saveModalDashboard.addToDashboardLabel"
|
||||
defaultMessage="Add to dashboard"
|
||||
<EuiFlexItem grow={false} data-test-subj="add-to-library-checkbox">
|
||||
<EuiCheckbox
|
||||
id="add-to-library-checkbox"
|
||||
label={i18n.translate('presentationUtil.saveModalDashboard.libraryOptionLabel', {
|
||||
defaultMessage: 'Add to library',
|
||||
})}
|
||||
checked={isAddToLibrarySelected}
|
||||
disabled={dashboardOption === null || isDisabled}
|
||||
onChange={(event) => setAddToLibrary(event.target.checked)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -55,67 +137,13 @@ export function SaveModalDashboardSelector(props: SaveModalDashboardSelectorProp
|
|||
content={
|
||||
<FormattedMessage
|
||||
id="presentationUtil.saveModalDashboard.dashboardInfoTooltip"
|
||||
defaultMessage="Items added to a dashboard will not appear in the library and must be edited from the dashboard."
|
||||
defaultMessage="items added to the Visualize Library are available to all dashboards. Edits to a library item appear everywhere it is used."
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
hasChildLabel={false}
|
||||
>
|
||||
<EuiPanel color="subdued" hasShadow={false} data-test-subj="add-to-dashboard-options">
|
||||
<div>
|
||||
<>
|
||||
<EuiRadio
|
||||
checked={dashboardOption === 'existing'}
|
||||
id="existing-dashboard-option"
|
||||
name="dashboard-option"
|
||||
label={i18n.translate(
|
||||
'presentationUtil.saveModalDashboard.existingDashboardOptionLabel',
|
||||
{
|
||||
defaultMessage: 'Existing',
|
||||
}
|
||||
)}
|
||||
onChange={() => onChange('existing')}
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
<div className="savAddDashboard__searchDashboards">
|
||||
<DashboardPicker
|
||||
isDisabled={dashboardOption !== 'existing'}
|
||||
onChange={onSelectDashboard}
|
||||
/>
|
||||
</div>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
<>
|
||||
<EuiRadio
|
||||
checked={dashboardOption === 'new'}
|
||||
id="new-dashboard-option"
|
||||
name="dashboard-option"
|
||||
label={i18n.translate(
|
||||
'presentationUtil.saveModalDashboard.newDashboardOptionLabel',
|
||||
{
|
||||
defaultMessage: 'New',
|
||||
}
|
||||
)}
|
||||
onChange={() => onChange('new')}
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
<EuiRadio
|
||||
checked={dashboardOption === null}
|
||||
id="add-to-library-option"
|
||||
name="dashboard-option"
|
||||
label={i18n.translate('presentationUtil.saveModalDashboard.libraryOptionLabel', {
|
||||
defaultMessage: 'No dashboard, but add to library',
|
||||
})}
|
||||
onChange={() => onChange(null)}
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -6675,10 +6675,10 @@
|
|||
"description": "Maximum size of the payload in bytes of saved objects that can be imported."
|
||||
}
|
||||
},
|
||||
"maxImportExportSizeBytes": {
|
||||
"maxImportExportSize": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "Maximum size in bytes of saved object that can be imported or exported."
|
||||
"description": "Maximum count of saved objects that can be imported or exported."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1672,7 +1672,12 @@ describe('migration visualization', () => {
|
|||
doc as Parameters<SavedObjectMigrationFn>[0],
|
||||
savedObjectMigrationContext
|
||||
);
|
||||
const getTestDoc = (type = 'area', categoryAxes?: object[], valueAxes?: object[]) => ({
|
||||
const getTestDoc = (
|
||||
type = 'area',
|
||||
categoryAxes?: object[],
|
||||
valueAxes?: object[],
|
||||
hasPalette = false
|
||||
) => ({
|
||||
attributes: {
|
||||
title: 'My Vis',
|
||||
description: 'This is my super cool vis.',
|
||||
|
@ -1691,6 +1696,12 @@ describe('migration visualization', () => {
|
|||
labels: {},
|
||||
},
|
||||
],
|
||||
...(hasPalette && {
|
||||
palette: {
|
||||
type: 'palette',
|
||||
name: 'default',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -1709,13 +1720,20 @@ describe('migration visualization', () => {
|
|||
expect(isVislibVis).toEqual(true);
|
||||
});
|
||||
|
||||
it('should decorate existing docs with the kibana legacy palette', () => {
|
||||
it('should decorate existing docs without a predefined palette with the kibana legacy palette', () => {
|
||||
const migratedTestDoc = migrate(getTestDoc());
|
||||
const { palette } = JSON.parse(migratedTestDoc.attributes.visState).params;
|
||||
|
||||
expect(palette.name).toEqual('kibana_palette');
|
||||
});
|
||||
|
||||
it('should not overwrite the palette with the legacy one if the palette already exists in the saved object', () => {
|
||||
const migratedTestDoc = migrate(getTestDoc('area', undefined, undefined, true));
|
||||
const { palette } = JSON.parse(migratedTestDoc.attributes.visState).params;
|
||||
|
||||
expect(palette.name).toEqual('default');
|
||||
});
|
||||
|
||||
describe('labels.filter', () => {
|
||||
it('should keep existing categoryAxes labels.filter value', () => {
|
||||
const migratedTestDoc = migrate(getTestDoc('area', [{ labels: { filter: false } }]));
|
||||
|
|
|
@ -859,6 +859,7 @@ const migrateVislibAreaLineBarTypes: SavedObjectMigrationFn<any, any> = (doc) =>
|
|||
const isHorizontalBar = visState.type === 'horizontal_bar';
|
||||
const isLineOrArea =
|
||||
visState?.params?.type === CHART_TYPE_AREA || visState?.params?.type === CHART_TYPE_LINE;
|
||||
const hasPalette = visState?.params?.palette;
|
||||
return {
|
||||
...doc,
|
||||
attributes: {
|
||||
|
@ -867,10 +868,12 @@ const migrateVislibAreaLineBarTypes: SavedObjectMigrationFn<any, any> = (doc) =>
|
|||
...visState,
|
||||
params: {
|
||||
...visState.params,
|
||||
palette: {
|
||||
type: 'palette',
|
||||
name: 'kibana_palette',
|
||||
},
|
||||
...(!hasPalette && {
|
||||
palette: {
|
||||
type: 'palette',
|
||||
name: 'kibana_palette',
|
||||
},
|
||||
}),
|
||||
categoryAxes:
|
||||
visState.params.categoryAxes &&
|
||||
decorateAxes(visState.params.categoryAxes, !isHorizontalBar),
|
||||
|
|
|
@ -93,7 +93,7 @@ export const getTopNavConfig = (
|
|||
/**
|
||||
* Called when the user clicks "Save" button.
|
||||
*/
|
||||
async function doSave(saveOptions: SavedObjectSaveOpts) {
|
||||
async function doSave(saveOptions: SavedObjectSaveOpts & { dashboardId?: string }) {
|
||||
const newlyCreated = !Boolean(savedVis.id) || savedVis.copyOnSave;
|
||||
// vis.title was not bound and it's needed to reflect title into visState
|
||||
stateContainer.transitions.setVis({
|
||||
|
@ -118,7 +118,7 @@ export const getTopNavConfig = (
|
|||
'data-test-subj': 'saveVisualizationSuccess',
|
||||
});
|
||||
|
||||
if (originatingApp && saveOptions.returnToOrigin) {
|
||||
if ((originatingApp && saveOptions.returnToOrigin) || saveOptions.dashboardId) {
|
||||
if (!embeddableId) {
|
||||
const appPath = `${VisualizeConstants.EDIT_PATH}/${encodeURIComponent(id)}`;
|
||||
|
||||
|
@ -127,16 +127,26 @@ export const getTopNavConfig = (
|
|||
setActiveUrl(appPath);
|
||||
}
|
||||
|
||||
const app = originatingApp || 'dashboards';
|
||||
|
||||
let path;
|
||||
if (saveOptions.dashboardId) {
|
||||
path =
|
||||
saveOptions.dashboardId === 'new' ? '#/create' : `#/view/${saveOptions.dashboardId}`;
|
||||
}
|
||||
|
||||
if (newlyCreated && stateTransfer) {
|
||||
stateTransfer.navigateToWithEmbeddablePackage(originatingApp, {
|
||||
stateTransfer.navigateToWithEmbeddablePackage(app, {
|
||||
state: {
|
||||
type: VISUALIZE_EMBEDDABLE_TYPE,
|
||||
input: { savedObjectId: id },
|
||||
embeddableId,
|
||||
},
|
||||
path,
|
||||
});
|
||||
} else {
|
||||
application.navigateToApp(originatingApp);
|
||||
// TODO: need the same thing here?
|
||||
application.navigateToApp(app, { path });
|
||||
}
|
||||
} else {
|
||||
if (setOriginatingApp && originatingApp && newlyCreated) {
|
||||
|
@ -321,7 +331,11 @@ export const getTopNavConfig = (
|
|||
newDescription,
|
||||
returnToOrigin,
|
||||
dashboardId,
|
||||
}: OnSaveProps & { returnToOrigin?: boolean } & { dashboardId?: string | null }) => {
|
||||
addToLibrary,
|
||||
}: OnSaveProps & { returnToOrigin?: boolean } & {
|
||||
dashboardId?: string | null;
|
||||
addToLibrary?: boolean;
|
||||
}) => {
|
||||
const currentTitle = savedVis.title;
|
||||
savedVis.title = newTitle;
|
||||
embeddableHandler.updateInput({ title: newTitle });
|
||||
|
@ -337,9 +351,12 @@ export const getTopNavConfig = (
|
|||
isTitleDuplicateConfirmed,
|
||||
onTitleDuplicate,
|
||||
returnToOrigin,
|
||||
dashboardId: !!dashboardId ? dashboardId : undefined,
|
||||
};
|
||||
|
||||
if (dashboardId) {
|
||||
// If we're adding to a dashboard and not saving to library,
|
||||
// we'll want to use a by-value operation
|
||||
if (dashboardId && !addToLibrary) {
|
||||
const appPath = `${VisualizeConstants.LANDING_PAGE_PATH}`;
|
||||
|
||||
// Manually insert a new url so the back button will open the saved visualization.
|
||||
|
@ -369,6 +386,8 @@ export const getTopNavConfig = (
|
|||
return { id: true };
|
||||
}
|
||||
|
||||
// We're adding the viz to a library so we need to save it and then
|
||||
// add to a dashboard if necessary
|
||||
const response = await doSave(saveOptions);
|
||||
// If the save wasn't successful, put the original values back.
|
||||
if (!response.id || response.error) {
|
||||
|
|
|
@ -553,7 +553,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
expect(resp.body).to.eql({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Can't export more than 10001 objects`,
|
||||
message: `Can't export more than 10001 objects. If your server has enough memory, this limit can be increased by adjusting the \"savedObjects.maxImportExportSize\" setting.`,
|
||||
});
|
||||
});
|
||||
await supertest
|
||||
|
|
|
@ -105,7 +105,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.discover.waitForDocTableLoadingComplete();
|
||||
});
|
||||
|
||||
it('navigates to doc view from embeddable', async () => {
|
||||
// flaky https://github.com/elastic/kibana/issues/93670
|
||||
it.skip('navigates to doc view from embeddable', async () => {
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.discover.saveSearch('my search');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
|
|
@ -58,7 +58,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.timePicker.setDefaultAbsoluteRange();
|
||||
});
|
||||
|
||||
it('should show popover with expanded cell content by click on expand button', async () => {
|
||||
// flaky https://github.com/elastic/kibana/issues/94889
|
||||
it.skip('should show popover with expanded cell content by click on expand button', async () => {
|
||||
log.debug('open popover with expanded cell content to get json from the editor');
|
||||
const documentCell = await dataGrid.getCellElement(1, 3);
|
||||
await documentCell.click();
|
||||
|
|
|
@ -26,7 +26,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
]);
|
||||
|
||||
describe('Add to Dashboard', function describeIndexTests() {
|
||||
it('adding a new metric to a new dashboard', async function () {
|
||||
it('adding a new metric to a new dashboard by value', async function () {
|
||||
await PageObjects.visualize.navigateToNewAggBasedVisualization();
|
||||
await PageObjects.visualize.clickMetric();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
|
@ -36,6 +36,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
await PageObjects.timeToVisualize.saveFromModal('My New Vis 1', {
|
||||
addToDashboard: 'new',
|
||||
saveToLibrary: false,
|
||||
});
|
||||
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
|
@ -43,10 +44,39 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.eql(1);
|
||||
|
||||
const isLinked = await PageObjects.timeToVisualize.libraryNotificationExists('My New Vis 1');
|
||||
expect(isLinked).to.be(false);
|
||||
|
||||
await PageObjects.timeToVisualize.resetNewDashboard();
|
||||
});
|
||||
|
||||
it('adding a existing metric to a new dashboard', async function () {
|
||||
it('adding a new metric to a new dashboard by reference', async function () {
|
||||
await PageObjects.visualize.navigateToNewAggBasedVisualization();
|
||||
await PageObjects.visualize.clickMetric();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
await PageObjects.timePicker.setDefaultAbsoluteRange();
|
||||
|
||||
await testSubjects.click('visualizeSaveButton');
|
||||
|
||||
await PageObjects.timeToVisualize.saveFromModal('My Saved New Vis 1', {
|
||||
addToDashboard: 'new',
|
||||
saveToLibrary: true,
|
||||
});
|
||||
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await dashboardExpect.metricValuesExist(['14,004']);
|
||||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.eql(1);
|
||||
|
||||
const isLinked = await PageObjects.timeToVisualize.libraryNotificationExists(
|
||||
'My Saved New Vis 1'
|
||||
);
|
||||
expect(isLinked).to.be(true);
|
||||
|
||||
await PageObjects.timeToVisualize.resetNewDashboard();
|
||||
});
|
||||
|
||||
it('adding a existing metric to a new dashboard by value', async function () {
|
||||
await PageObjects.visualize.navigateToNewAggBasedVisualization();
|
||||
await PageObjects.visualize.clickMetric();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
|
@ -57,6 +87,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
// Save this new viz to library
|
||||
await PageObjects.timeToVisualize.saveFromModal('My New Vis 1', {
|
||||
addToDashboard: null,
|
||||
saveToLibrary: true,
|
||||
});
|
||||
|
||||
await testSubjects.click('visualizeSaveButton');
|
||||
|
@ -68,6 +99,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.timeToVisualize.saveFromModal('My New Vis 1 Copy', {
|
||||
addToDashboard: 'new',
|
||||
saveAsNew: true,
|
||||
saveToLibrary: false,
|
||||
});
|
||||
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
|
@ -75,10 +107,85 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.eql(1);
|
||||
|
||||
const isLinked = await PageObjects.timeToVisualize.libraryNotificationExists(
|
||||
'My New Vis 1 Copy'
|
||||
);
|
||||
expect(isLinked).to.be(false);
|
||||
|
||||
await PageObjects.timeToVisualize.resetNewDashboard();
|
||||
});
|
||||
|
||||
it('adding a new metric to an existing dashboard', async function () {
|
||||
it('adding a existing metric to a new dashboard by reference', async function () {
|
||||
await PageObjects.visualize.navigateToNewAggBasedVisualization();
|
||||
await PageObjects.visualize.clickMetric();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
await PageObjects.timePicker.setDefaultAbsoluteRange();
|
||||
|
||||
await testSubjects.click('visualizeSaveButton');
|
||||
|
||||
// Save this new viz to library
|
||||
await PageObjects.timeToVisualize.saveFromModal('Another New Vis 1', {
|
||||
addToDashboard: null,
|
||||
saveToLibrary: true,
|
||||
});
|
||||
|
||||
await testSubjects.click('visualizeSaveButton');
|
||||
|
||||
// All the options should be disabled
|
||||
await PageObjects.timeToVisualize.ensureDashboardOptionsAreDisabled();
|
||||
|
||||
// Save a new copy of this viz to a new dashboard
|
||||
await PageObjects.timeToVisualize.saveFromModal('Another New Vis 1 Copy', {
|
||||
addToDashboard: 'new',
|
||||
saveAsNew: true,
|
||||
saveToLibrary: true,
|
||||
});
|
||||
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await dashboardExpect.metricValuesExist(['14,004']);
|
||||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.eql(1);
|
||||
|
||||
const isLinked = await PageObjects.timeToVisualize.libraryNotificationExists(
|
||||
'Another New Vis 1 Copy'
|
||||
);
|
||||
expect(isLinked).to.be(true);
|
||||
|
||||
await PageObjects.timeToVisualize.resetNewDashboard();
|
||||
});
|
||||
|
||||
it('adding a new metric to an existing dashboard by value', async function () {
|
||||
await PageObjects.common.navigateToApp('dashboard');
|
||||
|
||||
await PageObjects.dashboard.clickNewDashboard();
|
||||
await PageObjects.dashboard.addVisualizations(['Visualization AreaChart']);
|
||||
await PageObjects.dashboard.saveDashboard('My Excellent Dashboard');
|
||||
await PageObjects.dashboard.gotoDashboardLandingPage();
|
||||
await listingTable.searchAndExpectItemsCount('dashboard', 'My Excellent Dashboard', 1);
|
||||
|
||||
await PageObjects.visualize.navigateToNewAggBasedVisualization();
|
||||
await PageObjects.visualize.clickMetric();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
await PageObjects.timePicker.setDefaultAbsoluteRange();
|
||||
|
||||
await testSubjects.click('visualizeSaveButton');
|
||||
|
||||
await PageObjects.timeToVisualize.saveFromModal('My New Vis 2', {
|
||||
addToDashboard: 'existing',
|
||||
dashboardId: 'My Excellent Dashboard',
|
||||
saveToLibrary: false,
|
||||
});
|
||||
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await dashboardExpect.metricValuesExist(['14,004']);
|
||||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.eql(2);
|
||||
|
||||
const isLinked = await PageObjects.timeToVisualize.libraryNotificationExists('My New Vis 2');
|
||||
expect(isLinked).to.be(false);
|
||||
});
|
||||
|
||||
it('adding a new metric to an existing dashboard by reference', async function () {
|
||||
await PageObjects.common.navigateToApp('dashboard');
|
||||
|
||||
await PageObjects.dashboard.clickNewDashboard();
|
||||
|
@ -94,18 +201,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
await testSubjects.click('visualizeSaveButton');
|
||||
|
||||
await PageObjects.timeToVisualize.saveFromModal('My New Vis 2', {
|
||||
await PageObjects.timeToVisualize.saveFromModal('My Saved New Vis 2', {
|
||||
addToDashboard: 'existing',
|
||||
dashboardId: 'My Wonderful Dashboard',
|
||||
saveToLibrary: true,
|
||||
});
|
||||
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await dashboardExpect.metricValuesExist(['14,004']);
|
||||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.eql(2);
|
||||
|
||||
const isLinked = await PageObjects.timeToVisualize.libraryNotificationExists(
|
||||
'My Saved New Vis 2'
|
||||
);
|
||||
expect(isLinked).to.be(true);
|
||||
});
|
||||
|
||||
it('adding a existing metric to an existing dashboard', async function () {
|
||||
it('adding a existing metric to an existing dashboard by value', async function () {
|
||||
await PageObjects.common.navigateToApp('dashboard');
|
||||
|
||||
await PageObjects.dashboard.clickNewDashboard();
|
||||
|
@ -124,6 +237,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
// Save this new viz to library
|
||||
await PageObjects.timeToVisualize.saveFromModal('My New Vis 2', {
|
||||
addToDashboard: null,
|
||||
saveToLibrary: true,
|
||||
});
|
||||
|
||||
await testSubjects.click('visualizeSaveButton');
|
||||
|
@ -136,12 +250,64 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
addToDashboard: 'existing',
|
||||
dashboardId: 'My Very Cool Dashboard',
|
||||
saveAsNew: true,
|
||||
saveToLibrary: false,
|
||||
});
|
||||
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await dashboardExpect.metricValuesExist(['14,004']);
|
||||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.eql(2);
|
||||
|
||||
const isLinked = await PageObjects.timeToVisualize.libraryNotificationExists(
|
||||
'My New Vis 2 Copy'
|
||||
);
|
||||
expect(isLinked).to.be(false);
|
||||
});
|
||||
|
||||
it('adding a existing metric to an existing dashboard by reference', async function () {
|
||||
await PageObjects.common.navigateToApp('dashboard');
|
||||
|
||||
await PageObjects.dashboard.clickNewDashboard();
|
||||
await PageObjects.dashboard.addVisualizations(['Visualization AreaChart']);
|
||||
await PageObjects.dashboard.saveDashboard('My Very Neat Dashboard');
|
||||
await PageObjects.dashboard.gotoDashboardLandingPage();
|
||||
await listingTable.searchAndExpectItemsCount('dashboard', 'My Very Neat Dashboard', 1);
|
||||
|
||||
await PageObjects.visualize.navigateToNewAggBasedVisualization();
|
||||
await PageObjects.visualize.clickMetric();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
await PageObjects.timePicker.setDefaultAbsoluteRange();
|
||||
|
||||
await testSubjects.click('visualizeSaveButton');
|
||||
|
||||
// Save this new viz to library
|
||||
await PageObjects.timeToVisualize.saveFromModal('Neat Saved Vis 2', {
|
||||
addToDashboard: null,
|
||||
saveToLibrary: true,
|
||||
});
|
||||
|
||||
await testSubjects.click('visualizeSaveButton');
|
||||
|
||||
// All the options should be disabled
|
||||
await PageObjects.timeToVisualize.ensureDashboardOptionsAreDisabled();
|
||||
|
||||
// Save a new copy of this viz to an existing dashboard
|
||||
await PageObjects.timeToVisualize.saveFromModal('Neat Saved Vis 2 Copy', {
|
||||
addToDashboard: 'existing',
|
||||
dashboardId: 'My Very Neat Dashboard',
|
||||
saveAsNew: true,
|
||||
saveToLibrary: true,
|
||||
});
|
||||
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await dashboardExpect.metricValuesExist(['14,004']);
|
||||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.eql(2);
|
||||
|
||||
const isLinked = await PageObjects.timeToVisualize.libraryNotificationExists(
|
||||
'Neat Saved Vis 2 Copy'
|
||||
);
|
||||
expect(isLinked).to.be(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import { FtrProviderContext } from '../ftr_provider_context';
|
|||
|
||||
interface SaveModalArgs {
|
||||
addToDashboard?: 'new' | 'existing' | null;
|
||||
saveToLibrary?: boolean;
|
||||
dashboardId?: string;
|
||||
saveAsNew?: boolean;
|
||||
redirectToOrigin?: boolean;
|
||||
|
@ -35,7 +36,9 @@ export function TimeToVisualizePageProvider({ getService, getPageObjects }: FtrP
|
|||
const dashboardSelector = await testSubjects.find('add-to-dashboard-options');
|
||||
await dashboardSelector.findByCssSelector(`input[id="new-dashboard-option"]:disabled`);
|
||||
await dashboardSelector.findByCssSelector(`input[id="existing-dashboard-option"]:disabled`);
|
||||
await dashboardSelector.findByCssSelector(`input[id="add-to-library-option"]:disabled`);
|
||||
|
||||
const librarySelector = await testSubjects.find('add-to-library-checkbox');
|
||||
await librarySelector.findByCssSelector(`input[id="add-to-library-checkbox"]:disabled`);
|
||||
}
|
||||
|
||||
public async resetNewDashboard() {
|
||||
|
@ -46,7 +49,13 @@ export function TimeToVisualizePageProvider({ getService, getPageObjects }: FtrP
|
|||
|
||||
public async setSaveModalValues(
|
||||
vizName: string,
|
||||
{ saveAsNew, redirectToOrigin, addToDashboard, dashboardId }: SaveModalArgs = {}
|
||||
{
|
||||
saveAsNew,
|
||||
redirectToOrigin,
|
||||
addToDashboard,
|
||||
dashboardId,
|
||||
saveToLibrary,
|
||||
}: SaveModalArgs = {}
|
||||
) {
|
||||
await testSubjects.setValue('savedObjectTitle', vizName);
|
||||
|
||||
|
@ -57,13 +66,6 @@ export function TimeToVisualizePageProvider({ getService, getPageObjects }: FtrP
|
|||
await testSubjects.setEuiSwitch('saveAsNewCheckbox', state);
|
||||
}
|
||||
|
||||
const hasRedirectToOrigin = await testSubjects.exists('returnToOriginModeSwitch');
|
||||
if (hasRedirectToOrigin && redirectToOrigin !== undefined) {
|
||||
const state = redirectToOrigin ? 'check' : 'uncheck';
|
||||
log.debug('redirect to origin checkbox exists. Setting its state to', state);
|
||||
await testSubjects.setEuiSwitch('returnToOriginModeSwitch', state);
|
||||
}
|
||||
|
||||
const hasDashboardSelector = await testSubjects.exists('add-to-dashboard-options');
|
||||
if (hasDashboardSelector && addToDashboard !== undefined) {
|
||||
let option: DashboardPickerOption = 'add-to-library-option';
|
||||
|
@ -80,6 +82,40 @@ export function TimeToVisualizePageProvider({ getService, getPageObjects }: FtrP
|
|||
await find.clickByButtonText(dashboardId);
|
||||
}
|
||||
}
|
||||
|
||||
const hasSaveToLibrary = await testSubjects.exists('add-to-library-checkbox');
|
||||
if (hasSaveToLibrary && saveToLibrary !== undefined) {
|
||||
const libraryCheckbox = await find.byCssSelector('#add-to-library-checkbox');
|
||||
const isChecked = await libraryCheckbox.isSelected();
|
||||
const needsClick = isChecked !== saveToLibrary;
|
||||
const state = saveToLibrary ? 'check' : 'uncheck';
|
||||
|
||||
log.debug('save to library checkbox exists. Setting its state to', state);
|
||||
if (needsClick) {
|
||||
const selector = await testSubjects.find('add-to-library-checkbox');
|
||||
const label = await selector.findByCssSelector(`label[for="add-to-library-checkbox"]`);
|
||||
await label.click();
|
||||
}
|
||||
}
|
||||
|
||||
const hasRedirectToOrigin = await testSubjects.exists('returnToOriginModeSwitch');
|
||||
if (hasRedirectToOrigin && redirectToOrigin !== undefined) {
|
||||
const state = redirectToOrigin ? 'check' : 'uncheck';
|
||||
log.debug('redirect to origin checkbox exists. Setting its state to', state);
|
||||
await testSubjects.setEuiSwitch('returnToOriginModeSwitch', state);
|
||||
}
|
||||
}
|
||||
|
||||
public async libraryNotificationExists(panelTitle: string) {
|
||||
log.debug('searching for library modal on panel:', panelTitle);
|
||||
const panel = await testSubjects.find(
|
||||
`embeddablePanelHeading-${panelTitle.replace(/ /g, '')}`
|
||||
);
|
||||
const libraryActionExists = await testSubjects.descendantExists(
|
||||
'embeddablePanelNotification-ACTION_LIBRARY_NOTIFICATION',
|
||||
panel
|
||||
);
|
||||
return libraryActionExists;
|
||||
}
|
||||
|
||||
public async saveFromModal(
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
export * from './cases';
|
||||
export * from './connectors';
|
||||
export * from './helpers';
|
||||
export * from './runtime_types';
|
||||
export * from './saved_object';
|
||||
export * from './user';
|
||||
|
|