From 84b23b6d7ca021d2674563d7c6cb2ec6c33d08b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Thu, 29 Oct 2020 12:39:20 -0400 Subject: [PATCH 1/9] Move task manager README.md to root of plugin (#82012) * Move task manager README.md to root of plugin * Fix failing test, update task manager plugin description in docs --- docs/developer/plugin-list.asciidoc | 4 ++-- x-pack/plugins/task_manager/{server => }/README.md | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) rename x-pack/plugins/task_manager/{server => }/README.md (99%) diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 8e08c3806446d..914bd8fce6dff 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -488,8 +488,8 @@ the alertTypes by the Stack in the alerting plugin, register associated HTTP routes, etc. -|{kib-repo}blob/{branch}/x-pack/plugins/task_manager[taskManager] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/task_manager/README.md[taskManager] +|The task manager is a generic system for running background tasks. |{kib-repo}blob/{branch}/x-pack/plugins/telemetry_collection_xpack/README.md[telemetryCollectionXpack] diff --git a/x-pack/plugins/task_manager/server/README.md b/x-pack/plugins/task_manager/README.md similarity index 99% rename from x-pack/plugins/task_manager/server/README.md rename to x-pack/plugins/task_manager/README.md index a0b35ad094537..b25d3cc49f980 100644 --- a/x-pack/plugins/task_manager/server/README.md +++ b/x-pack/plugins/task_manager/README.md @@ -1,7 +1,8 @@ # Kibana task manager -The task manager is a generic system for running background tasks. It supports: +The task manager is a generic system for running background tasks. +It supports: - Single-run and recurring tasks - Scheduling tasks to run after a specified datetime - Basic retry logic From 052f8277fea0df42e41cab0dc021b7ef7bddc893 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Thu, 29 Oct 2020 10:56:42 -0700 Subject: [PATCH 2/9] Add READMEs for ES UI plugins (#81973) * Add Search Profiler README. * Add Upgrade Assistant README. * Add name of plugin to Watcher README. * Add Console Extensions README. * Add Grok Debugger README. * Add Painless Lab README. * Add License Management README. * Add Remote Clusters README. * Add Console README. --- docs/developer/plugin-list.asciidoc | 37 +++++++----- src/plugins/console/README.md | 5 ++ x-pack/plugins/console_extensions/README.md | 3 + x-pack/plugins/grokdebugger/README.md | 6 ++ x-pack/plugins/license_management/README.md | 5 ++ x-pack/plugins/painless_lab/README.md | 5 ++ x-pack/plugins/remote_clusters/README.md | 5 ++ x-pack/plugins/searchprofiler/README.md | 8 +++ x-pack/plugins/upgrade_assistant/README.md | 67 +++++++++++++++++++++ x-pack/plugins/watcher/README.md | 4 +- 10 files changed, 127 insertions(+), 18 deletions(-) create mode 100644 src/plugins/console/README.md create mode 100644 x-pack/plugins/console_extensions/README.md create mode 100644 x-pack/plugins/grokdebugger/README.md create mode 100644 x-pack/plugins/license_management/README.md create mode 100644 x-pack/plugins/painless_lab/README.md create mode 100644 x-pack/plugins/remote_clusters/README.md create mode 100644 x-pack/plugins/searchprofiler/README.md create mode 100644 x-pack/plugins/upgrade_assistant/README.md diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 914bd8fce6dff..f30afce3ee02c 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -38,8 +38,8 @@ NOTE: |The Charts plugin is a way to create easier integration of shared colors, themes, types and other utilities across all Kibana charts and visualizations. -|{kib-repo}blob/{branch}/src/plugins/console[console] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/src/plugins/console/README.md[console] +|Console provides the user with tools for storing and executing requests against Elasticsearch. |<> @@ -307,8 +307,8 @@ Failure to have auth enabled in Kibana will make for a broken UI. UI-based error |WARNING: Missing README. -|{kib-repo}blob/{branch}/x-pack/plugins/console_extensions[consoleExtensions] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/console_extensions/README.md[consoleExtensions] +|This plugin provides autocomplete definitions of licensed APIs to the OSS Console plugin. |{kib-repo}blob/{branch}/x-pack/plugins/cross_cluster_replication/README.md[crossClusterReplication] @@ -376,8 +376,9 @@ or dashboards from the Kibana instance, from both server and client-side plugins |This is the main source folder of the Graph plugin. It contains all of the Kibana server and client source code. x-pack/test/functional/apps/graph contains additional functional tests. -|{kib-repo}blob/{branch}/x-pack/plugins/grokdebugger[grokdebugger] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/grokdebugger/README.md[grokdebugger] +|This plugin helps users define Grok patterns, +which are particularly useful for ingesting logs. |{kib-repo}blob/{branch}/x-pack/plugins/index_lifecycle_management/README.md[indexLifecycleManagement] @@ -406,8 +407,8 @@ the infrastructure monitoring use-case within Kibana. |Run all tests from the x-pack root directory -|{kib-repo}blob/{branch}/x-pack/plugins/license_management[licenseManagement] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/license_management/README.md[licenseManagement] +|This plugin enables users to activate a trial license, downgrade to Basic, and upload a new license. |{kib-repo}blob/{branch}/x-pack/plugins/licensing/README.md[licensing] @@ -444,12 +445,12 @@ Elastic. |This plugin provides shared components and services for use across observability solutions, as well as the observability landing page UI. -|{kib-repo}blob/{branch}/x-pack/plugins/painless_lab[painlessLab] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/painless_lab/README.md[painlessLab] +|This plugin helps users learn how to use the Painless scripting language. -|{kib-repo}blob/{branch}/x-pack/plugins/remote_clusters[remoteClusters] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/remote_clusters/README.md[remoteClusters] +|This plugin helps users manage their remote clusters, which enable cross-cluster search and cross-cluster replication. |{kib-repo}blob/{branch}/x-pack/plugins/reporting/README.md[reporting] @@ -460,8 +461,11 @@ Elastic. |Welcome to the Kibana rollup plugin! This plugin provides Kibana support for Elasticsearch's rollup feature. Please refer to the Elasticsearch documentation to understand rollup indices and how to create rollup jobs. -|{kib-repo}blob/{branch}/x-pack/plugins/searchprofiler[searchprofiler] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/searchprofiler/README.md[searchprofiler] +|The search profiler consumes the Profile API +by sending a search API with profile: true enabled in the request body. The response contains +detailed information on how Elasticsearch executed the search request. People use this information +to understand why a search request might be slow. |{kib-repo}blob/{branch}/x-pack/plugins/security/README.md[security] @@ -513,8 +517,9 @@ As a developer you can reuse and extend built-in alerts and actions UI functiona |Registers commercially licensed generic actions like per panel time range and contains some code that supports drilldown work. -|{kib-repo}blob/{branch}/x-pack/plugins/upgrade_assistant[upgradeAssistant] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/upgrade_assistant/README.md[upgradeAssistant] +|Upgrade Assistant helps users prepare their Stack for being upgraded to the next major. Its primary +purposes are to: |{kib-repo}blob/{branch}/x-pack/plugins/uptime/README.md[uptime] diff --git a/src/plugins/console/README.md b/src/plugins/console/README.md new file mode 100644 index 0000000000000..07421151f8087 --- /dev/null +++ b/src/plugins/console/README.md @@ -0,0 +1,5 @@ +# Console + +## About + +Console provides the user with tools for storing and executing requests against Elasticsearch. \ No newline at end of file diff --git a/x-pack/plugins/console_extensions/README.md b/x-pack/plugins/console_extensions/README.md new file mode 100644 index 0000000000000..49d83d2888d6b --- /dev/null +++ b/x-pack/plugins/console_extensions/README.md @@ -0,0 +1,3 @@ +# Console extensions + +This plugin provides autocomplete definitions of licensed APIs to the OSS Console plugin. \ No newline at end of file diff --git a/x-pack/plugins/grokdebugger/README.md b/x-pack/plugins/grokdebugger/README.md new file mode 100644 index 0000000000000..80729b35500b6 --- /dev/null +++ b/x-pack/plugins/grokdebugger/README.md @@ -0,0 +1,6 @@ +# Grok Debugger + +## About + +This plugin helps users define [Grok patterns](https://www.elastic.co/guide/en/elasticsearch/reference/current/grok-processor.html), +which are particularly useful for ingesting logs. \ No newline at end of file diff --git a/x-pack/plugins/license_management/README.md b/x-pack/plugins/license_management/README.md new file mode 100644 index 0000000000000..b103c8fcd6721 --- /dev/null +++ b/x-pack/plugins/license_management/README.md @@ -0,0 +1,5 @@ +# License Management + +## About + +This plugin enables users to activate a trial license, downgrade to Basic, and upload a new license. \ No newline at end of file diff --git a/x-pack/plugins/painless_lab/README.md b/x-pack/plugins/painless_lab/README.md new file mode 100644 index 0000000000000..519b6a9dea8ed --- /dev/null +++ b/x-pack/plugins/painless_lab/README.md @@ -0,0 +1,5 @@ +# Painless Lab + +## About + +This plugin helps users learn how to use the [Painless scripting language](https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting-painless.html). \ No newline at end of file diff --git a/x-pack/plugins/remote_clusters/README.md b/x-pack/plugins/remote_clusters/README.md new file mode 100644 index 0000000000000..1119c98ffe84a --- /dev/null +++ b/x-pack/plugins/remote_clusters/README.md @@ -0,0 +1,5 @@ +# Remote Clusters + +## About + +This plugin helps users manage their [remote clusters](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-remote-clusters.html), which enable cross-cluster search and cross-cluster replication. \ No newline at end of file diff --git a/x-pack/plugins/searchprofiler/README.md b/x-pack/plugins/searchprofiler/README.md new file mode 100644 index 0000000000000..6e25163470488 --- /dev/null +++ b/x-pack/plugins/searchprofiler/README.md @@ -0,0 +1,8 @@ +# Search Profiler + +## About + +The search profiler consumes the [Profile API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-profile.html) +by sending a `search` API with `profile: true` enabled in the request body. The response contains +detailed information on how Elasticsearch executed the search request. People use this information +to understand why a search request might be slow. \ No newline at end of file diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md new file mode 100644 index 0000000000000..a6cb3b431c82b --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -0,0 +1,67 @@ +# Upgrade Assistant + +## About + +Upgrade Assistant helps users prepare their Stack for being upgraded to the next major. Its primary +purposes are to: + +* **Surface deprecations.** Deprecations are features that are currently being used that will be +removed in the next major. Surfacing tells the user that there's a problem preventing them +from upgrading. +* **Migrate from deprecation features to supported features.** This addresses the problem, clearing +the path for the upgrade. Generally speaking, once all deprecations are addressed, the user can +safely upgrade. + +### Deprecations + +There are two sources of deprecation information: + +* [**Deprecation Info API.**](https://www.elastic.co/guide/en/elasticsearch/reference/master/migration-api-deprecation.html) +This is information about cluster, node, and index level settings that use deprecated features that +will be removed or changed in the next major version. Currently, only cluster and index deprecations +will be surfaced in the Upgrade Assistant. ES server engineers are responsible for adding +deprecations to the Deprecation Info API. +* [**Deprecation logs.**](https://www.elastic.co/guide/en/elasticsearch/reference/current/logging.html#deprecation-logging) +These surface runtime deprecations, e.g. a Painless script that uses a deprecated accessor or a +request to a deprecated API. These are also generally surfaced as deprecation headers within the +response. Even if the cluster state is good, app maintainers need to watch the logs in case +deprecations are discovered as data is migrated. + +### Fixing problems + +Problems can be fixed at various points in the upgrade process. The Upgrade Assistant supports +various upgrade paths and surfaces various types of upgrade-related issues. + +* **Fixing deprecated cluster settings pre-upgrade.** This generally requires fixing some settings +in `elasticsearch.yml`. +* **Migrating indices data pre-upgrade.** This can involve deleting indices so that ES can rebuild +them in the new version, reindexing them so that they're built using a new Lucene version, or +applying a migration script that reindexes them with new settings/mappings/etc. +* **Migrating indices data post-upgrade.** As was the case with APM in the 6.8->7.x upgrade, +sometimes the new data format isn't forwards-compatible. In these cases, the user will perform the +upgrade first and then use the Upgrade Assistant to reindex their data to be compatible with the new +version. + +Deprecations can be handled in a number of ways: + +* **Reindexing.** When a user's index contains deprecations (e.g. mappings) a reindex solves them. +Upgrade Assistant contains migration scripts that are executed as part of the reindex process. +The user will see a "Reindex" button they can click which will apply this script and perform the +reindex. + * Reindexing is an atomic process in Upgrade Assistant, so that ingestion is never disrupted. + It works like this: + * Create a new index with a "reindexed-" prefix ([#30114](https://github.com/elastic/kibana/pull/30114)). + * Create an index alias pointing from the original index name to the prefixed index name. + * Reindex from the original index into the prefixed index. + * Delete the old index and rename the prefixed index. + * Some apps might require custom scripts, as was the case with APM ([#29845](https://github.com/elastic/kibana/pull/29845)). + In that case the migration performed a reindex with a Painless script (covered by automated tests) + that made the required changes to the data. +* **Update index settings.** Some index settings will need to be updated, which doesn't require a +reindex. An example of this is the "Fix" button that was added for metricbeat and filebeat indices +([#32829](https://github.com/elastic/kibana/pull/32829), [#33439](https://github.com/elastic/kibana/pull/33439)). +* **Following the docs.** The Deprecation Info API provides links to the deprecation docs. Users +will follow these docs to address the problem and make these warnings or errors disappear in the +Upgrade Assistant. +* **Stopping/restarting tasks and jobs.** Users had to stop watches and ML jobs and restart them as +soon as reindexing was complete ([#29663](https://github.com/elastic/kibana/pull/29663)). \ No newline at end of file diff --git a/x-pack/plugins/watcher/README.md b/x-pack/plugins/watcher/README.md index 4f9111760a0a6..c849a65019174 100644 --- a/x-pack/plugins/watcher/README.md +++ b/x-pack/plugins/watcher/README.md @@ -1,4 +1,4 @@ -# Conventions +# Watcher This plugins adopts some conventions in addition to or in place of conventions in Kibana (at the time of the plugin's creation): @@ -69,4 +69,4 @@ encapsulating operations around such relationships — for example, updating the ### Kibana client code This layer deals almost exclusively with data in the form of client models. The one exception to this rule is when the client code needs -to bootstrap a model instance from a bare JS object — for example, creating a new `Watch` model from the contents of the Add/Edit Watch Form. +to bootstrap a model instance from a bare JS object — for example, creating a new `Watch` model from the contents of the Add/Edit Watch Form. \ No newline at end of file From d84ac13a4abd5de1f97aede2843b7c62745d191b Mon Sep 17 00:00:00 2001 From: Jason Rhodes Date: Thu, 29 Oct 2020 14:04:37 -0400 Subject: [PATCH 3/9] [Logs App] Fix logs permissions for alert management (#81199) * Mimics metrics permissions for alert mgmt in logs feature * Updates logs security functional tests Alert management permissions were added for read and all logs users in this PR, so both of these users now have "Stack Management" appear in the nav. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/infra/server/features.ts | 9 +++++++++ .../apps/infra/feature_controls/logs_security.ts | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/infra/server/features.ts b/x-pack/plugins/infra/server/features.ts index d49755b6f68c1..c768cae247a99 100644 --- a/x-pack/plugins/infra/server/features.ts +++ b/x-pack/plugins/infra/server/features.ts @@ -68,6 +68,9 @@ export const LOGS_FEATURE = { category: DEFAULT_APP_CATEGORIES.observability, app: ['infra', 'logs', 'kibana'], catalogue: ['infralogging', 'logs'], + management: { + insightsAndAlerting: ['triggersActions'], + }, alerting: [LOG_DOCUMENT_COUNT_ALERT_TYPE_ID], privileges: { all: { @@ -81,6 +84,9 @@ export const LOGS_FEATURE = { alerting: { all: [LOG_DOCUMENT_COUNT_ALERT_TYPE_ID], }, + management: { + insightsAndAlerting: ['triggersActions'], + }, ui: ['show', 'configureSource', 'save'], }, read: { @@ -90,6 +96,9 @@ export const LOGS_FEATURE = { alerting: { read: [LOG_DOCUMENT_COUNT_ALERT_TYPE_ID], }, + management: { + insightsAndAlerting: ['triggersActions'], + }, savedObject: { all: [], read: ['infrastructure-ui-source'], diff --git a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts index de6353d6b0456..78edbafa4ae47 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts @@ -58,7 +58,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows logs navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Logs']); + expect(navLinks).to.eql(['Overview', 'Logs', 'Stack Management']); }); describe('logs landing page without data', () => { @@ -121,7 +121,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows logs navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Logs']); + expect(navLinks).to.eql(['Overview', 'Logs', 'Stack Management']); }); describe('logs landing page without data', () => { From ee7ce25048818611416e9cc3a9791aa82d19583c Mon Sep 17 00:00:00 2001 From: Jane Miller <57721870+jmiller263@users.noreply.github.com> Date: Thu, 29 Oct 2020 14:09:01 -0400 Subject: [PATCH 4/9] [SECURITY_SOLUTION] 145: Advanced Policy UI (#80390) * Create Policies for each generated host * Refactor Ingest setup to also setup Fleet * Rename prop name * Add generic response type to KbnClient.request + support for headers * first attempt at adding fleet agent registration * a little closer with fleet integration * SUCCESS. Able to enroll agent and set it to online * update names to be policy * policy generator has advanced types in endpoint confit * linting * flesh out callback * add submit button for verify_peer * add verify hostname field * 145 generalize cb * 145 fix setAgain and getValue * 145 merge conflict * 145 add verify_hostname back, start loop for form * 145 remove OS trick * 145 make AdvancedPolicyForms its own component * 145 grid partially working * 145 back to basics * 145 back to basics * 145 rolled back grid * 145 flex table working * 145 undo accidental change * 145 remove extra schema file * 145 remove unused variable * 145 kevin's PR feedback * 145 fix type check and jest * 145 EuiFlexGroups * 145 use simple EuiFormRow and add show/hide buttons * 145 move all advanced policy code to advanced file; remove unnec test code * 145 fix IDs * 145 take out unnecessary stuff * 145 removed a couple more lines * 145 add some fields back in * 145 add spacer Co-authored-by: Paul Tavares Co-authored-by: Elastic Machine Co-authored-by: kevinlog Co-authored-by: Candace Park --- .../common/endpoint/types/index.ts | 9 +- .../policy/models/advanced_policy_schema.ts | 315 ++++++++++++++++++ .../policy/models/policy_details_config.ts | 41 +-- .../policy/store/policy_details/index.test.ts | 8 +- .../policy/store/policy_details/selectors.ts | 3 + .../management/pages/policy/view/index.ts | 1 + .../pages/policy/view/policy_advanced.tsx | 124 +++++++ .../pages/policy/view/policy_details.tsx | 18 + .../view/policy_forms/protections/malware.tsx | 8 +- 9 files changed, 477 insertions(+), 50 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/policy_advanced.tsx diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 882b3e5182bf3..79157018c315a 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -860,6 +860,7 @@ type KbnConfigSchemaNonOptionalProps> = Pi */ export interface PolicyConfig { windows: { + advanced?: {}; events: { dll_and_driver_load: boolean; dns: boolean; @@ -881,6 +882,7 @@ export interface PolicyConfig { }; }; mac: { + advanced?: {}; events: { file: boolean; process: boolean; @@ -898,6 +900,7 @@ export interface PolicyConfig { }; }; linux: { + advanced?: {}; events: { file: boolean; process: boolean; @@ -916,15 +919,15 @@ export interface UIPolicyConfig { /** * Windows-specific policy configuration that is supported via the UI */ - windows: Pick; + windows: Pick; /** * Mac-specific policy configuration that is supported via the UI */ - mac: Pick; + mac: Pick; /** * Linux-specific policy configuration that is supported via the UI */ - linux: Pick; + linux: Pick; } /** Policy: Malware protection fields */ diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts b/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts new file mode 100644 index 0000000000000..d25588dabedc6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts @@ -0,0 +1,315 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +interface AdvancedPolicySchemaType { + key: string; + first_supported_version: string; + last_supported_version?: string; + documentation: string; +} + +export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ + { + key: 'linux.advanced.agent.connection_delay', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.artifacts.global.base_url', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.artifacts.global.manifest_relative_url', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.artifacts.global.ca_cert', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.artifacts.global.public_key', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.artifacts.global.interval', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.artifacts.user.base_url', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.artifacts.user.ca_cert', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.artifacts.user.public_key', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.artifacts.user.interval', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.elasticsearch.delay', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'linux.advanced.elasticsearch.tls.verify_peer', + first_supported_version: '7.11', + documentation: 'default is true', + }, + { + key: 'linux.advanced.elasticsearch.tls.verify_hostname', + first_supported_version: '7.11', + documentation: 'default is true', + }, + { + key: 'linux.advanced.elasticsearch.tls.ca_cert', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.agent.connection_delay', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.artifacts.global.base_url', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.artifacts.global.manifest_relative_url', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.artifacts.global.ca_cert', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.artifacts.global.public_key', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.artifacts.global.interval', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.artifacts.user.base_url', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.artifacts.user.ca_cert', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.artifacts.user.public_key', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.artifacts.user.interval', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.elasticsearch.delay', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.elasticsearch.tls.verify_peer', + first_supported_version: '7.11', + documentation: 'default is true', + }, + { + key: 'mac.advanced.elasticsearch.tls.verify_hostname', + first_supported_version: '7.11', + documentation: 'default is true', + }, + { + key: 'mac.advanced.elasticsearch.tls.ca_cert', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.malware.quarantine', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.kernel.connect', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.kernel.harden', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.kernel.process', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.kernel.filewrite', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'mac.advanced.kernel.network', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.agent.connection_delay', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.artifacts.global.base_url', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.artifacts.global.manifest_relative_url', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.artifacts.global.ca_cert', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.artifacts.global.public_key', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.artifacts.global.interval', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.artifacts.user.base_url', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.artifacts.user.ca_cert', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.artifacts.user.public_key', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.artifacts.user.interval', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.elasticsearch.delay', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.elasticsearch.tls.verify_peer', + first_supported_version: '7.11', + documentation: 'default is true', + }, + { + key: 'windows.advanced.elasticsearch.tls.verify_hostname', + first_supported_version: '7.11', + documentation: 'default is true', + }, + { + key: 'windows.advanced.elasticsearch.tls.ca_cert', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.malware.quarantine', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.ransomware.mbr', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.ransomware.canary', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.kernel.connect', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.kernel.harden', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.kernel.process', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.kernel.filewrite', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.kernel.network', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.kernel.fileopen', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.kernel.asyncimageload', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.kernel.syncimageload', + first_supported_version: '7.11', + documentation: '', + }, + { + key: 'windows.advanced.kernel.registry', + first_supported_version: '7.11', + documentation: '', + }, +]; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/models/policy_details_config.ts b/x-pack/plugins/security_solution/public/management/pages/policy/models/policy_details_config.ts index 4d32a9fbec694..8d5c19a9e489a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/models/policy_details_config.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/models/policy_details_config.ts @@ -4,46 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +import { cloneDeep } from 'lodash'; import { UIPolicyConfig } from '../../../../../common/endpoint/types'; -/** - * A typed Object.entries() function where the keys and values are typed based on the given object - */ -const entries = (o: T): Array<[keyof T, T[keyof T]]> => - Object.entries(o) as Array<[keyof T, T[keyof T]]>; -type DeepPartial = { [K in keyof T]?: DeepPartial }; - -/** - * Returns a deep copy of `UIPolicyConfig` object - */ -export function clone(policyDetailsConfig: UIPolicyConfig): UIPolicyConfig { - const clonedConfig: DeepPartial = {}; - for (const [key, val] of entries(policyDetailsConfig)) { - if (typeof val === 'object') { - const valClone: Partial = {}; - clonedConfig[key] = valClone; - for (const [key2, val2] of entries(val)) { - if (typeof val2 === 'object') { - valClone[key2] = { - ...val2, - }; - } else { - clonedConfig[key] = { - ...val, - }; - } - } - } else { - clonedConfig[key] = val; - } - } - - /** - * clonedConfig is typed as DeepPartial so we can construct the copy from an empty object - */ - return clonedConfig as UIPolicyConfig; -} - /** * Returns value from `configuration` */ @@ -69,7 +32,7 @@ export const setIn = (a: UIPolicyConfig) => (k >( v: V ): UIPolicyConfig => { - const c = clone(a); + const c = cloneDeep(a); c[key][subKey][leafKey] = v; return c; }; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts index b76e0c8acf4c3..89ba05547f447 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts @@ -8,7 +8,6 @@ import { PolicyDetailsState } from '../../types'; import { applyMiddleware, createStore, Dispatch, Store } from 'redux'; import { policyDetailsReducer, PolicyDetailsAction, policyDetailsMiddlewareFactory } from './index'; import { policyConfig } from './selectors'; -import { clone } from '../../models/policy_details_config'; import { factory as policyConfigFactory } from '../../../../../../common/endpoint/models/policy_config'; import { PolicyData } from '../../../../../../common/endpoint/types'; import { @@ -20,6 +19,7 @@ import { createAppRootMockRenderer, } from '../../../../../common/mock/endpoint'; import { HttpFetchOptions } from 'kibana/public'; +import { cloneDeep } from 'lodash'; describe('policy details: ', () => { let store: Store; @@ -93,7 +93,7 @@ describe('policy details: ', () => { throw new Error(); } - const newPayload1 = clone(config); + const newPayload1 = cloneDeep(config); newPayload1.windows.events.process = true; dispatch({ @@ -115,7 +115,7 @@ describe('policy details: ', () => { throw new Error(); } - const newPayload1 = clone(config); + const newPayload1 = cloneDeep(config); newPayload1.mac.events.file = true; dispatch({ @@ -137,7 +137,7 @@ describe('policy details: ', () => { throw new Error(); } - const newPayload1 = clone(config); + const newPayload1 = cloneDeep(config); newPayload1.linux.events.file = true; dispatch({ diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors.ts index 953438526b87e..f275124a73527 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors.ts @@ -103,16 +103,19 @@ export const policyConfig: (s: PolicyDetailsState) => UIPolicyConfig = createSel (windows, mac, linux) => { return { windows: { + advanced: windows.advanced, events: windows.events, malware: windows.malware, popup: windows.popup, }, mac: { + advanced: mac.advanced, events: mac.events, malware: mac.malware, popup: mac.popup, }, linux: { + advanced: linux.advanced, events: linux.events, }, }; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/index.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/index.ts index 9c227ca81a426..ce942205b1620 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/index.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/index.ts @@ -6,3 +6,4 @@ export * from './policy_list'; export * from './policy_details'; +export * from './policy_advanced'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_advanced.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_advanced.tsx new file mode 100644 index 0000000000000..b4b82b7f692b9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_advanced.tsx @@ -0,0 +1,124 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useCallback } from 'react'; +import { useDispatch } from 'react-redux'; +import { EuiFieldText, EuiFormRow, EuiPanel, EuiText } from '@elastic/eui'; +import { cloneDeep } from 'lodash'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { policyConfig } from '../store/policy_details/selectors'; +import { usePolicyDetailsSelector } from './policy_hooks'; +import { AdvancedPolicySchema } from '../models/advanced_policy_schema'; + +function setValue(obj: Record, value: string, path: string[]) { + let newPolicyConfig = obj; + for (let i = 0; i < path.length - 1; i++) { + if (!newPolicyConfig[path[i]]) { + newPolicyConfig[path[i]] = {} as Record; + } + newPolicyConfig = newPolicyConfig[path[i]] as Record; + } + newPolicyConfig[path[path.length - 1]] = value; +} + +function getValue(obj: Record, path: string[]) { + let currentPolicyConfig = obj; + + for (let i = 0; i < path.length - 1; i++) { + if (currentPolicyConfig[path[i]]) { + currentPolicyConfig = currentPolicyConfig[path[i]] as Record; + } else { + return undefined; + } + } + return currentPolicyConfig[path[path.length - 1]]; +} + +export const AdvancedPolicyForms = React.memo(() => { + return ( + <> + +

+ +

+
+ + {AdvancedPolicySchema.map((advancedField, index) => { + const configPath = advancedField.key.split('.'); + return ( + + ); + })} + + + ); +}); + +AdvancedPolicyForms.displayName = 'AdvancedPolicyForms'; + +const PolicyAdvanced = React.memo( + ({ + configPath, + firstSupportedVersion, + lastSupportedVersion, + }: { + configPath: string[]; + firstSupportedVersion: string; + lastSupportedVersion?: string; + }) => { + const dispatch = useDispatch(); + const policyDetailsConfig = usePolicyDetailsSelector(policyConfig); + const onChange = useCallback( + (event) => { + if (policyDetailsConfig) { + const newPayload = cloneDeep(policyDetailsConfig); + setValue( + (newPayload as unknown) as Record, + event.target.value, + configPath + ); + dispatch({ + type: 'userChangedPolicyConfig', + payload: { policyConfig: newPayload }, + }); + } + }, + [dispatch, policyDetailsConfig, configPath] + ); + + const value = + policyDetailsConfig && + getValue((policyDetailsConfig as unknown) as Record, configPath); + + return ( + <> + + {lastSupportedVersion + ? `${firstSupportedVersion}-${lastSupportedVersion}` + : `${firstSupportedVersion}+`} + + } + > + + + + ); + } +); + +PolicyAdvanced.displayName = 'PolicyAdvanced'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx index 40c982cfc071b..8fc5de48f36db 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx @@ -47,6 +47,7 @@ import { MANAGEMENT_APP_ID } from '../../../common/constants'; import { PolicyDetailsRouteState } from '../../../../../common/endpoint/types'; import { WrapperPage } from '../../../../common/components/wrapper_page'; import { HeaderPage } from '../../../../common/components/header_page'; +import { AdvancedPolicyForms } from './policy_advanced'; export const PolicyDetails = React.memo(() => { const dispatch = useDispatch<(action: AppAction) => void>(); @@ -69,6 +70,7 @@ export const PolicyDetails = React.memo(() => { // Local state const [showConfirm, setShowConfirm] = useState(false); const [routeState, setRouteState] = useState(); + const [showAdvancedPolicy, setShowAdvancedPolicy] = useState(false); const policyName = policyItem?.name ?? ''; const hostListRouterPath = getEndpointListPath({ name: 'endpointList' }); @@ -128,6 +130,10 @@ export const PolicyDetails = React.memo(() => { setShowConfirm(false); }, []); + const handleAdvancedPolicyClick = useCallback(() => { + setShowAdvancedPolicy(!showAdvancedPolicy); + }, [showAdvancedPolicy]); + useEffect(() => { if (!routeState && locationRouteState) { setRouteState(locationRouteState); @@ -245,6 +251,18 @@ export const PolicyDetails = React.memo(() => { + + + + + + + + {showAdvancedPolicy && } diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx index 6773ed6541927..215851fb28152 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx @@ -19,6 +19,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { cloneDeep } from 'lodash'; import { APP_ID } from '../../../../../../../common/constants'; import { SecurityPageName } from '../../../../../../app/types'; @@ -27,7 +28,6 @@ import { OS, MalwareProtectionOSes } from '../../../types'; import { ConfigForm } from '../config_form'; import { policyConfig } from '../../../store/policy_details/selectors'; import { usePolicyDetailsSelector } from '../../policy_hooks'; -import { clone } from '../../../models/policy_details_config'; import { LinkToApp } from '../../../../../../common/components/endpoint/link_to_app'; import { popupVersionsMap } from './popup_options_to_versions'; @@ -50,7 +50,7 @@ const ProtectionRadio = React.memo(({ id, label }: { id: ProtectionModes; label: const handleRadioChange = useCallback(() => { if (policyDetailsConfig) { - const newPayload = clone(policyDetailsConfig); + const newPayload = cloneDeep(policyDetailsConfig); for (const os of OSes) { newPayload[os][protection].mode = id; if (id === ProtectionModes.prevent) { @@ -141,7 +141,7 @@ export const MalwareProtections = React.memo(() => { const handleSwitchChange = useCallback( (event) => { if (policyDetailsConfig) { - const newPayload = clone(policyDetailsConfig); + const newPayload = cloneDeep(policyDetailsConfig); if (event.target.checked === false) { for (const os of OSes) { newPayload[os][protection].mode = ProtectionModes.off; @@ -165,7 +165,7 @@ export const MalwareProtections = React.memo(() => { const handleUserNotificationCheckbox = useCallback( (event) => { if (policyDetailsConfig) { - const newPayload = clone(policyDetailsConfig); + const newPayload = cloneDeep(policyDetailsConfig); for (const os of OSes) { newPayload[os].popup[protection].enabled = event.target.checked; } From 5752b7a8ddd28d245bd5f2887b1d146fe99936aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Oct 2020 14:21:36 -0400 Subject: [PATCH 5/9] Bump xml-crypto from 1.4.0 to 2.0.0 (#81859) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index ec4388c0b8b7d..ba464a21263d7 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -259,7 +259,7 @@ "venn.js": "0.2.20", "vinyl-fs": "^3.0.3", "whatwg-fetch": "^3.0.0", - "xml-crypto": "^1.4.0", + "xml-crypto": "^2.0.0", "yargs": "^15.4.1" }, "dependencies": { diff --git a/yarn.lock b/yarn.lock index b2216537bbd7c..6b77b14f09d42 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29247,10 +29247,10 @@ xhr@^2.0.1: parse-headers "^2.0.0" xtend "^4.0.0" -xml-crypto@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/xml-crypto/-/xml-crypto-1.4.0.tgz#de1cec8cd31cbd689cd90d3d6e8a27d4ae807de7" - integrity sha512-K8FRdRxICVulK4WhiTUcJrRyAIJFPVOqxfurA3x/JlmXBTxy+SkEENF6GeRt7p/rB6WSOUS9g0gXNQw5n+407g== +xml-crypto@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/xml-crypto/-/xml-crypto-2.0.0.tgz#54cd268ad9d31930afcf7092cbb664258ca9e826" + integrity sha512-/a04qr7RpONRZHOxROZ6iIHItdsQQjN3sj8lJkYDDss8tAkEaAs0VrFjb3tlhmS5snQru5lTs9/5ISSMdPDHlg== dependencies: xmldom "0.1.27" xpath "0.0.27" From e0b6b0ba5cabe78fb884e629144e4d088bdf92c6 Mon Sep 17 00:00:00 2001 From: Nick Partridge Date: Thu, 29 Oct 2020 13:34:41 -0500 Subject: [PATCH 6/9] Vislib visualization renderer (#80744) --- .../public/components/tag_cloud_chart.tsx | 4 +- .../public/timelion_vis_renderer.tsx | 6 - .../public/__snapshots__/pie_fn.test.ts.snap | 5 +- .../public/__snapshots__/to_ast.test.ts.snap | 22 + .../__snapshots__/to_ast_pie.test.ts.snap | 19 + src/plugins/vis_type_vislib/public/area.ts | 19 +- .../public/components/options/gauge/index.tsx | 4 +- .../components/options/heatmap/index.tsx | 4 +- .../public/components/options/index.tsx | 51 + .../options/metrics_axes/index.test.tsx | 2 +- .../components/options/metrics_axes/index.tsx | 4 +- .../public/components/options/pie.tsx | 4 +- .../components/options/point_series/index.ts | 4 +- src/plugins/vis_type_vislib/public/gauge.ts | 11 +- src/plugins/vis_type_vislib/public/goal.ts | 11 +- src/plugins/vis_type_vislib/public/heatmap.ts | 20 +- .../vis_type_vislib/public/histogram.ts | 19 +- .../vis_type_vislib/public/horizontal_bar.ts | 19 +- src/plugins/vis_type_vislib/public/index.scss | 2 +- src/plugins/vis_type_vislib/public/line.ts | 19 +- src/plugins/vis_type_vislib/public/pie.ts | 16 +- src/plugins/vis_type_vislib/public/pie_fn.ts | 37 +- src/plugins/vis_type_vislib/public/plugin.ts | 73 +- .../public/sample_vis.test.mocks.ts | 3307 +++++++++++++++++ .../vis_type_vislib/public/services.ts | 5 - .../vis_type_vislib/public/to_ast.test.ts | 60 + src/plugins/vis_type_vislib/public/to_ast.ts | 103 + .../options/index.ts => to_ast_esaggs.ts} | 26 +- .../vis_type_vislib/public/to_ast_pie.test.ts | 60 + .../vis_type_vislib/public/to_ast_pie.ts | 50 + src/plugins/vis_type_vislib/public/types.ts | 6 + .../vis_type_vislib/public/vis_controller.tsx | 172 +- .../vis_type_vislib/public/vis_renderer.tsx | 61 + .../public/vis_type_vislib_vis_fn.ts | 42 +- .../public/vis_type_vislib_vis_types.ts | 27 +- .../vis_type_vislib/public/vis_wrapper.tsx | 89 + .../public/vislib/_vislib_vis_type.scss | 14 +- .../vislib/components/legend/_legend.scss | 9 +- .../vislib/components/legend/legend.test.tsx | 36 +- .../vislib/components/legend/legend.tsx | 49 +- .../helpers/point_series/_init_x_axis.ts | 4 +- .../helpers/point_series/point_series.ts | 5 +- .../public/vislib/lib/_handler.scss | 17 - .../public/vislib/lib/_index.scss | 1 - .../public/vislib/lib/dispatch.js | 4 - .../public/vislib/lib/handler.js | 22 +- .../public/vislib/lib/handler.test.js | 2 +- .../public/vislib/lib/vis_config.js | 1 - .../vis_type_vislib/public/vislib/vis.js | 13 +- .../public/vislib/visualizations/_chart.js | 4 +- .../vislib/visualizations/_vis_fixture.js | 17 +- .../vislib/visualizations/gauge_chart.test.js | 4 +- .../public/vislib/visualizations/pie_chart.js | 4 +- .../vislib/visualizations/pie_chart.test.js | 8 +- .../vislib/visualizations/point_series.js | 14 +- .../visualizations/point_series/area_chart.js | 4 +- .../point_series/area_chart.test.js | 4 +- .../point_series/column_chart.js | 4 +- .../point_series/column_chart.test.js | 16 +- .../point_series/heatmap_chart.test.js | 4 +- .../visualizations/point_series/line_chart.js | 4 +- .../point_series/line_chart.test.js | 4 +- .../public/components/_visualization.scss | 4 +- src/plugins/visualizations/public/index.ts | 1 + .../__snapshots__/build_pipeline.test.ts.snap | 2 - .../public/legacy/build_pipeline.test.ts | 164 - .../public/legacy/build_pipeline.ts | 96 - src/plugins/visualizations/public/types.ts | 2 +- .../page_objects/visualize_chart_page.ts | 2 +- 69 files changed, 4235 insertions(+), 687 deletions(-) create mode 100644 src/plugins/vis_type_vislib/public/__snapshots__/to_ast.test.ts.snap create mode 100644 src/plugins/vis_type_vislib/public/__snapshots__/to_ast_pie.test.ts.snap create mode 100644 src/plugins/vis_type_vislib/public/components/options/index.tsx create mode 100644 src/plugins/vis_type_vislib/public/sample_vis.test.mocks.ts create mode 100644 src/plugins/vis_type_vislib/public/to_ast.test.ts create mode 100644 src/plugins/vis_type_vislib/public/to_ast.ts rename src/plugins/vis_type_vislib/public/{components/options/index.ts => to_ast_esaggs.ts} (51%) create mode 100644 src/plugins/vis_type_vislib/public/to_ast_pie.test.ts create mode 100644 src/plugins/vis_type_vislib/public/to_ast_pie.ts create mode 100644 src/plugins/vis_type_vislib/public/vis_renderer.tsx create mode 100644 src/plugins/vis_type_vislib/public/vis_wrapper.tsx delete mode 100644 src/plugins/vis_type_vislib/public/vislib/lib/_handler.scss diff --git a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_chart.tsx b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_chart.tsx index cb0daa6d29382..a14328ac994f0 100644 --- a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_chart.tsx +++ b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_chart.tsx @@ -45,7 +45,9 @@ export const TagCloudChart = ({ const visController = useRef(null); useEffect(() => { - visController.current = new TagCloudVisualization(chartDiv.current, colors, fireEvent); + if (chartDiv.current) { + visController.current = new TagCloudVisualization(chartDiv.current, colors, fireEvent); + } return () => { visController.current.destroy(); visController.current = null; diff --git a/src/plugins/vis_type_timelion/public/timelion_vis_renderer.tsx b/src/plugins/vis_type_timelion/public/timelion_vis_renderer.tsx index 04579407105e8..2c914d3c5b662 100644 --- a/src/plugins/vis_type_timelion/public/timelion_vis_renderer.tsx +++ b/src/plugins/vis_type_timelion/public/timelion_vis_renderer.tsx @@ -42,12 +42,6 @@ export const getTimelionVisRenderer: ( const [seriesList] = visData.sheet; const showNoResult = !seriesList || !seriesList.list.length; - if (showNoResult) { - // send the render complete event when there is no data to show - // to notify that a chart is updated - handlers.done(); - } - render( diff --git a/src/plugins/vis_type_vislib/public/__snapshots__/pie_fn.test.ts.snap b/src/plugins/vis_type_vislib/public/__snapshots__/pie_fn.test.ts.snap index 2cee55e4751c2..b64366c1ce0f3 100644 --- a/src/plugins/vis_type_vislib/public/__snapshots__/pie_fn.test.ts.snap +++ b/src/plugins/vis_type_vislib/public/__snapshots__/pie_fn.test.ts.snap @@ -2,12 +2,9 @@ exports[`interpreter/functions#pie returns an object with the correct structure 1`] = ` Object { - "as": "visualization", + "as": "vislib_vis", "type": "render", "value": Object { - "params": Object { - "listenOnChange": true, - }, "visConfig": Object { "addLegend": true, "addTooltip": true, diff --git a/src/plugins/vis_type_vislib/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_type_vislib/public/__snapshots__/to_ast.test.ts.snap new file mode 100644 index 0000000000000..c3ffc0dd08412 --- /dev/null +++ b/src/plugins/vis_type_vislib/public/__snapshots__/to_ast.test.ts.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`vislib vis toExpressionAst function should match basic snapshot 1`] = ` +Object { + "addArgument": [Function], + "arguments": Object { + "type": Array [ + "area", + ], + "visConfig": Array [ + "{\\"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},\\"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,\\"thresholdLine\\":{\\"show\\":false,\\"value\\":10,\\"width\\":1,\\"style\\":\\"full\\",\\"color\\":\\"#E7664C\\"},\\"labels\\":{},\\"dimensions\\":{\\"x\\":{\\"accessor\\":1,\\"format\\":{\\"id\\":\\"date\\",\\"params\\":{\\"pattern\\":\\"HH:mm:ss.SSS\\"}},\\"params\\":{}},\\"y\\":[{\\"accessor\\":0,\\"format\\":{\\"id\\":\\"number\\",\\"params\\":{\\"parsedUrl\\":{\\"origin\\":\\"http://localhost:5801\\",\\"pathname\\":\\"/app/visualize\\",\\"basePath\\":\\"\\"}}},\\"params\\":{}}],\\"series\\":[{\\"accessor\\":2,\\"format\\":{\\"id\\":\\"terms\\",\\"params\\":{\\"id\\":\\"string\\",\\"otherBucketLabel\\":\\"Other\\",\\"missingBucketLabel\\":\\"Missing\\",\\"parsedUrl\\":{\\"origin\\":\\"http://localhost:5801\\",\\"pathname\\":\\"/app/visualize\\",\\"basePath\\":\\"\\"}}},\\"params\\":{}}]}}", + ], + }, + "getArgument": [Function], + "name": "vislib_vis", + "removeArgument": [Function], + "replaceArgument": [Function], + "toAst": [Function], + "toString": [Function], + "type": "expression_function_builder", +} +`; diff --git a/src/plugins/vis_type_vislib/public/__snapshots__/to_ast_pie.test.ts.snap b/src/plugins/vis_type_vislib/public/__snapshots__/to_ast_pie.test.ts.snap new file mode 100644 index 0000000000000..b8dc4b31747c4 --- /dev/null +++ b/src/plugins/vis_type_vislib/public/__snapshots__/to_ast_pie.test.ts.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`vislib pie vis toExpressionAst function should match basic snapshot 1`] = ` +Object { + "addArgument": [Function], + "arguments": Object { + "visConfig": Array [ + "{\\"type\\":\\"pie\\",\\"addTooltip\\":true,\\"addLegend\\":true,\\"legendPosition\\":\\"right\\",\\"isDonut\\":true,\\"labels\\":{\\"show\\":true,\\"values\\":true,\\"last_level\\":true,\\"truncate\\":100},\\"dimensions\\":{\\"metric\\":{\\"accessor\\":0,\\"format\\":{\\"id\\":\\"number\\"},\\"params\\":{}},\\"buckets\\":[{\\"accessor\\":1,\\"format\\":{\\"id\\":\\"terms\\",\\"params\\":{\\"id\\":\\"string\\",\\"otherBucketLabel\\":\\"Other\\",\\"missingBucketLabel\\":\\"Missing\\",\\"parsedUrl\\":{\\"origin\\":\\"http://localhost:5801\\",\\"pathname\\":\\"/app/visualize\\",\\"basePath\\":\\"\\"}}},\\"params\\":{}}]}}", + ], + }, + "getArgument": [Function], + "name": "vislib_pie_vis", + "removeArgument": [Function], + "replaceArgument": [Function], + "toAst": [Function], + "toString": [Function], + "type": "expression_function_builder", +} +`; diff --git a/src/plugins/vis_type_vislib/public/area.ts b/src/plugins/vis_type_vislib/public/area.ts index ec90fbd1746a1..531958d6b3db3 100644 --- a/src/plugins/vis_type_vislib/public/area.ts +++ b/src/plugins/vis_type_vislib/public/area.ts @@ -37,22 +37,20 @@ import { getConfigCollections, } from './utils/collections'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { createVislibVisController } from './vis_controller'; -import { VisTypeVislibDependencies } from './plugin'; import { Rotates } from '../../charts/public'; -import { VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { toExpressionAst } from './to_ast'; +import { BasicVislibParams } from './types'; -export const createAreaVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ +export const areaVisTypeDefinition: BaseVisTypeOptions = { name: 'area', title: i18n.translate('visTypeVislib.area.areaTitle', { defaultMessage: 'Area' }), icon: 'visArea', description: i18n.translate('visTypeVislib.area.areaDescription', { defaultMessage: 'Emphasize the quantity beneath a line chart', }), - visualization: createVislibVisController(deps), - getSupportedTriggers: () => { - return [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush]; - }, + getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], + toExpressionAst, visConfig: { defaults: { type: 'area', @@ -131,9 +129,6 @@ export const createAreaVisTypeDefinition = (deps: VisTypeVislibDependencies) => labels: {}, }, }, - events: { - brush: { disabled: false }, - }, editorConfig: { collections: getConfigCollections(), optionTabs: getAreaOptionTabs(), @@ -190,4 +185,4 @@ export const createAreaVisTypeDefinition = (deps: VisTypeVislibDependencies) => }, ]), }, -}); +}; diff --git a/src/plugins/vis_type_vislib/public/components/options/gauge/index.tsx b/src/plugins/vis_type_vislib/public/components/options/gauge/index.tsx index 6109b548f9412..911ee293f580e 100644 --- a/src/plugins/vis_type_vislib/public/components/options/gauge/index.tsx +++ b/src/plugins/vis_type_vislib/public/components/options/gauge/index.tsx @@ -60,4 +60,6 @@ function GaugeOptions(props: VisOptionsProps) { ); } -export { GaugeOptions }; +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { GaugeOptions as default }; diff --git a/src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx b/src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx index 7a89496d9441e..312cf60fda6b0 100644 --- a/src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx +++ b/src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx @@ -185,4 +185,6 @@ function HeatmapOptions(props: VisOptionsProps) { ); } -export { HeatmapOptions }; +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { HeatmapOptions as default }; diff --git a/src/plugins/vis_type_vislib/public/components/options/index.tsx b/src/plugins/vis_type_vislib/public/components/options/index.tsx new file mode 100644 index 0000000000000..18c41bf289b11 --- /dev/null +++ b/src/plugins/vis_type_vislib/public/components/options/index.tsx @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { lazy } from 'react'; + +import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { ValidationVisOptionsProps } from '../common'; +import { GaugeVisParams } from '../../gauge'; +import { PieVisParams } from '../../pie'; +import { BasicVislibParams } from '../../types'; +import { HeatmapVisParams } from '../../heatmap'; + +const GaugeOptionsLazy = lazy(() => import('./gauge')); +const PieOptionsLazy = lazy(() => import('./pie')); +const PointSeriesOptionsLazy = lazy(() => import('./point_series')); +const HeatmapOptionsLazy = lazy(() => import('./heatmap')); +const MetricsAxisOptionsLazy = lazy(() => import('./metrics_axes')); + +export const GaugeOptions = (props: VisOptionsProps) => ( + +); + +export const PieOptions = (props: VisOptionsProps) => ; + +export const PointSeriesOptions = (props: ValidationVisOptionsProps) => ( + +); + +export const HeatmapOptions = (props: VisOptionsProps) => ( + +); + +export const MetricsAxisOptions = (props: ValidationVisOptionsProps) => ( + +); diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx b/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx index 0cc737f19e5c6..63881fea1ad88 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx +++ b/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { mount, shallow } from 'enzyme'; import { IAggConfig, IAggType } from 'src/plugins/data/public'; -import { MetricsAxisOptions } from './index'; +import MetricsAxisOptions from './index'; import { BasicVislibParams, SeriesParam, ValueAxis } from '../../../types'; import { ValidationVisOptionsProps } from '../../common'; import { Positions } from '../../../utils/collections'; diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx b/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx index 18687404b9114..0862c47c35cff 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx +++ b/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx @@ -325,4 +325,6 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps) ) : null; } -export { MetricsAxisOptions }; +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { MetricsAxisOptions as default }; diff --git a/src/plugins/vis_type_vislib/public/components/options/pie.tsx b/src/plugins/vis_type_vislib/public/components/options/pie.tsx index 54ba307982967..30828bfc6a3ea 100644 --- a/src/plugins/vis_type_vislib/public/components/options/pie.tsx +++ b/src/plugins/vis_type_vislib/public/components/options/pie.tsx @@ -99,4 +99,6 @@ function PieOptions(props: VisOptionsProps) { ); } -export { PieOptions }; +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { PieOptions as default }; diff --git a/src/plugins/vis_type_vislib/public/components/options/point_series/index.ts b/src/plugins/vis_type_vislib/public/components/options/point_series/index.ts index fb94ec6743faa..937b92c950430 100644 --- a/src/plugins/vis_type_vislib/public/components/options/point_series/index.ts +++ b/src/plugins/vis_type_vislib/public/components/options/point_series/index.ts @@ -17,4 +17,6 @@ * under the License. */ -export { PointSeriesOptions } from './point_series'; +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { PointSeriesOptions as default } from './point_series'; diff --git a/src/plugins/vis_type_vislib/public/gauge.ts b/src/plugins/vis_type_vislib/public/gauge.ts index 561c45d26fa7f..86e3b8793d618 100644 --- a/src/plugins/vis_type_vislib/public/gauge.ts +++ b/src/plugins/vis_type_vislib/public/gauge.ts @@ -24,8 +24,9 @@ import { AggGroupNames } from '../../data/public'; import { GaugeOptions } from './components/options'; import { getGaugeCollections, Alignments, GaugeTypes } from './utils/collections'; import { ColorModes, ColorSchemas, ColorSchemaParams, Labels, Style } from '../../charts/public'; -import { createVislibVisController } from './vis_controller'; -import { VisTypeVislibDependencies } from './plugin'; +import { toExpressionAst } from './to_ast'; +import { BaseVisTypeOptions } from '../../visualizations/public'; +import { BasicVislibParams } from './types'; export interface Gauge extends ColorSchemaParams { backStyle: 'Full'; @@ -55,7 +56,7 @@ export interface GaugeVisParams { gauge: Gauge; } -export const createGaugeVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ +export const gaugeVisTypeDefinition: BaseVisTypeOptions = { name: 'gauge', title: i18n.translate('visTypeVislib.gauge.gaugeTitle', { defaultMessage: 'Gauge' }), icon: 'visGauge', @@ -63,6 +64,7 @@ export const createGaugeVisTypeDefinition = (deps: VisTypeVislibDependencies) => defaultMessage: "Gauges indicate the status of a metric. Use it to show how a metric's value relates to reference threshold values.", }), + toExpressionAst, visConfig: { defaults: { type: 'gauge', @@ -109,7 +111,6 @@ export const createGaugeVisTypeDefinition = (deps: VisTypeVislibDependencies) => }, }, }, - visualization: createVislibVisController(deps), editorConfig: { collections: getGaugeCollections(), optionsTemplate: GaugeOptions, @@ -145,4 +146,4 @@ export const createGaugeVisTypeDefinition = (deps: VisTypeVislibDependencies) => ]), }, useCustomNoDataScreen: true, -}); +}; diff --git a/src/plugins/vis_type_vislib/public/goal.ts b/src/plugins/vis_type_vislib/public/goal.ts index 5f74698938a0b..32574fb5b0a9c 100644 --- a/src/plugins/vis_type_vislib/public/goal.ts +++ b/src/plugins/vis_type_vislib/public/goal.ts @@ -21,20 +21,21 @@ import { i18n } from '@kbn/i18n'; import { GaugeOptions } from './components/options'; import { getGaugeCollections, GaugeTypes } from './utils/collections'; -import { createVislibVisController } from './vis_controller'; -import { VisTypeVislibDependencies } from './plugin'; import { ColorModes, ColorSchemas } from '../../charts/public'; import { AggGroupNames } from '../../data/public'; import { Schemas } from '../../vis_default_editor/public'; +import { toExpressionAst } from './to_ast'; +import { BaseVisTypeOptions } from '../../visualizations/public'; +import { BasicVislibParams } from './types'; -export const createGoalVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ +export const goalVisTypeDefinition: BaseVisTypeOptions = { name: 'goal', title: i18n.translate('visTypeVislib.goal.goalTitle', { defaultMessage: 'Goal' }), icon: 'visGoal', description: i18n.translate('visTypeVislib.goal.goalDescription', { defaultMessage: 'A goal chart indicates how close you are to your final goal.', }), - visualization: createVislibVisController(deps), + toExpressionAst, visConfig: { defaults: { addTooltip: true, @@ -110,4 +111,4 @@ export const createGoalVisTypeDefinition = (deps: VisTypeVislibDependencies) => ]), }, useCustomNoDataScreen: true, -}); +}; diff --git a/src/plugins/vis_type_vislib/public/heatmap.ts b/src/plugins/vis_type_vislib/public/heatmap.ts index bd3d02029cb23..f970eddd645f5 100644 --- a/src/plugins/vis_type_vislib/public/heatmap.ts +++ b/src/plugins/vis_type_vislib/public/heatmap.ts @@ -23,12 +23,11 @@ import { RangeValues, Schemas } from '../../vis_default_editor/public'; import { AggGroupNames } from '../../data/public'; import { AxisTypes, getHeatmapCollections, Positions, ScaleTypes } from './utils/collections'; import { HeatmapOptions } from './components/options'; -import { createVislibVisController } from './vis_controller'; import { TimeMarker } from './vislib/visualizations/time_marker'; -import { CommonVislibParams, ValueAxis } from './types'; -import { VisTypeVislibDependencies } from './plugin'; +import { BasicVislibParams, CommonVislibParams, ValueAxis } from './types'; import { ColorSchemas, ColorSchemaParams } from '../../charts/public'; -import { VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { toExpressionAst } from './to_ast'; export interface HeatmapVisParams extends CommonVislibParams, ColorSchemaParams { type: 'heatmap'; @@ -42,17 +41,15 @@ export interface HeatmapVisParams extends CommonVislibParams, ColorSchemaParams times: TimeMarker[]; } -export const createHeatmapVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ +export const heatmapVisTypeDefinition: BaseVisTypeOptions = { name: 'heatmap', title: i18n.translate('visTypeVislib.heatmap.heatmapTitle', { defaultMessage: 'Heat Map' }), icon: 'heatmap', description: i18n.translate('visTypeVislib.heatmap.heatmapDescription', { defaultMessage: 'Shade cells within a matrix', }), - getSupportedTriggers: () => { - return [VIS_EVENT_TO_TRIGGER.filter]; - }, - visualization: createVislibVisController(deps), + getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter], + toExpressionAst, visConfig: { defaults: { type: 'heatmap', @@ -86,9 +83,6 @@ export const createHeatmapVisTypeDefinition = (deps: VisTypeVislibDependencies) ], }, }, - events: { - brush: { disabled: false }, - }, editorConfig: { collections: getHeatmapCollections(), optionsTemplate: HeatmapOptions, @@ -142,4 +136,4 @@ export const createHeatmapVisTypeDefinition = (deps: VisTypeVislibDependencies) }, ]), }, -}); +}; diff --git a/src/plugins/vis_type_vislib/public/histogram.ts b/src/plugins/vis_type_vislib/public/histogram.ts index 8aeeb4ec533ab..d5fb92f5c6a0c 100644 --- a/src/plugins/vis_type_vislib/public/histogram.ts +++ b/src/plugins/vis_type_vislib/public/histogram.ts @@ -36,12 +36,12 @@ import { getConfigCollections, } from './utils/collections'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { createVislibVisController } from './vis_controller'; -import { VisTypeVislibDependencies } from './plugin'; import { Rotates } from '../../charts/public'; -import { VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { BasicVislibParams } from './types'; +import { toExpressionAst } from './to_ast'; -export const createHistogramVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ +export const histogramVisTypeDefinition: BaseVisTypeOptions = { name: 'histogram', title: i18n.translate('visTypeVislib.histogram.histogramTitle', { defaultMessage: 'Vertical Bar', @@ -50,10 +50,8 @@ export const createHistogramVisTypeDefinition = (deps: VisTypeVislibDependencies description: i18n.translate('visTypeVislib.histogram.histogramDescription', { defaultMessage: 'Assign a continuous variable to each axis', }), - visualization: createVislibVisController(deps), - getSupportedTriggers: () => { - return [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush]; - }, + getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], + toExpressionAst, visConfig: { defaults: { type: 'histogram', @@ -133,9 +131,6 @@ export const createHistogramVisTypeDefinition = (deps: VisTypeVislibDependencies }, }, }, - events: { - brush: { disabled: false }, - }, editorConfig: { collections: getConfigCollections(), optionTabs: getAreaOptionTabs(), @@ -192,4 +187,4 @@ export const createHistogramVisTypeDefinition = (deps: VisTypeVislibDependencies }, ]), }, -}); +}; diff --git a/src/plugins/vis_type_vislib/public/horizontal_bar.ts b/src/plugins/vis_type_vislib/public/horizontal_bar.ts index 702581828e60d..f1a5365e5ae74 100644 --- a/src/plugins/vis_type_vislib/public/horizontal_bar.ts +++ b/src/plugins/vis_type_vislib/public/horizontal_bar.ts @@ -34,12 +34,12 @@ import { getConfigCollections, } from './utils/collections'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { createVislibVisController } from './vis_controller'; -import { VisTypeVislibDependencies } from './plugin'; import { Rotates } from '../../charts/public'; -import { VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { BasicVislibParams } from './types'; +import { toExpressionAst } from './to_ast'; -export const createHorizontalBarVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ +export const horizontalBarVisTypeDefinition: BaseVisTypeOptions = { name: 'horizontal_bar', title: i18n.translate('visTypeVislib.horizontalBar.horizontalBarTitle', { defaultMessage: 'Horizontal Bar', @@ -48,10 +48,8 @@ export const createHorizontalBarVisTypeDefinition = (deps: VisTypeVislibDependen description: i18n.translate('visTypeVislib.horizontalBar.horizontalBarDescription', { defaultMessage: 'Assign a continuous variable to each axis', }), - visualization: createVislibVisController(deps), - getSupportedTriggers: () => { - return [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush]; - }, + getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], + toExpressionAst, visConfig: { defaults: { type: 'histogram', @@ -130,9 +128,6 @@ export const createHorizontalBarVisTypeDefinition = (deps: VisTypeVislibDependen }, }, }, - events: { - brush: { disabled: false }, - }, editorConfig: { collections: getConfigCollections(), optionTabs: getAreaOptionTabs(), @@ -189,4 +184,4 @@ export const createHorizontalBarVisTypeDefinition = (deps: VisTypeVislibDependen }, ]), }, -}); +}; diff --git a/src/plugins/vis_type_vislib/public/index.scss b/src/plugins/vis_type_vislib/public/index.scss index 64445648ba84a..3c347aebde225 100644 --- a/src/plugins/vis_type_vislib/public/index.scss +++ b/src/plugins/vis_type_vislib/public/index.scss @@ -1 +1 @@ -@import './vislib/index' +@import './vislib/index'; diff --git a/src/plugins/vis_type_vislib/public/line.ts b/src/plugins/vis_type_vislib/public/line.ts index 6e9190229114b..a65b0bcf7e2bb 100644 --- a/src/plugins/vis_type_vislib/public/line.ts +++ b/src/plugins/vis_type_vislib/public/line.ts @@ -35,22 +35,20 @@ import { getConfigCollections, } from './utils/collections'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { createVislibVisController } from './vis_controller'; -import { VisTypeVislibDependencies } from './plugin'; import { Rotates } from '../../charts/public'; -import { VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { toExpressionAst } from './to_ast'; +import { BasicVislibParams } from './types'; -export const createLineVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ +export const lineVisTypeDefinition: BaseVisTypeOptions = { name: 'line', title: i18n.translate('visTypeVislib.line.lineTitle', { defaultMessage: 'Line' }), icon: 'visLine', description: i18n.translate('visTypeVislib.line.lineDescription', { defaultMessage: 'Emphasize trends', }), - visualization: createVislibVisController(deps), - getSupportedTriggers: () => { - return [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush]; - }, + getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], + toExpressionAst, visConfig: { defaults: { type: 'line', @@ -129,9 +127,6 @@ export const createLineVisTypeDefinition = (deps: VisTypeVislibDependencies) => }, }, }, - events: { - brush: { disabled: false }, - }, editorConfig: { collections: getConfigCollections(), optionTabs: getAreaOptionTabs(), @@ -182,4 +177,4 @@ export const createLineVisTypeDefinition = (deps: VisTypeVislibDependencies) => }, ]), }, -}); +}; diff --git a/src/plugins/vis_type_vislib/public/pie.ts b/src/plugins/vis_type_vislib/public/pie.ts index 1e81dbdde3f68..58f7dd0df89e8 100644 --- a/src/plugins/vis_type_vislib/public/pie.ts +++ b/src/plugins/vis_type_vislib/public/pie.ts @@ -23,14 +23,12 @@ import { AggGroupNames } from '../../data/public'; import { Schemas } from '../../vis_default_editor/public'; import { PieOptions } from './components/options'; import { getPositions, Positions } from './utils/collections'; -import { createVislibVisController } from './vis_controller'; import { CommonVislibParams } from './types'; -import { VisTypeVislibDependencies } from './plugin'; -import { VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { toExpressionAst } from './to_ast_pie'; export interface PieVisParams extends CommonVislibParams { type: 'pie'; - addLegend: boolean; isDonut: boolean; labels: { show: boolean; @@ -40,17 +38,15 @@ export interface PieVisParams extends CommonVislibParams { }; } -export const createPieVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ +export const pieVisTypeDefinition: BaseVisTypeOptions = { name: 'pie', title: i18n.translate('visTypeVislib.pie.pieTitle', { defaultMessage: 'Pie' }), icon: 'visPie', description: i18n.translate('visTypeVislib.pie.pieDescription', { defaultMessage: 'Compare parts of a whole', }), - visualization: createVislibVisController(deps), - getSupportedTriggers: () => { - return [VIS_EVENT_TO_TRIGGER.filter]; - }, + getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter], + toExpressionAst, visConfig: { defaults: { type: 'pie', @@ -108,4 +104,4 @@ export const createPieVisTypeDefinition = (deps: VisTypeVislibDependencies) => ( }, hierarchicalData: true, responseHandler: 'vislib_slices', -}); +}; diff --git a/src/plugins/vis_type_vislib/public/pie_fn.ts b/src/plugins/vis_type_vislib/public/pie_fn.ts index bee200cbe30ee..c9da9e9bd9fab 100644 --- a/src/plugins/vis_type_vislib/public/pie_fn.ts +++ b/src/plugins/vis_type_vislib/public/pie_fn.ts @@ -18,27 +18,35 @@ */ import { i18n } from '@kbn/i18n'; + import { ExpressionFunctionDefinition, Datatable, Render } from '../../expressions/public'; + // @ts-ignore import { vislibSlicesResponseHandler } from './vislib/response_handler'; +import { PieVisParams } from './pie'; +import { vislibVisName } from './vis_type_vislib_vis_fn'; + +export const vislibPieName = 'vislib_pie_vis'; interface Arguments { visConfig: string; } -type VisParams = Required; - interface RenderValue { - visConfig: VisParams; + visData: unknown; + visType: string; + visConfig: PieVisParams; } -export const createPieVisFn = (): ExpressionFunctionDefinition< - 'kibana_pie', +export type VisTypeVislibPieExpressionFunctionDefinition = ExpressionFunctionDefinition< + typeof vislibPieName, Datatable, Arguments, Render -> => ({ - name: 'kibana_pie', +>; + +export const createPieVisFn = (): VisTypeVislibPieExpressionFunctionDefinition => ({ + name: vislibPieName, type: 'render', inputTypes: ['datatable'], help: i18n.translate('visTypeVislib.functions.pie.help', { @@ -48,23 +56,20 @@ export const createPieVisFn = (): ExpressionFunctionDefinition< visConfig: { types: ['string'], default: '"{}"', - help: '', + help: 'vislib pie vis config', }, }, fn(input, args) { - const visConfig = JSON.parse(args.visConfig); - const convertedData = vislibSlicesResponseHandler(input, visConfig.dimensions); + const visConfig = JSON.parse(args.visConfig) as PieVisParams; + const visData = vislibSlicesResponseHandler(input, visConfig.dimensions); return { type: 'render', - as: 'visualization', + as: vislibVisName, value: { - visData: convertedData, - visType: 'pie', + visData, visConfig, - params: { - listenOnChange: true, - }, + visType: 'pie', }, }; }, diff --git a/src/plugins/vis_type_vislib/public/plugin.ts b/src/plugins/vis_type_vislib/public/plugin.ts index c6a6b6f82592b..f183042fd5201 100644 --- a/src/plugins/vis_type_vislib/public/plugin.ts +++ b/src/plugins/vis_type_vislib/public/plugin.ts @@ -17,40 +17,20 @@ * under the License. */ -import './index.scss'; - -import { - CoreSetup, - CoreStart, - Plugin, - IUiSettingsClient, - PluginInitializerContext, -} from 'kibana/public'; +import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'kibana/public'; import { VisTypeXyPluginSetup } from 'src/plugins/vis_type_xy/public'; import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; +import { BaseVisTypeOptions, VisualizationsSetup } from '../../visualizations/public'; import { createVisTypeVislibVisFn } from './vis_type_vislib_vis_fn'; import { createPieVisFn } from './pie_fn'; -import { - createHistogramVisTypeDefinition, - createLineVisTypeDefinition, - createPieVisTypeDefinition, - createAreaVisTypeDefinition, - createHeatmapVisTypeDefinition, - createHorizontalBarVisTypeDefinition, - createGaugeVisTypeDefinition, - createGoalVisTypeDefinition, -} from './vis_type_vislib_vis_types'; +import { visLibVisTypeDefinitions, pieVisTypeDefinition } from './vis_type_vislib_vis_types'; import { ChartsPluginSetup } from '../../charts/public'; import { DataPublicPluginStart } from '../../data/public'; -import { setFormatService, setDataActions, setKibanaLegacy } from './services'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; - -export interface VisTypeVislibDependencies { - uiSettings: IUiSettingsClient; - charts: ChartsPluginSetup; -} +import { setFormatService, setDataActions } from './services'; +import { getVislibVisRenderer } from './vis_renderer'; +import { BasicVislibParams } from './types'; /** @internal */ export interface VisTypeVislibPluginSetupDependencies { @@ -66,54 +46,37 @@ export interface VisTypeVislibPluginStartDependencies { kibanaLegacy: KibanaLegacyStart; } -type VisTypeVislibCoreSetup = CoreSetup; +export type VisTypeVislibCoreSetup = CoreSetup; /** @internal */ -export class VisTypeVislibPlugin implements Plugin { +export class VisTypeVislibPlugin + implements + Plugin { constructor(public initializerContext: PluginInitializerContext) {} public async setup( core: VisTypeVislibCoreSetup, { expressions, visualizations, charts, visTypeXy }: VisTypeVislibPluginSetupDependencies ) { - const visualizationDependencies: Readonly = { - uiSettings: core.uiSettings, - charts, - }; - const vislibTypes = [ - createHistogramVisTypeDefinition, - createLineVisTypeDefinition, - createPieVisTypeDefinition, - createAreaVisTypeDefinition, - createHeatmapVisTypeDefinition, - createHorizontalBarVisTypeDefinition, - createGaugeVisTypeDefinition, - createGoalVisTypeDefinition, - ]; - const vislibFns = [createVisTypeVislibVisFn(), createPieVisFn()]; - // if visTypeXy plugin is disabled it's config will be undefined if (!visTypeXy) { - const convertedTypes: any[] = []; + const convertedTypes: Array> = []; const convertedFns: any[] = []; // Register legacy vislib types that have been converted convertedFns.forEach(expressions.registerFunction); - convertedTypes.forEach((vis) => - visualizations.createBaseVisualization(vis(visualizationDependencies)) - ); + convertedTypes.forEach(visualizations.createBaseVisualization); + expressions.registerRenderer(getVislibVisRenderer(core, charts)); } - // Register non-converted types - vislibFns.forEach(expressions.registerFunction); - vislibTypes.forEach((vis) => - visualizations.createBaseVisualization(vis(visualizationDependencies)) - ); + visLibVisTypeDefinitions.forEach(visualizations.createBaseVisualization); + visualizations.createBaseVisualization(pieVisTypeDefinition); + expressions.registerRenderer(getVislibVisRenderer(core, charts)); + [createVisTypeVislibVisFn(), createPieVisFn()].forEach(expressions.registerFunction); } - public start(core: CoreStart, { data, kibanaLegacy }: VisTypeVislibPluginStartDependencies) { + public start(core: CoreStart, { data }: VisTypeVislibPluginStartDependencies) { setFormatService(data.fieldFormats); setDataActions(data.actions); - setKibanaLegacy(kibanaLegacy); } } diff --git a/src/plugins/vis_type_vislib/public/sample_vis.test.mocks.ts b/src/plugins/vis_type_vislib/public/sample_vis.test.mocks.ts new file mode 100644 index 0000000000000..324e8e00f37fc --- /dev/null +++ b/src/plugins/vis_type_vislib/public/sample_vis.test.mocks.ts @@ -0,0 +1,3307 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const samplePieVis = { + type: { + name: 'pie', + title: 'Pie', + description: 'Compare parts of a whole', + icon: 'visPie', + stage: 'production', + options: { + showTimePicker: true, + showQueryBar: true, + showFilterBar: true, + showIndexSelection: true, + hierarchicalData: false, + }, + visConfig: { + defaults: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + }, + }, + editorConfig: { + collections: { + legendPositions: [ + { + text: 'Top', + value: 'top', + }, + { + text: 'Left', + value: 'left', + }, + { + text: 'Right', + value: 'right', + }, + { + text: 'Bottom', + value: 'bottom', + }, + ], + }, + schemas: { + all: [ + { + group: 'metrics', + name: 'metric', + title: 'Slice size', + min: 1, + max: 1, + aggFilter: ['sum', 'count', 'cardinality', 'top_hits'], + defaults: [ + { + schema: 'metric', + type: 'count', + }, + ], + editor: false, + params: [], + }, + { + group: 'buckets', + name: 'segment', + title: 'Split slices', + min: 0, + max: null, + aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], + editor: false, + params: [], + }, + { + group: 'buckets', + name: 'split', + title: 'Split chart', + mustBeFirst: true, + min: 0, + max: 1, + aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], + params: [ + { + name: 'row', + default: true, + }, + ], + editor: false, + }, + ], + buckets: [null, null], + metrics: [null], + }, + }, + hidden: false, + requestHandler: 'courier', + responseHandler: 'vislib_slices', + hierarchicalData: true, + useCustomNoDataScreen: false, + }, + title: '[Flights] Airline Carrier', + description: '', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: true, + values: true, + last_level: true, + truncate: 100, + }, + }, + sessionState: {}, + data: { + searchSource: { + id: 'data_source1', + requestStartHandlers: [], + inheritOptions: {}, + history: [], + fields: { + filter: [], + query: { + query: '', + language: 'kuery', + }, + index: { + id: 'd3d7af60-4c81-11e8-b3d7-01146121b73d', + title: 'kibana_sample_data_flights', + fieldFormatMap: { + AvgTicketPrice: { + id: 'number', + params: { + parsedUrl: { + origin: 'http://localhost:5801', + pathname: '/app/visualize', + basePath: '', + }, + pattern: '$0,0.[00]', + }, + }, + hour_of_day: { + id: 'number', + params: { + pattern: '00', + }, + }, + }, + fields: [ + { + count: 0, + name: 'AvgTicketPrice', + type: 'number', + esTypes: ['float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'Cancelled', + type: 'boolean', + esTypes: ['boolean'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'Carrier', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'Dest', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'DestAirportID', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'DestCityName', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'DestCountry', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'DestLocation', + type: 'geo_point', + esTypes: ['geo_point'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'DestRegion', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'DestWeather', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'DistanceKilometers', + type: 'number', + esTypes: ['float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'DistanceMiles', + type: 'number', + esTypes: ['float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'FlightDelay', + type: 'boolean', + esTypes: ['boolean'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'FlightDelayMin', + type: 'number', + esTypes: ['integer'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'FlightDelayType', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'FlightNum', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'FlightTimeHour', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'FlightTimeMin', + type: 'number', + esTypes: ['float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'Origin', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'OriginAirportID', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'OriginCityName', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'OriginCountry', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'OriginLocation', + type: 'geo_point', + esTypes: ['geo_point'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'OriginRegion', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'OriginWeather', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: '_id', + type: 'string', + esTypes: ['_id'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + count: 0, + name: '_index', + type: 'string', + esTypes: ['_index'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + count: 0, + name: '_score', + type: 'number', + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: '_source', + type: '_source', + esTypes: ['_source'], + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: '_type', + type: 'string', + esTypes: ['_type'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + count: 0, + name: 'dayOfWeek', + type: 'number', + esTypes: ['integer'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'timestamp', + type: 'date', + esTypes: ['date'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + script: "doc['timestamp'].value.hourOfDay", + lang: 'painless', + name: 'hour_of_day', + type: 'number', + scripted: true, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + ], + timeFieldName: 'timestamp', + metaFields: ['_source', '_id', '_type', '_index', '_score'], + version: 'WzM1LDFd', + originalSavedObjectBody: { + title: 'kibana_sample_data_flights', + timeFieldName: 'timestamp', + fields: + '[{"count":0,"name":"AvgTicketPrice","type":"number","esTypes":["float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"Cancelled","type":"boolean","esTypes":["boolean"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"Carrier","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"Dest","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"DestAirportID","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"DestCityName","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"DestCountry","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"DestLocation","type":"geo_point","esTypes":["geo_point"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"DestRegion","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"DestWeather","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"DistanceKilometers","type":"number","esTypes":["float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"DistanceMiles","type":"number","esTypes":["float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"FlightDelay","type":"boolean","esTypes":["boolean"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"FlightDelayMin","type":"number","esTypes":["integer"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"FlightDelayType","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"FlightNum","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"FlightTimeHour","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"FlightTimeMin","type":"number","esTypes":["float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"Origin","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"OriginAirportID","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"OriginCityName","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"OriginCountry","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"OriginLocation","type":"geo_point","esTypes":["geo_point"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"OriginRegion","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"OriginWeather","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"_id","type":"string","esTypes":["_id"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":false},{"count":0,"name":"_index","type":"string","esTypes":["_index"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":false},{"count":0,"name":"_score","type":"number","scripted":false,"searchable":false,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"_source","type":"_source","esTypes":["_source"],"scripted":false,"searchable":false,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"_type","type":"string","esTypes":["_type"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":false},{"count":0,"name":"dayOfWeek","type":"number","esTypes":["integer"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"timestamp","type":"date","esTypes":["date"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"script":"doc[\'timestamp\'].value.hourOfDay","lang":"painless","name":"hour_of_day","type":"number","scripted":true,"searchable":true,"aggregatable":true,"readFromDocValues":false}]', + fieldFormatMap: + '{"AvgTicketPrice":{"id":"number","params":{"parsedUrl":{"origin":"http://localhost:5801","pathname":"/app/visualize","basePath":""},"pattern":"$0,0.[00]"}},"hour_of_day":{"id":"number","params":{"parsedUrl":{"origin":"http://localhost:5801","pathname":"/app/visualize","basePath":""},"pattern":"00"}}}', + }, + shortDotsEnable: false, + fieldFormats: { + fieldFormats: {}, + defaultMap: { + ip: { + id: 'ip', + params: {}, + }, + date: { + id: 'date', + params: {}, + }, + date_nanos: { + id: 'date_nanos', + params: {}, + es: true, + }, + number: { + id: 'number', + params: {}, + }, + boolean: { + id: 'boolean', + params: {}, + }, + _source: { + id: '_source', + params: {}, + }, + _default_: { + id: 'string', + params: {}, + }, + }, + metaParamsOptions: {}, + }, + }, + }, + dependencies: { + legacy: { + loadingCount$: { + _isScalar: false, + observers: [ + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + destination: { + closed: true, + }, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 1, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [ + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 13, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + null, + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [null], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 1, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + null, + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [null], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 1, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + null, + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [null], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 3, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + null, + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [null], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + null, + ], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + null, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + }, + }, + aggs: { + typesRegistry: {}, + getResponseAggs: () => [ + { + id: '1', + enabled: true, + type: 'count', + params: {}, + schema: 'metric', + toSerializedFieldFormat: () => ({ + id: 'number', + }), + }, + { + id: '2', + enabled: true, + type: 'terms', + params: { + field: 'Carrier', + orderBy: '1', + order: 'desc', + size: 5, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + schema: 'segment', + toSerializedFieldFormat: () => ({ + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + parsedUrl: { + origin: 'http://localhost:5801', + pathname: '/app/visualize', + basePath: '', + }, + }, + }), + }, + ], + }, + }, + isHierarchical: () => true, + uiState: { + vis: { + legendOpen: false, + }, + }, +}; + +export const sampleAreaVis = { + type: { + name: 'area', + title: 'Area', + description: 'Emphasize the quantity beneath a line chart', + icon: 'visArea', + stage: 'production', + options: { + showTimePicker: true, + showQueryBar: true, + showFilterBar: true, + showIndexSelection: true, + hierarchicalData: false, + }, + visConfig: { + defaults: { + type: 'area', + grid: { + categoryLines: false, + }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { + type: 'linear', + }, + labels: { + show: true, + filter: true, + truncate: 100, + }, + 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: 'area', + mode: 'stacked', + data: { + label: 'Count', + id: '1', + }, + drawLinesBetweenPoints: true, + lineWidth: 2, + showCircles: true, + interpolate: 'linear', + valueAxis: 'ValueAxis-1', + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + thresholdLine: { + show: false, + value: 10, + width: 1, + style: 'full', + color: '#E7664C', + }, + labels: {}, + }, + }, + editorConfig: { + collections: { + legendPositions: [ + { + text: 'Top', + value: 'top', + }, + { + text: 'Left', + value: 'left', + }, + { + text: 'Right', + value: 'right', + }, + { + text: 'Bottom', + value: 'bottom', + }, + ], + positions: [ + { + text: 'Top', + value: 'top', + }, + { + text: 'Left', + value: 'left', + }, + { + text: 'Right', + value: 'right', + }, + { + text: 'Bottom', + value: 'bottom', + }, + ], + chartTypes: [ + { + text: 'Line', + value: 'line', + }, + { + text: 'Area', + value: 'area', + }, + { + text: 'Bar', + value: 'histogram', + }, + ], + axisModes: [ + { + text: 'Normal', + value: 'normal', + }, + { + text: 'Percentage', + value: 'percentage', + }, + { + text: 'Wiggle', + value: 'wiggle', + }, + { + text: 'Silhouette', + value: 'silhouette', + }, + ], + scaleTypes: [ + { + text: 'Linear', + value: 'linear', + }, + { + text: 'Log', + value: 'log', + }, + { + text: 'Square root', + value: 'square root', + }, + ], + chartModes: [ + { + text: 'Normal', + value: 'normal', + }, + { + text: 'Stacked', + value: 'stacked', + }, + ], + interpolationModes: [ + { + text: 'Straight', + value: 'linear', + }, + { + text: 'Smoothed', + value: 'cardinal', + }, + { + text: 'Stepped', + value: 'step-after', + }, + ], + thresholdLineStyles: [ + { + value: 'full', + text: 'Full', + }, + { + value: 'dashed', + text: 'Dashed', + }, + { + value: 'dot-dashed', + text: 'Dot-dashed', + }, + ], + }, + optionTabs: [ + { + name: 'advanced', + title: 'Metrics & axes', + }, + { + name: 'options', + title: 'Panel settings', + }, + ], + schemas: { + all: [ + { + group: 'metrics', + name: 'metric', + title: 'Y-axis', + aggFilter: ['!geo_centroid', '!geo_bounds'], + min: 1, + defaults: [ + { + schema: 'metric', + type: 'count', + }, + ], + max: null, + editor: false, + params: [], + }, + { + group: 'metrics', + name: 'radius', + title: 'Dot size', + min: 0, + max: 1, + aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality'], + editor: false, + params: [], + }, + { + group: 'buckets', + name: 'segment', + title: 'X-axis', + min: 0, + max: 1, + aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], + editor: false, + params: [], + }, + { + group: 'buckets', + name: 'group', + title: 'Split series', + min: 0, + max: 3, + aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], + editor: false, + params: [], + }, + { + group: 'buckets', + name: 'split', + title: 'Split chart', + min: 0, + max: 1, + aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], + params: [ + { + name: 'row', + default: true, + }, + ], + editor: false, + }, + ], + buckets: [null, null, null], + metrics: [null, null], + }, + }, + hidden: false, + requestHandler: 'courier', + responseHandler: 'none', + hierarchicalData: false, + useCustomNoDataScreen: false, + }, + title: '[eCommerce] Sales by Category', + description: '', + 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, + }, + 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, + thresholdLine: { + show: false, + value: 10, + width: 1, + style: 'full', + color: '#E7664C', + }, + labels: {}, + dimensions: { + x: { + accessor: 0, + format: { + id: 'date', + params: { + pattern: 'YYYY-MM-DD HH:mm', + }, + }, + params: { + date: true, + interval: 43200000, + format: 'YYYY-MM-DD HH:mm', + bounds: { + min: '2020-09-30T12:41:13.795Z', + max: '2020-10-15T17:00:00.000Z', + }, + }, + label: 'order_date per 12 hours', + aggType: 'date_histogram', + }, + y: [ + { + accessor: 2, + format: { + id: 'number', + params: { + parsedUrl: { + origin: 'http://localhost:5801', + pathname: '/app/visualize', + basePath: '', + }, + }, + }, + params: {}, + label: 'Sum of total_quantity', + aggType: 'sum', + }, + ], + series: [ + { + accessor: 1, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + label: 'category.keyword: Descending', + aggType: 'terms', + }, + ], + }, + }, + sessionState: {}, + data: { + searchSource: { + id: 'data_source1', + requestStartHandlers: [], + inheritOptions: {}, + history: [], + fields: { + query: { + query: '', + language: 'kuery', + }, + filter: [], + index: { + id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + title: 'kibana_sample_data_ecommerce', + fieldFormatMap: { + taxful_total_price: { + id: 'number', + params: { + pattern: '$0,0.[00]', + }, + }, + }, + fields: [ + { + count: 0, + name: '_id', + type: 'string', + esTypes: ['_id'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + count: 0, + name: '_index', + type: 'string', + esTypes: ['_index'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + count: 0, + name: '_score', + type: 'number', + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: '_source', + type: '_source', + esTypes: ['_source'], + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: '_type', + type: 'string', + esTypes: ['_type'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + count: 0, + name: 'category', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'category.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'category', + }, + }, + }, + { + count: 0, + name: 'currency', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'customer_birth_date', + type: 'date', + esTypes: ['date'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'customer_first_name', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'customer_first_name.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'customer_first_name', + }, + }, + }, + { + count: 0, + name: 'customer_full_name', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'customer_full_name.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'customer_full_name', + }, + }, + }, + { + count: 0, + name: 'customer_gender', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'customer_id', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'customer_last_name', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'customer_last_name.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'customer_last_name', + }, + }, + }, + { + count: 0, + name: 'customer_phone', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'day_of_week', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'day_of_week_i', + type: 'number', + esTypes: ['integer'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'email', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'event.dataset', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'geoip.city_name', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'geoip.continent_name', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'geoip.country_iso_code', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'geoip.location', + type: 'geo_point', + esTypes: ['geo_point'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'geoip.region_name', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'manufacturer', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'manufacturer.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'manufacturer', + }, + }, + }, + { + count: 0, + name: 'order_date', + type: 'date', + esTypes: ['date'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'order_id', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products._id', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'products._id.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'products._id', + }, + }, + }, + { + count: 0, + name: 'products.base_price', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.base_unit_price', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.category', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'products.category.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'products.category', + }, + }, + }, + { + count: 0, + name: 'products.created_on', + type: 'date', + esTypes: ['date'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.discount_amount', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.discount_percentage', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.manufacturer', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'products.manufacturer.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'products.manufacturer', + }, + }, + }, + { + count: 0, + name: 'products.min_price', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.price', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.product_id', + type: 'number', + esTypes: ['long'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.product_name', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'products.product_name.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'products.product_name', + }, + }, + }, + { + count: 0, + name: 'products.quantity', + type: 'number', + esTypes: ['integer'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.sku', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.tax_amount', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.taxful_price', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.taxless_price', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'products.unit_discount_amount', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'sku', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'taxful_total_price', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'taxless_total_price', + type: 'number', + esTypes: ['half_float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'total_quantity', + type: 'number', + esTypes: ['integer'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'total_unique_products', + type: 'number', + esTypes: ['integer'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'type', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'user', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + ], + timeFieldName: 'order_date', + metaFields: ['_source', '_id', '_type', '_index', '_score'], + version: 'WzEzLDFd', + originalSavedObjectBody: { + title: 'kibana_sample_data_ecommerce', + timeFieldName: 'order_date', + fields: + '[{"count":0,"name":"_id","type":"string","esTypes":["_id"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":false},{"count":0,"name":"_index","type":"string","esTypes":["_index"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":false},{"count":0,"name":"_score","type":"number","scripted":false,"searchable":false,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"_source","type":"_source","esTypes":["_source"],"scripted":false,"searchable":false,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"_type","type":"string","esTypes":["_type"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":false},{"count":0,"name":"category","type":"string","esTypes":["text"],"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"category.keyword","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"category"}}},{"count":0,"name":"currency","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"customer_birth_date","type":"date","esTypes":["date"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"customer_first_name","type":"string","esTypes":["text"],"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"customer_first_name.keyword","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"customer_first_name"}}},{"count":0,"name":"customer_full_name","type":"string","esTypes":["text"],"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"customer_full_name.keyword","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"customer_full_name"}}},{"count":0,"name":"customer_gender","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"customer_id","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"customer_last_name","type":"string","esTypes":["text"],"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"customer_last_name.keyword","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"customer_last_name"}}},{"count":0,"name":"customer_phone","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"day_of_week","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"day_of_week_i","type":"number","esTypes":["integer"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"email","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"event.dataset","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"geoip.city_name","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"geoip.continent_name","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"geoip.country_iso_code","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"geoip.location","type":"geo_point","esTypes":["geo_point"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"geoip.region_name","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"manufacturer","type":"string","esTypes":["text"],"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"manufacturer.keyword","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"manufacturer"}}},{"count":0,"name":"order_date","type":"date","esTypes":["date"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"order_id","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products._id","type":"string","esTypes":["text"],"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"products._id.keyword","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"products._id"}}},{"count":0,"name":"products.base_price","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.base_unit_price","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.category","type":"string","esTypes":["text"],"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"products.category.keyword","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"products.category"}}},{"count":0,"name":"products.created_on","type":"date","esTypes":["date"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.discount_amount","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.discount_percentage","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.manufacturer","type":"string","esTypes":["text"],"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"products.manufacturer.keyword","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"products.manufacturer"}}},{"count":0,"name":"products.min_price","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.price","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.product_id","type":"number","esTypes":["long"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.product_name","type":"string","esTypes":["text"],"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"count":0,"name":"products.product_name.keyword","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"products.product_name"}}},{"count":0,"name":"products.quantity","type":"number","esTypes":["integer"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.sku","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.tax_amount","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.taxful_price","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.taxless_price","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"products.unit_discount_amount","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"sku","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"taxful_total_price","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"taxless_total_price","type":"number","esTypes":["half_float"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"total_quantity","type":"number","esTypes":["integer"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"total_unique_products","type":"number","esTypes":["integer"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"type","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"count":0,"name":"user","type":"string","esTypes":["keyword"],"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true}]', + fieldFormatMap: + '{"taxful_total_price":{"id":"number","params":{"parsedUrl":{"origin":"http://localhost:5801","pathname":"/app/visualize","basePath":""},"pattern":"$0,0.[00]"}}}', + }, + shortDotsEnable: false, + fieldFormats: { + fieldFormats: {}, + defaultMap: { + ip: { + id: 'ip', + params: {}, + }, + date: { + id: 'date', + params: {}, + }, + date_nanos: { + id: 'date_nanos', + params: {}, + es: true, + }, + number: { + id: 'number', + params: {}, + }, + boolean: { + id: 'boolean', + params: {}, + }, + _source: { + id: '_source', + params: {}, + }, + _default_: { + id: 'string', + params: {}, + }, + }, + metaParamsOptions: {}, + }, + }, + }, + dependencies: { + legacy: { + loadingCount$: { + _isScalar: false, + observers: [ + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + destination: { + closed: true, + }, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 1, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [ + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 13, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + null, + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [null], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 1, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + null, + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [null], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 1, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + null, + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [null], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: { + closed: false, + _parentOrParents: null, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + destination: { + closed: false, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + _context: {}, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + count: 3, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: false, + hasPrev: true, + prev: 0, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: true, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [], + active: 1, + index: 2, + }, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + parent: { + closed: true, + _parentOrParents: null, + _subscriptions: null, + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: true, + concurrent: 1, + hasCompleted: true, + buffer: [ + { + _isScalar: false, + }, + ], + active: 1, + index: 1, + }, + }, + _subscriptions: [ + null, + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + subject: { + _isScalar: false, + observers: [null], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + null, + ], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + }, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + null, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + seenValue: false, + }, + _subscriptions: [null], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + }, + _subscriptions: [ + { + closed: false, + _subscriptions: null, + }, + ], + syncErrorValue: null, + syncErrorThrown: false, + syncErrorThrowable: false, + isStopped: false, + hasKey: true, + key: 0, + }, + ], + closed: false, + isStopped: false, + hasError: false, + thrownError: null, + _value: 0, + }, + }, + }, + }, + aggs: { + typesRegistry: {}, + getResponseAggs: () => [ + { + id: '1', + enabled: true, + type: 'sum', + params: { + field: 'total_quantity', + }, + schema: 'metric', + toSerializedFieldFormat: () => ({ + id: 'number', + params: { + parsedUrl: { + origin: 'http://localhost:5801', + pathname: '/app/visualize', + basePath: '', + }, + }, + }), + }, + { + id: '2', + enabled: true, + type: 'date_histogram', + params: { + field: 'order_date', + timeRange: { + from: '2020-09-30T12:41:13.795Z', + to: '2020-10-15T17:00:00.000Z', + }, + useNormalizedEsInterval: true, + scaleMetricValues: false, + interval: 'auto', + drop_partials: false, + min_doc_count: 1, + extended_bounds: {}, + }, + schema: 'segment', + toSerializedFieldFormat: () => ({ + id: 'date', + params: { pattern: 'HH:mm:ss.SSS' }, + }), + }, + { + id: '3', + enabled: true, + type: 'terms', + params: { + field: 'category.keyword', + orderBy: '1', + order: 'desc', + size: 5, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + schema: 'group', + toSerializedFieldFormat: () => ({ + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + parsedUrl: { + origin: 'http://localhost:5801', + pathname: '/app/visualize', + basePath: '', + }, + }, + }), + }, + ], + }, + }, + isHierarchical: () => false, + uiState: {}, +}; diff --git a/src/plugins/vis_type_vislib/public/services.ts b/src/plugins/vis_type_vislib/public/services.ts index 7257b98f2e9f5..633fae9c7f2a6 100644 --- a/src/plugins/vis_type_vislib/public/services.ts +++ b/src/plugins/vis_type_vislib/public/services.ts @@ -19,7 +19,6 @@ import { createGetterSetter } from '../../kibana_utils/public'; import { DataPublicPluginStart } from '../../data/public'; -import { KibanaLegacyStart } from '../../kibana_legacy/public'; export const [getDataActions, setDataActions] = createGetterSetter< DataPublicPluginStart['actions'] @@ -28,7 +27,3 @@ export const [getDataActions, setDataActions] = createGetterSetter< export const [getFormatService, setFormatService] = createGetterSetter< DataPublicPluginStart['fieldFormats'] >('vislib data.fieldFormats'); - -export const [getKibanaLegacy, setKibanaLegacy] = createGetterSetter( - 'vislib kibanalegacy' -); diff --git a/src/plugins/vis_type_vislib/public/to_ast.test.ts b/src/plugins/vis_type_vislib/public/to_ast.test.ts new file mode 100644 index 0000000000000..48d3dfe254d0b --- /dev/null +++ b/src/plugins/vis_type_vislib/public/to_ast.test.ts @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Vis } from '../../visualizations/public'; +import { buildExpression } from '../../expressions/public'; + +import { BasicVislibParams } from './types'; +import { toExpressionAst } from './to_ast'; +import { sampleAreaVis } from './sample_vis.test.mocks'; + +jest.mock('../../expressions/public', () => ({ + ...(jest.requireActual('../../expressions/public') as any), + buildExpression: jest.fn().mockImplementation(() => ({ + toAst: () => ({ + type: 'expression', + chain: [], + }), + })), +})); + +jest.mock('./to_ast_esaggs', () => ({ + getEsaggsFn: jest.fn(), +})); + +describe('vislib vis toExpressionAst function', () => { + let vis: Vis; + + const params = { + timefilter: {}, + timeRange: {}, + abortSignal: {}, + } as any; + + beforeEach(() => { + vis = sampleAreaVis as any; + }); + + it('should match basic snapshot', () => { + toExpressionAst(vis, params); + const [, builtExpression] = (buildExpression as jest.Mock).mock.calls[0][0]; + + expect(builtExpression).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/vis_type_vislib/public/to_ast.ts b/src/plugins/vis_type_vislib/public/to_ast.ts new file mode 100644 index 0000000000000..7cd55ccd32ebc --- /dev/null +++ b/src/plugins/vis_type_vislib/public/to_ast.ts @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import moment from 'moment'; + +import { VisToExpressionAst, getVisSchemas } from '../../visualizations/public'; +import { buildExpression, buildExpressionFunction } from '../../expressions/public'; + +import { vislibVisName, VisTypeVislibExpressionFunctionDefinition } from './vis_type_vislib_vis_fn'; +import { BasicVislibParams } from './types'; +import { + DateHistogramParams, + Dimensions, + HistogramParams, +} from './vislib/helpers/point_series/point_series'; +import { getEsaggsFn } from './to_ast_esaggs'; + +export const toExpressionAst: VisToExpressionAst = async (vis, params) => { + const schemas = getVisSchemas(vis, params); + const dimensions: Dimensions = { + x: schemas.segment ? schemas.segment[0] : null, + y: schemas.metric, + z: schemas.radius, + width: schemas.width, + series: schemas.group, + splitRow: schemas.split_row, + splitColumn: schemas.split_column, + }; + + const responseAggs = vis.data.aggs?.getResponseAggs() ?? []; + + if (dimensions.x) { + const xAgg = responseAggs[dimensions.x.accessor] as any; + if (xAgg.type.name === 'date_histogram') { + (dimensions.x.params as DateHistogramParams).date = true; + const { esUnit, esValue } = xAgg.buckets.getInterval(); + (dimensions.x.params as DateHistogramParams).intervalESUnit = esUnit; + (dimensions.x.params as DateHistogramParams).intervalESValue = esValue; + (dimensions.x.params as DateHistogramParams).interval = moment + .duration(esValue, esUnit) + .asMilliseconds(); + (dimensions.x.params as DateHistogramParams).format = xAgg.buckets.getScaledDateFormat(); + (dimensions.x.params as DateHistogramParams).bounds = xAgg.buckets.getBounds(); + } else if (xAgg.type.name === 'histogram') { + const intervalParam = xAgg.type.paramByName('interval'); + const output = { params: {} as any }; + await intervalParam.modifyAggConfigOnSearchRequestStart(xAgg, vis.data.searchSource, { + abortSignal: params.abortSignal, + }); + intervalParam.write(xAgg, output); + (dimensions.x.params as HistogramParams).interval = output.params.interval; + } + } + + const visConfig = { ...vis.params }; + + (dimensions.y || []).forEach((yDimension) => { + const yAgg = responseAggs.filter(({ enabled }) => enabled)[yDimension.accessor]; + const seriesParam = (visConfig.seriesParams || []).find((param) => param.data.id === yAgg.id); + if (seriesParam) { + const usedValueAxis = (visConfig.valueAxes || []).find( + (valueAxis) => valueAxis.id === seriesParam.valueAxis + ); + if (usedValueAxis?.scale.mode === 'percentage') { + yDimension.format = { id: 'percent' }; + } + } + if (visConfig?.gauge?.percentageMode === true) { + yDimension.format = { id: 'percent' }; + } + }); + + visConfig.dimensions = dimensions; + + const configStr = JSON.stringify(visConfig).replace(/\\/g, `\\\\`).replace(/'/g, `\\'`); + const visTypeXy = buildExpressionFunction( + vislibVisName, + { + type: vis.type.name, + visConfig: configStr, + } + ); + + const ast = buildExpression([getEsaggsFn(vis), visTypeXy]); + + return ast.toAst(); +}; diff --git a/src/plugins/vis_type_vislib/public/components/options/index.ts b/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts similarity index 51% rename from src/plugins/vis_type_vislib/public/components/options/index.ts rename to src/plugins/vis_type_vislib/public/to_ast_esaggs.ts index 57afbd4818ae4..a7312c9d36cbb 100644 --- a/src/plugins/vis_type_vislib/public/components/options/index.ts +++ b/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts @@ -17,8 +17,24 @@ * under the License. */ -export { GaugeOptions } from './gauge'; -export { PieOptions } from './pie'; -export { PointSeriesOptions } from './point_series'; -export { HeatmapOptions } from './heatmap'; -export { MetricsAxisOptions } from './metrics_axes'; +import { Vis } from '../../visualizations/public'; +import { buildExpressionFunction } from '../../expressions/public'; +import { EsaggsExpressionFunctionDefinition } from '../../data/public'; + +import { PieVisParams } from './pie'; +import { BasicVislibParams } from './types'; + +/** + * Get esaggs expressions function + * TODO: replace this with vis.data.aggs!.toExpressionAst(); + * @param vis + */ +export function getEsaggsFn(vis: Vis | Vis) { + return buildExpressionFunction('esaggs', { + index: vis.data.indexPattern!.id!, + metricsAtAllLevels: vis.isHierarchical(), + partialRows: false, + aggConfigs: JSON.stringify(vis.data.aggs!.aggs), + includeFormatHints: false, + }); +} diff --git a/src/plugins/vis_type_vislib/public/to_ast_pie.test.ts b/src/plugins/vis_type_vislib/public/to_ast_pie.test.ts new file mode 100644 index 0000000000000..36a9a17341bc5 --- /dev/null +++ b/src/plugins/vis_type_vislib/public/to_ast_pie.test.ts @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Vis } from '../../visualizations/public'; +import { buildExpression } from '../../expressions/public'; + +import { PieVisParams } from './pie'; +import { samplePieVis } from './sample_vis.test.mocks'; +import { toExpressionAst } from './to_ast_pie'; + +jest.mock('../../expressions/public', () => ({ + ...(jest.requireActual('../../expressions/public') as any), + buildExpression: jest.fn().mockImplementation(() => ({ + toAst: () => ({ + type: 'expression', + chain: [], + }), + })), +})); + +jest.mock('./to_ast_esaggs', () => ({ + getEsaggsFn: jest.fn(), +})); + +describe('vislib pie vis toExpressionAst function', () => { + let vis: Vis; + + const params = { + timefilter: {}, + timeRange: {}, + abortSignal: {}, + } as any; + + beforeEach(() => { + vis = samplePieVis as any; + }); + + it('should match basic snapshot', () => { + toExpressionAst(vis, params); + const [, builtExpression] = (buildExpression as jest.Mock).mock.calls[0][0]; + + expect(builtExpression).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/vis_type_vislib/public/to_ast_pie.ts b/src/plugins/vis_type_vislib/public/to_ast_pie.ts new file mode 100644 index 0000000000000..95a5f89208ef9 --- /dev/null +++ b/src/plugins/vis_type_vislib/public/to_ast_pie.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getVisSchemas, VisToExpressionAst } from '../../visualizations/public'; +import { buildExpression, buildExpressionFunction } from '../../expressions/public'; + +import { PieVisParams } from './pie'; +import { vislibPieName, VisTypeVislibPieExpressionFunctionDefinition } from './pie_fn'; +import { getEsaggsFn } from './to_ast_esaggs'; + +export const toExpressionAst: VisToExpressionAst = async (vis, params) => { + const schemas = getVisSchemas(vis, params); + const visConfig = { + ...vis.params, + dimensions: { + metric: schemas.metric[0], + buckets: schemas.segment, + splitRow: schemas.split_row, + splitColumn: schemas.split_column, + }, + }; + + const configStr = JSON.stringify(visConfig).replace(/\\/g, `\\\\`).replace(/'/g, `\\'`); + const visTypePie = buildExpressionFunction( + vislibPieName, + { + visConfig: configStr, + } + ); + + const ast = buildExpression([getEsaggsFn(vis), visTypePie]); + + return ast.toAst(); +}; diff --git a/src/plugins/vis_type_vislib/public/types.ts b/src/plugins/vis_type_vislib/public/types.ts index a29f0bcb5c52a..c0311edf76154 100644 --- a/src/plugins/vis_type_vislib/public/types.ts +++ b/src/plugins/vis_type_vislib/public/types.ts @@ -29,10 +29,13 @@ import { ThresholdLineStyles, } from './utils/collections'; import { Labels, Style } from '../../charts/public'; +import { Dimensions } from './vislib/helpers/point_series/point_series'; export interface CommonVislibParams { addTooltip: boolean; + addLegend: boolean; legendPosition: Positions; + dimensions: Dimensions; } export interface Scale { @@ -87,6 +90,9 @@ export interface BasicVislibParams extends CommonVislibParams { labels: Labels; thresholdLine: ThresholdLine; valueAxes: ValueAxis[]; + gauge?: { + percentageMode: boolean; + }; grid: { categoryLines: boolean; valueAxis?: string; diff --git a/src/plugins/vis_type_vislib/public/vis_controller.tsx b/src/plugins/vis_type_vislib/public/vis_controller.tsx index 3a05030f804ca..1804d0d52ae7a 100644 --- a/src/plugins/vis_type_vislib/public/vis_controller.tsx +++ b/src/plugins/vis_type_vislib/public/vis_controller.tsx @@ -20,127 +20,147 @@ import $ from 'jquery'; import React, { RefObject } from 'react'; -import { Positions } from './utils/collections'; -import { VisTypeVislibDependencies } from './plugin'; import { mountReactNode } from '../../../core/public/utils'; +import { ChartsPluginSetup } from '../../charts/public'; +import { PersistedState } from '../../visualizations/public'; +import { IInterpreterRenderHandlers } from '../../expressions/public'; + +import { VisTypeVislibCoreSetup } from './plugin'; import { VisLegend, CUSTOM_LEGEND_VIS_TYPES } from './vislib/components/legend'; -import { VisParams, ExprVis } from '../../visualizations/public'; -import { getKibanaLegacy } from './services'; +import { BasicVislibParams } from './types'; +import { PieVisParams } from './pie'; const legendClassName = { - top: 'visLib--legend-top', - bottom: 'visLib--legend-bottom', - left: 'visLib--legend-left', - right: 'visLib--legend-right', + top: 'vislib--legend-top', + bottom: 'vislib--legend-bottom', + left: 'vislib--legend-left', + right: 'vislib--legend-right', }; -export const createVislibVisController = (deps: VisTypeVislibDependencies) => { +export type VislibVisController = InstanceType>; + +export const createVislibVisController = ( + core: VisTypeVislibCoreSetup, + charts: ChartsPluginSetup +) => { return class VislibVisController { - unmount: (() => void) | null = null; - visParams?: VisParams; + private removeListeners?: () => void; + private unmountLegend?: () => void; + legendRef: RefObject; container: HTMLDivElement; chartEl: HTMLDivElement; legendEl: HTMLDivElement; - vislibVis: any; + vislibVis?: any; - constructor(public el: Element, public vis: ExprVis) { + constructor(public el: HTMLDivElement) { this.el = el; - this.vis = vis; - this.unmount = null; this.legendRef = React.createRef(); // vis mount point this.container = document.createElement('div'); - this.container.className = 'visLib'; + this.container.className = 'vislib'; this.el.appendChild(this.container); // chart mount point this.chartEl = document.createElement('div'); - this.chartEl.className = 'visLib__chart'; + this.chartEl.className = 'vislib__chart'; this.container.appendChild(this.chartEl); // legend mount point this.legendEl = document.createElement('div'); - this.legendEl.className = 'visLib__legend'; + this.legendEl.className = 'vislib__legend'; this.container.appendChild(this.legendEl); } - render(esResponse: any, visParams: VisParams): Promise { + async render( + esResponse: any, + visParams: BasicVislibParams | PieVisParams, + handlers: IInterpreterRenderHandlers + ): Promise { if (this.vislibVis) { - this.destroy(); + this.destroy(false); + } + + // Used in functional tests to know when chart is loaded by type + this.chartEl.dataset.vislibChartType = visParams.type; + + if (this.el.clientWidth === 0 || this.el.clientHeight === 0) { + handlers.done(); + return; + } + + const [, { kibanaLegacy }] = await core.getStartServices(); + kibanaLegacy.loadFontAwesome(); + + // @ts-expect-error + const { Vis: Vislib } = await import('./vislib/vis'); + const { uiState, event: fireEvent } = handlers; + + this.vislibVis = new Vislib(this.chartEl, visParams, core, charts); + this.vislibVis.on('brush', fireEvent); + this.vislibVis.on('click', fireEvent); + this.vislibVis.on('renderComplete', handlers.done); + this.removeListeners = () => { + this.vislibVis.off('brush', fireEvent); + this.vislibVis.off('click', fireEvent); + }; + + this.vislibVis.initVisConfig(esResponse, uiState); + + if (visParams.addLegend) { + $(this.container) + .attr('class', (i, cls) => { + return cls.replace(/vislib--legend-\S+/g, ''); + }) + .addClass((legendClassName as any)[visParams.legendPosition]); + + this.mountLegend(esResponse, visParams, fireEvent, uiState); } - getKibanaLegacy().loadFontAwesome(); - - return new Promise(async (resolve) => { - if (this.el.clientWidth === 0 || this.el.clientHeight === 0) { - return resolve(); - } - - // @ts-expect-error - const { Vis: Vislib } = await import('./vislib/vis'); - - this.vislibVis = new Vislib(this.chartEl, visParams, deps); - this.vislibVis.on('brush', this.vis.API.events.brush); - this.vislibVis.on('click', this.vis.API.events.filter); - this.vislibVis.on('renderComplete', resolve); - - this.vislibVis.initVisConfig(esResponse, this.vis.getUiState()); - - if (visParams.addLegend) { - $(this.container) - .attr('class', (i, cls) => { - return cls.replace(/visLib--legend-\S+/g, ''); - }) - .addClass((legendClassName as any)[visParams.legendPosition]); - - this.mountLegend(esResponse, visParams.legendPosition); - } - - this.vislibVis.render(esResponse, this.vis.getUiState()); - - // refreshing the legend after the chart is rendered. - // this is necessary because some visualizations - // provide data necessary for the legend only after a render cycle. - if ( - visParams.addLegend && - CUSTOM_LEGEND_VIS_TYPES.includes(this.vislibVis.visConfigArgs.type) - ) { - this.unmountLegend(); - this.mountLegend(esResponse, visParams.legendPosition); - this.vislibVis.render(esResponse, this.vis.getUiState()); - } - }); + this.vislibVis.render(esResponse, uiState); + + // refreshing the legend after the chart is rendered. + // this is necessary because some visualizations + // provide data necessary for the legend only after a render cycle. + if ( + visParams.addLegend && + CUSTOM_LEGEND_VIS_TYPES.includes(this.vislibVis.visConfigArgs.type) + ) { + this.unmountLegend?.(); + this.mountLegend(esResponse, visParams, fireEvent, uiState); + this.vislibVis.render(esResponse, uiState); + } } - mountLegend(visData: any, position: Positions) { - this.unmount = mountReactNode( + mountLegend( + visData: unknown, + { legendPosition, addLegend }: BasicVislibParams | PieVisParams, + fireEvent: IInterpreterRenderHandlers['event'], + uiState?: PersistedState + ) { + this.unmountLegend = mountReactNode( )(this.legendEl); } - unmountLegend() { - if (this.unmount) { - this.unmount(); - } - } + destroy(clearElement = true) { + this.unmountLegend?.(); - destroy() { - if (this.unmount) { - this.unmount(); + if (clearElement) { + this.el.innerHTML = ''; } if (this.vislibVis) { - this.vislibVis.off('brush', this.vis.API.events.brush); - this.vislibVis.off('click', this.vis.API.events.filter); + this.removeListeners?.(); this.vislibVis.destroy(); delete this.vislibVis; } diff --git a/src/plugins/vis_type_vislib/public/vis_renderer.tsx b/src/plugins/vis_type_vislib/public/vis_renderer.tsx new file mode 100644 index 0000000000000..9c697f481e63e --- /dev/null +++ b/src/plugins/vis_type_vislib/public/vis_renderer.tsx @@ -0,0 +1,61 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { lazy } from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import { ExpressionRenderDefinition } from '../../expressions/public'; +import { VisualizationContainer } from '../../visualizations/public'; +import { ChartsPluginSetup } from '../../charts/public'; + +import { VisTypeVislibCoreSetup } from './plugin'; +import { VislibRenderValue, vislibVisName } from './vis_type_vislib_vis_fn'; + +function shouldShowNoResultsMessage(visData: any, visType: string): boolean { + if (['goal', 'gauge'].includes(visType)) { + return false; + } + + const rows: object[] | undefined = visData?.rows; + const isZeroHits = visData?.hits === 0 || (rows && !rows.length); + + return Boolean(isZeroHits); +} + +const VislibWrapper = lazy(() => import('./vis_wrapper')); + +export const getVislibVisRenderer: ( + core: VisTypeVislibCoreSetup, + charts: ChartsPluginSetup +) => ExpressionRenderDefinition = (core, charts) => ({ + name: vislibVisName, + reuseDomNode: true, + render: async (domNode, config, handlers) => { + const showNoResult = shouldShowNoResultsMessage(config.visData, config.visType); + + handlers.onDestroy(() => unmountComponentAtNode(domNode)); + + render( + + + , + domNode + ); + }, +}); diff --git a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts index 557f9930f55b1..c5fa8f36f43e3 100644 --- a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts +++ b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts @@ -18,29 +18,35 @@ */ import { i18n } from '@kbn/i18n'; + import { ExpressionFunctionDefinition, Datatable, Render } from '../../expressions/public'; + // @ts-ignore import { vislibSeriesResponseHandler } from './vislib/response_handler'; +import { BasicVislibParams } from './types'; + +export const vislibVisName = 'vislib_vis'; interface Arguments { type: string; visConfig: string; } -type VisParams = Required; - -interface RenderValue { +export interface VislibRenderValue { + visData: any; visType: string; - visConfig: VisParams; + visConfig: BasicVislibParams; } -export const createVisTypeVislibVisFn = (): ExpressionFunctionDefinition< - 'vislib', +export type VisTypeVislibExpressionFunctionDefinition = ExpressionFunctionDefinition< + typeof vislibVisName, Datatable, Arguments, - Render -> => ({ - name: 'vislib', + Render +>; + +export const createVisTypeVislibVisFn = (): VisTypeVislibExpressionFunctionDefinition => ({ + name: vislibVisName, type: 'render', inputTypes: ['datatable'], help: i18n.translate('visTypeVislib.functions.vislib.help', { @@ -55,23 +61,21 @@ export const createVisTypeVislibVisFn = (): ExpressionFunctionDefinition< visConfig: { types: ['string'], default: '"{}"', - help: '', + help: 'vislib vis config', }, }, fn(context, args) { - const visConfigParams = JSON.parse(args.visConfig); - const convertedData = vislibSeriesResponseHandler(context, visConfigParams.dimensions); + const visType = args.type; + const visConfig = JSON.parse(args.visConfig) as BasicVislibParams; + const visData = vislibSeriesResponseHandler(context, visConfig.dimensions); return { type: 'render', - as: 'visualization', + as: vislibVisName, value: { - visData: convertedData, - visType: args.type, - visConfig: visConfigParams, - params: { - listenOnChange: true, - }, + visData, + visConfig, + visType, }, }; }, diff --git a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts index f44d503895483..1b43a213c618d 100644 --- a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts +++ b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts @@ -17,11 +17,22 @@ * under the License. */ -export { createHistogramVisTypeDefinition } from './histogram'; -export { createLineVisTypeDefinition } from './line'; -export { createPieVisTypeDefinition } from './pie'; -export { createAreaVisTypeDefinition } from './area'; -export { createHeatmapVisTypeDefinition } from './heatmap'; -export { createHorizontalBarVisTypeDefinition } from './horizontal_bar'; -export { createGaugeVisTypeDefinition } from './gauge'; -export { createGoalVisTypeDefinition } from './goal'; +import { histogramVisTypeDefinition } from './histogram'; +import { lineVisTypeDefinition } from './line'; +import { areaVisTypeDefinition } from './area'; +import { heatmapVisTypeDefinition } from './heatmap'; +import { horizontalBarVisTypeDefinition } from './horizontal_bar'; +import { gaugeVisTypeDefinition } from './gauge'; +import { goalVisTypeDefinition } from './goal'; + +export { pieVisTypeDefinition } from './pie'; + +export const visLibVisTypeDefinitions = [ + histogramVisTypeDefinition, + lineVisTypeDefinition, + areaVisTypeDefinition, + heatmapVisTypeDefinition, + horizontalBarVisTypeDefinition, + gaugeVisTypeDefinition, + goalVisTypeDefinition, +]; diff --git a/src/plugins/vis_type_vislib/public/vis_wrapper.tsx b/src/plugins/vis_type_vislib/public/vis_wrapper.tsx new file mode 100644 index 0000000000000..980ba1c175885 --- /dev/null +++ b/src/plugins/vis_type_vislib/public/vis_wrapper.tsx @@ -0,0 +1,89 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect, useMemo, useRef } from 'react'; +import { EuiResizeObserver } from '@elastic/eui'; +import { debounce } from 'lodash'; + +import { IInterpreterRenderHandlers } from '../../expressions/public'; +import { ChartsPluginSetup } from '../../charts/public'; + +import { VislibRenderValue } from './vis_type_vislib_vis_fn'; +import { createVislibVisController, VislibVisController } from './vis_controller'; +import { VisTypeVislibCoreSetup } from './plugin'; + +import './index.scss'; + +type VislibWrapperProps = VislibRenderValue & { + core: VisTypeVislibCoreSetup; + charts: ChartsPluginSetup; + handlers: IInterpreterRenderHandlers; +}; + +const VislibWrapper = ({ core, charts, visData, visConfig, handlers }: VislibWrapperProps) => { + const chartDiv = useRef(null); + const visController = useRef(null); + + const updateChart = useMemo( + () => + debounce(() => { + if (visController.current) { + visController.current.render(visData, visConfig, handlers); + } + }, 100), + [visConfig, visData, handlers] + ); + + useEffect(() => { + if (chartDiv.current) { + const Controller = createVislibVisController(core, charts); + visController.current = new Controller(chartDiv.current); + } + return () => { + visController.current?.destroy(); + visController.current = null; + }; + }, [core, charts, handlers]); + + useEffect(updateChart, [updateChart]); + + useEffect(() => { + if (handlers.uiState) { + handlers.uiState.on('change', updateChart); + + return () => { + handlers.uiState?.off('change', updateChart); + }; + } + }, [handlers.uiState, updateChart]); + + return ( + + {(resizeRef) => ( +
+
+
+ )} + + ); +}; + +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { VislibWrapper as default }; diff --git a/src/plugins/vis_type_vislib/public/vislib/_vislib_vis_type.scss b/src/plugins/vis_type_vislib/public/vislib/_vislib_vis_type.scss index c03aa19140de0..843bb9d3f03eb 100644 --- a/src/plugins/vis_type_vislib/public/vislib/_vislib_vis_type.scss +++ b/src/plugins/vis_type_vislib/public/vislib/_vislib_vis_type.scss @@ -1,27 +1,29 @@ -.visLib { +.vislib { flex: 1 1 0; display: flex; flex-direction: row; overflow: auto; - &.visLib--legend-left { + &.vislib--legend-left { flex-direction: row-reverse; } - &.visLib--legend-right { + &.vislib--legend-right { flex-direction: row; } - &.visLib--legend-top { + &.vislib--legend-top { flex-direction: column-reverse; } - &.visLib--legend-bottom { + &.vislib--legend-bottom { flex-direction: column; } } -.visLib__chart { +.vislib__chart, +.vislib__wrapper, +.vislib__container { display: flex; flex: 1 1 auto; min-height: 0; diff --git a/src/plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss b/src/plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss index b1a59f88a348a..a06f0cb00787b 100644 --- a/src/plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss +++ b/src/plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss @@ -13,6 +13,7 @@ $visLegendLineHeight: $euiSize; left: 0; display: flex; padding: $euiSizeXS; + margin: $euiSizeS; background-color: $euiColorEmptyShade; transition: opacity $euiAnimSpeedFast $euiAnimSlightResistance, background-color $euiAnimSpeedFast $euiAnimSlightResistance $euiAnimSpeedExtraSlow; @@ -33,13 +34,13 @@ $visLegendLineHeight: $euiSize; height: 100%; } -.visLib--legend-left { +.vislib--legend-left { .visLegend__list { margin-bottom: $euiSizeL; } } -.visLib--legend-bottom { +.vislib--legend-bottom { .visLegend__list { margin-left: $euiSizeL; } @@ -64,8 +65,8 @@ $visLegendLineHeight: $euiSize; } } - .visLib--legend-top &, - .visLib--legend-bottom & { + .vislib--legend-top &, + .vislib--legend-bottom & { width: auto; flex-direction: row; flex-wrap: wrap; diff --git a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx index 65d148cfc5ef4..a3fb536d0aec5 100644 --- a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx +++ b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx @@ -41,16 +41,8 @@ jest.mock('../../../services', () => ({ }), })); -const vis = { - params: { - addLegend: true, - }, - API: { - events: { - filter: jest.fn(), - }, - }, -}; +const fireEvent = jest.fn(); + const vislibVis = { handler: { highlight: jest.fn(), @@ -96,14 +88,15 @@ const uiState = { set: jest.fn().mockImplementation((key, value) => mockState.set(key, value)), emit: jest.fn(), setSilent: jest.fn(), -}; +} as any; const getWrapper = async (props?: Partial) => { const wrapper = mount( { }); it('should work with no handlers set', () => { - const newVis = { - ...vis, + const newProps = { vislibVis: { ...vislibVis, handler: null, @@ -197,7 +189,7 @@ describe('VisLegend Component', () => { }; expect(async () => { - wrapper = await getWrapper({ vis: newVis }); + wrapper = await getWrapper(newProps); const first = getLegendItems(wrapper).first(); first.simulate('focus'); first.simulate('blur'); @@ -216,8 +208,11 @@ describe('VisLegend Component', () => { const filterGroup = wrapper.find(EuiButtonGroup).first(); filterGroup.getElement().props.onChange('filterIn'); - expect(vis.API.events.filter).toHaveBeenCalledWith({ data: ['valuesA'], negate: false }); - expect(vis.API.events.filter).toHaveBeenCalledTimes(1); + expect(fireEvent).toHaveBeenCalledWith({ + name: 'filterBucket', + data: { data: ['valuesA'], negate: false }, + }); + expect(fireEvent).toHaveBeenCalledTimes(1); }); it('should filter in when clicked', () => { @@ -226,8 +221,11 @@ describe('VisLegend Component', () => { const filterGroup = wrapper.find(EuiButtonGroup).first(); filterGroup.getElement().props.onChange('filterOut'); - expect(vis.API.events.filter).toHaveBeenCalledWith({ data: ['valuesA'], negate: true }); - expect(vis.API.events.filter).toHaveBeenCalledTimes(1); + expect(fireEvent).toHaveBeenCalledWith({ + name: 'filterBucket', + data: { data: ['valuesA'], negate: true }, + }); + expect(fireEvent).toHaveBeenCalledTimes(1); }); }); diff --git a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx index 5a2db2d21c6fe..cec97f0cadf11 100644 --- a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx +++ b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx @@ -23,16 +23,21 @@ import { compact, uniqBy, map, every, isUndefined } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiPopoverProps, EuiIcon, keys, htmlIdGenerator } from '@elastic/eui'; +import { PersistedState } from '../../../../../visualizations/public'; +import { IInterpreterRenderHandlers } from '../../../../../expressions/public'; + import { getDataActions } from '../../../services'; import { CUSTOM_LEGEND_VIS_TYPES, LegendItem } from './models'; import { VisLegendItem } from './legend_item'; import { getPieNames } from './pie_utils'; +import { BasicVislibParams } from '../../../types'; export interface VisLegendProps { - vis: any; vislibVis: any; - visData: any; - uiState: any; + visData: unknown; + uiState?: PersistedState; + fireEvent: IInterpreterRenderHandlers['event']; + addLegend: BasicVislibParams['addLegend']; position: 'top' | 'bottom' | 'left' | 'right'; } @@ -49,7 +54,10 @@ export class VisLegend extends PureComponent { constructor(props: VisLegendProps) { super(props); - const open = props.uiState.get('vis.legendOpen', true); + + // TODO: Check when this bwc can safely be removed + const bwcLegendStateDefault = props.addLegend ?? true; + const open = props.uiState?.get('vis.legendOpen', bwcLegendStateDefault) as boolean; this.state = { open, @@ -64,13 +72,9 @@ export class VisLegend extends PureComponent { } toggleLegend = () => { - const bwcAddLegend = this.props.vis.params.addLegend; - const bwcLegendStateDefault = bwcAddLegend == null ? true : bwcAddLegend; - const newOpen = !this.props.uiState.get('vis.legendOpen', bwcLegendStateDefault); - this.setState({ open: newOpen }); - // open should be applied on template before we update uiState - setTimeout(() => { - this.props.uiState.set('vis.legendOpen', newOpen); + const newOpen = !this.state.open; + this.setState({ open: newOpen }, () => { + this.props.uiState?.set('vis.legendOpen', newOpen); }); }; @@ -79,17 +83,23 @@ export class VisLegend extends PureComponent { return; } - const colors = this.props.uiState.get('vis.colors') || {}; + const colors = this.props.uiState?.get('vis.colors') || {}; if (colors[label] === color) delete colors[label]; else colors[label] = color; - this.props.uiState.setSilent('vis.colors', null); - this.props.uiState.set('vis.colors', colors); - this.props.uiState.emit('colorChanged'); + this.props.uiState?.setSilent('vis.colors', null); + this.props.uiState?.set('vis.colors', colors); + this.props.uiState?.emit('colorChanged'); this.refresh(); }; filter = ({ values: data }: LegendItem, negate: boolean) => { - this.props.vis.API.events.filter({ data, negate }); + this.props.fireEvent({ + name: 'filterBucket', + data: { + data, + negate, + }, + }); }; canFilter = async (item: LegendItem): Promise => { @@ -172,11 +182,8 @@ export class VisLegend extends PureComponent { return; } // make sure vislib is defined at this point - if ( - this.props.uiState.get('vis.legendOpen') == null && - this.props.vis.params.addLegend != null - ) { - this.setState({ open: this.props.vis.params.addLegend }); + if (this.props.uiState?.get('vis.legendOpen') == null && this.props.addLegend != null) { + this.setState({ open: this.props.addLegend }); } if (vislibVis.visConfig) { diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.ts index 32536960c59cd..147bae7e3b985 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.ts @@ -33,11 +33,11 @@ export function initXAxis(chart: Chart, table: Table) { chart.xAxisLabel = title; if ('interval' in params) { - const { interval } = params; if ('date' in params) { const { intervalESUnit, intervalESValue } = params; + chart.ordered = { - interval: moment.duration(interval), + interval: moment.duration(intervalESValue, intervalESUnit as any), intervalESUnit, intervalESValue, }; diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts index 4ba3101d34898..f40d01e6a8123 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts @@ -28,7 +28,7 @@ import { Column, Table } from '../../types'; export interface DateHistogramParams { date: boolean; - interval: string; + interval: number | string; intervalESValue: number; intervalESUnit: string; format: string; @@ -57,6 +57,9 @@ export interface Dimensions { y: Dimension[]; z?: Dimension[]; series?: Dimension | Dimension[]; + width?: Dimension[]; + splitRow?: Dimension[]; + splitColumn?: Dimension[]; } export interface Aspect { accessor: Column['id']; diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/_handler.scss b/src/plugins/vis_type_vislib/public/vislib/lib/_handler.scss deleted file mode 100644 index d1c7fc7c6278c..0000000000000 --- a/src/plugins/vis_type_vislib/public/vislib/lib/_handler.scss +++ /dev/null @@ -1,17 +0,0 @@ -.visError { - flex: 1 1 0; - display: flex; - align-items: center; - justify-content: center; - text-align: center; - - // From ML - .top { align-self: flex-start; } - .bottom { align-self: flex-end; } -} - -// Prevent large request errors from overflowing the container -.visError--request { - max-width: 100%; - max-height: 100%; -} diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/_index.scss b/src/plugins/vis_type_vislib/public/vislib/lib/_index.scss index b19c2dfb153b9..6751e9f28a8ee 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/_index.scss +++ b/src/plugins/vis_type_vislib/public/vislib/lib/_index.scss @@ -1,4 +1,3 @@ @import './alerts'; -@import './handler'; @import './layout/index'; diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/dispatch.js b/src/plugins/vis_type_vislib/public/vislib/lib/dispatch.js index 4c50472b9d11a..16283c6bddf26 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/dispatch.js +++ b/src/plugins/vis_type_vislib/public/vislib/lib/dispatch.js @@ -182,7 +182,6 @@ export class Dispatch { const data = d.input || d; return { - e: d3.event, data: isSlices ? this._pieClickResponse(data) : this._seriesClickResponse(data), }; } @@ -423,7 +422,6 @@ export class Dispatch { */ createBrush(xScale, svg) { const self = this; - const visConfig = self.handler.visConfig; const { width, height } = svg.node().getBBox(); const isHorizontal = self.handler.categoryAxes[0].axisConfig.isHorizontal(); @@ -449,8 +447,6 @@ export class Dispatch { return self.emit('brush', { range, - config: visConfig, - e: d3.event, data, }); }); diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/handler.js b/src/plugins/vis_type_vislib/public/vislib/lib/handler.js index 3c1aeaa0d1d0d..938ea3adcb9b5 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/handler.js +++ b/src/plugins/vis_type_vislib/public/vislib/lib/handler.js @@ -46,10 +46,10 @@ const markdownIt = new MarkdownIt({ * create the visualization */ export class Handler { - constructor(vis, visConfig, deps) { + constructor(vis, visConfig, uiSettings) { this.el = visConfig.get('el'); this.ChartClass = chartTypes[visConfig.get('type')]; - this.deps = deps; + this.uiSettings = uiSettings; this.charts = []; this.vis = vis; @@ -91,12 +91,18 @@ export class Handler { const xRaw = _.get(eventPayload.data, 'series[0].values[0].xRaw'); if (!xRaw) return; // not sure if this is possible? return self.vis.emit(eventType, { - table: xRaw.table, - range: eventPayload.range, - column: xRaw.column, + name: 'brush', + data: { + table: xRaw.table, + range: eventPayload.range, + column: xRaw.column, + }, }); case 'click': - return self.vis.emit(eventType, eventPayload); + return self.vis.emit(eventType, { + name: 'filterBucket', + data: eventPayload, + }); } }; }); @@ -164,7 +170,7 @@ export class Handler { let loadedCount = 0; const chartSelection = selection.selectAll('.chart'); chartSelection.each(function (chartData) { - const chart = new self.ChartClass(self, this, chartData, self.deps); + const chart = new self.ChartClass(self, this, chartData, self.uiSettings); self.vis.eventNames().forEach(function (event) { self.enable(event, chart); @@ -222,7 +228,7 @@ export class Handler { // class name needs `chart` in it for the polling checkSize function // to continuously call render on resize .attr('class', 'visError chart error') - .attr('data-test-subj', 'visLibVisualizeError'); + .attr('data-test-subj', 'vislibVisualizeError'); div.append('h4').text(markdownIt.renderInline(message)); diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/handler.test.js b/src/plugins/vis_type_vislib/public/vislib/lib/handler.test.js index d50c70de1bb48..119a24d2f25d1 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/handler.test.js +++ b/src/plugins/vis_type_vislib/public/vislib/lib/handler.test.js @@ -157,7 +157,7 @@ dateHistogramArray.forEach(function (data, i) { const args = Array.from(arguments); expect(args.length).toBe(2); expect(args[0]).toBe('click'); - expect(args[1]).toBe(event); + expect(args[1].data).toBe(event); done(); }; diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/vis_config.js b/src/plugins/vis_type_vislib/public/vislib/lib/vis_config.js index dda9d85ec43c5..2086f744be584 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/vis_config.js +++ b/src/plugins/vis_type_vislib/public/vislib/lib/vis_config.js @@ -50,7 +50,6 @@ export class VisConfig { return _.get(this._values, property, defaults); } else { throw new Error(`Accessing invalid config property: ${property}`); - return defaults; } } diff --git a/src/plugins/vis_type_vislib/public/vislib/vis.js b/src/plugins/vis_type_vislib/public/vislib/vis.js index f258cb55ba281..628b876fc50c5 100644 --- a/src/plugins/vis_type_vislib/public/vislib/vis.js +++ b/src/plugins/vis_type_vislib/public/vislib/vis.js @@ -35,13 +35,14 @@ import { DIMMING_OPACITY_SETTING, HEATMAP_MAX_BUCKETS_SETTING } from '../../comm * @param config {Object} Parameters that define the chart type and chart options */ export class Vis extends EventEmitter { - constructor(element, visConfigArgs, deps) { + constructor(element, visConfigArgs, core, charts) { super(); this.element = element.get ? element.get(0) : element; this.visConfigArgs = _.cloneDeep(visConfigArgs); - this.visConfigArgs.dimmingOpacity = deps.uiSettings.get(DIMMING_OPACITY_SETTING); - this.visConfigArgs.heatmapMaxBuckets = deps.uiSettings.get(HEATMAP_MAX_BUCKETS_SETTING); - this.deps = deps; + this.visConfigArgs.dimmingOpacity = core.uiSettings.get(DIMMING_OPACITY_SETTING); + this.visConfigArgs.heatmapMaxBuckets = core.uiSettings.get(HEATMAP_MAX_BUCKETS_SETTING); + this.charts = charts; + this.uiSettings = core.uiSettings; } hasLegend() { @@ -56,7 +57,7 @@ export class Vis extends EventEmitter { this.data, this.uiState, this.element, - this.deps.charts.colors.createColorLookupFunction.bind(this.deps.charts.colors) + this.charts.colors.createColorLookupFunction.bind(this.charts.colors) ); } @@ -78,7 +79,7 @@ export class Vis extends EventEmitter { this.initVisConfig(data, uiState); - this.handler = new Handler(this, this.visConfig, this.deps); + this.handler = new Handler(this, this.visConfig, this.uiSettings); this._runOnHandler('render'); } diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/_chart.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/_chart.js index 5ed6d3eb79f4b..e5cb0235b6510 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/_chart.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/_chart.js @@ -39,13 +39,13 @@ import { * @param chartData {Object} Elasticsearch query results for this specific chart */ export class Chart { - constructor(handler, element, chartData, deps) { + constructor(handler, element, chartData, uiSettings) { this.handler = handler; this.chartEl = element; this.chartData = chartData; this.tooltips = []; - const events = (this.events = new Dispatch(handler, deps.uiSettings)); + const events = (this.events = new Dispatch(handler, uiSettings)); const fieldFormatter = getFormatService().deserialize( this.handler.data.get('tooltipFormatter') diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/_vis_fixture.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/_vis_fixture.js index 0ffa53fc7ca9c..11b5964eebdf3 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/_vis_fixture.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/_vis_fixture.js @@ -53,20 +53,10 @@ afterEach(function () { count = 0; }); -const getDeps = () => { - const mockUiSettings = coreMock.createSetup().uiSettings; - const charts = chartPluginMock.createStartContract(); - - return { - uiSettings: mockUiSettings, - charts: charts, - }; -}; - -export function getVis(visLibParams, element) { +export function getVis(vislibParams, element) { return new Vis( element || $visCanvas.new(), - _.defaults({}, visLibParams || {}, { + _.defaults({}, vislibParams || {}, { addTooltip: true, addLegend: true, defaultYExtents: false, @@ -74,6 +64,7 @@ export function getVis(visLibParams, element) { yAxis: {}, type: 'histogram', }), - getDeps() + coreMock.createSetup(), + chartPluginMock.createStartContract() ); } diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.test.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.test.js index 6fdc2a134b820..913b237a10e58 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.test.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.test.js @@ -28,7 +28,7 @@ import { getVis } from './_vis_fixture'; describe('Vislib Gauge Chart Test Suite', function () { let vis; let chartEl; - const visLibParams = { + const vislibParams = { type: 'gauge', addTooltip: true, addLegend: false, @@ -71,7 +71,7 @@ describe('Vislib Gauge Chart Test Suite', function () { }; function generateVis(opts = {}) { - const config = _.defaultsDeep({}, opts, visLibParams); + const config = _.defaultsDeep({}, opts, vislibParams); if (vis) { vis.destroy(); $('.visChart').remove(); diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.js index 938d3d0ec6d74..b1acea34aabf6 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.js @@ -42,8 +42,8 @@ const defaults = { * @param chartData {Object} Elasticsearch query results for this specific chart */ export class PieChart extends Chart { - constructor(handler, chartEl, chartData, deps) { - super(handler, chartEl, chartData, deps); + constructor(handler, chartEl, chartData, uiSettings) { + super(handler, chartEl, chartData, uiSettings); const charts = this.handler.data.getVisData(); this._validatePieData(charts); this._attr = _.defaults(handler.visConfig.get('chart', {}), defaults); diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.test.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.test.js index e2da33d0808ba..1207db2e54bb8 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.test.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.test.js @@ -40,7 +40,7 @@ let mockedSVGElementGetBBox; let mockedSVGElementGetComputedTextLength; describe('No global chart settings', function () { - const visLibParams1 = { + const vislibParams1 = { el: '
', type: 'pie', addLegend: true, @@ -58,7 +58,7 @@ describe('No global chart settings', function () { }); beforeEach(() => { - chart1 = getVis(visLibParams1); + chart1 = getVis(vislibParams1); mockUiState = getMockUiState(); }); @@ -153,7 +153,7 @@ describe('Vislib PieChart Class Test Suite', function () { describe('Vislib PieChart Class Test Suite for ' + names[i] + ' data', function () { const mockPieData = pieChartMockData[aggItem]; - const visLibParams = { + const vislibParams = { type: 'pie', addLegend: true, addTooltip: true, @@ -161,7 +161,7 @@ describe('Vislib PieChart Class Test Suite', function () { let vis; beforeEach(async () => { - vis = getVis(visLibParams); + vis = getVis(vislibParams); const mockUiState = getMockUiState(); vis.render(mockPieData, mockUiState); }); diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series.js index 9a25d041f6567..a40d46737f05e 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series.js @@ -40,10 +40,10 @@ const touchdownTmpl = _.template(touchdownTmplHtml); * @param chartData {Object} Elasticsearch query results for this specific chart */ export class PointSeries extends Chart { - constructor(handler, chartEl, chartData, deps) { - super(handler, chartEl, chartData, deps); + constructor(handler, chartEl, chartData, uiSettings) { + super(handler, chartEl, chartData, uiSettings); - this.deps = deps; + this.uiSettings = uiSettings; this.handler = handler; this.chartData = chartData; this.chartEl = chartEl; @@ -246,7 +246,13 @@ export class PointSeries extends Chart { if (!seriArgs.show) return; const SeriClass = seriTypes[seriArgs.type || self.handler.visConfig.get('chart.type')] || seriTypes.line; - const series = new SeriClass(self.handler, svg, data.series[i], seriArgs, self.deps); + const series = new SeriClass( + self.handler, + svg, + data.series[i], + seriArgs, + self.uiSettings + ); series.events = self.events; svg.call(series.draw()); self.series.push(series); diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.js index e3e2d31ecd4f4..b65c5be330fef 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.js @@ -43,8 +43,8 @@ const defaults = { * chart */ export class AreaChart extends PointSeries { - constructor(handler, chartEl, chartData, seriesConfigArgs, deps) { - super(handler, chartEl, chartData, seriesConfigArgs, deps); + constructor(handler, chartEl, chartData, seriesConfigArgs, core) { + super(handler, chartEl, chartData, seriesConfigArgs, core); this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults); this.isOverlapping = this.seriesConfig.mode !== 'stacked'; diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.test.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.test.js index 3cd58060978ee..ae15d95d560ca 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.test.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.test.js @@ -38,7 +38,7 @@ const dataTypesArray = { stackedSeries: import('../../../fixtures/mock_data/date_histogram/_stacked_series'), }; -const visLibParams = { +const vislibParams = { type: 'area', addLegend: true, addTooltip: true, @@ -61,7 +61,7 @@ _.forOwn(dataTypesArray, function (dataType, dataTypeName) { }); beforeEach(async () => { - vis = getVis(visLibParams); + vis = getVis(vislibParams); mockUiState = getMockUiState(); vis.on('brush', _.noop); vis.render(await dataType, mockUiState); diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.js index 1369bf1dff68a..07bebf4eb2f83 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.js @@ -57,8 +57,8 @@ function datumWidth(defaultWidth, datum, nextDatum, scale, gutterWidth, groupCou * @param chartData {Object} Elasticsearch query results for this specific chart */ export class ColumnChart extends PointSeries { - constructor(handler, chartEl, chartData, seriesConfigArgs, deps) { - super(handler, chartEl, chartData, seriesConfigArgs, deps); + constructor(handler, chartEl, chartData, seriesConfigArgs, core) { + super(handler, chartEl, chartData, seriesConfigArgs, core); this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults); this.labelOptions = _.defaults(handler.visConfig.get('labels', {}), defaults.showLabel); } diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.test.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.test.js index f3d8d66df2d85..d7fc177a30009 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.test.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.test.js @@ -62,7 +62,7 @@ dataTypesArray.forEach(function (dataType) { describe('Vislib Column Chart Test Suite for ' + name + ' Data', function () { let vis; let mockUiState; - const visLibParams = { + const vislibParams = { type: 'histogram', addLegend: true, addTooltip: true, @@ -81,7 +81,7 @@ dataTypesArray.forEach(function (dataType) { }); beforeEach(() => { - vis = getVis(visLibParams); + vis = getVis(vislibParams); mockUiState = getMockUiState(); vis.on('brush', _.noop); vis.render(data, mockUiState); @@ -261,7 +261,7 @@ dataTypesArray.forEach(function (dataType) { describe('stackData method - data set with zeros in percentage mode', function () { let vis; let mockUiState; - const visLibParams = { + const vislibParams = { type: 'histogram', addLegend: true, addTooltip: true, @@ -276,7 +276,7 @@ describe('stackData method - data set with zeros in percentage mode', function ( }); beforeEach(() => { - vis = getVis(visLibParams); + vis = getVis(vislibParams); mockUiState = getMockUiState(); vis.on('brush', _.noop); }); @@ -320,7 +320,7 @@ describe('stackData method - data set with zeros in percentage mode', function ( describe('datumWidth - split chart data set with holes', function () { let vis; let mockUiState; - const visLibParams = { + const vislibParams = { type: 'histogram', addLegend: true, addTooltip: true, @@ -335,7 +335,7 @@ describe('datumWidth - split chart data set with holes', function () { }); beforeEach(() => { - vis = getVis(visLibParams); + vis = getVis(vislibParams); mockUiState = getMockUiState(); vis.on('brush', _.noop); vis.render(rowsSeriesWithHoles, mockUiState); @@ -366,7 +366,7 @@ describe('datumWidth - split chart data set with holes', function () { describe('datumWidth - monthly interval', function () { let vis; let mockUiState; - const visLibParams = { + const vislibParams = { type: 'histogram', addLegend: true, addTooltip: true, @@ -384,7 +384,7 @@ describe('datumWidth - monthly interval', function () { }); beforeEach(() => { - vis = getVis(visLibParams); + vis = getVis(vislibParams); mockUiState = getMockUiState(); vis.on('brush', _.noop); vis.render(seriesMonthlyInterval, mockUiState); diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.test.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.test.js index 8c727d225c6c3..a7534add76e36 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.test.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.test.js @@ -71,7 +71,7 @@ describe('Vislib Heatmap Chart Test Suite', function () { describe('for ' + name + ' Data', function () { let vis; let mockUiState; - const visLibParams = { + const vislibParams = { type: 'heatmap', addLegend: true, addTooltip: true, @@ -84,7 +84,7 @@ describe('Vislib Heatmap Chart Test Suite', function () { }; function generateVis(opts = {}) { - const config = _.defaultsDeep({}, opts, visLibParams); + const config = _.defaultsDeep({}, opts, vislibParams); vis = getVis(config); mockUiState = getMockUiState(); vis.on('brush', _.noop); diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.js index 64fbae7d1ac8c..983c15c004b97 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.js @@ -42,8 +42,8 @@ const defaults = { * @param chartData {Object} Elasticsearch query results for this specific chart */ export class LineChart extends PointSeries { - constructor(handler, chartEl, chartData, seriesConfigArgs, deps) { - super(handler, chartEl, chartData, seriesConfigArgs, deps); + constructor(handler, chartEl, chartData, seriesConfigArgs, core) { + super(handler, chartEl, chartData, seriesConfigArgs, core); this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults); } diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.test.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.test.js index a84c74c095051..8d86df7c27da4 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.test.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.test.js @@ -71,14 +71,14 @@ describe('Vislib Line Chart', function () { let mockUiState; beforeEach(() => { - const visLibParams = { + const vislibParams = { type: 'line', addLegend: true, addTooltip: true, drawLinesBetweenPoints: true, }; - vis = getVis(visLibParams); + vis = getVis(vislibParams); mockUiState = getMockUiState(); vis.render(data, mockUiState); vis.on('brush', _.noop); diff --git a/src/plugins/visualizations/public/components/_visualization.scss b/src/plugins/visualizations/public/components/_visualization.scss index f5e2d4fcf2862..bde9621fd70b8 100644 --- a/src/plugins/visualizations/public/components/_visualization.scss +++ b/src/plugins/visualizations/public/components/_visualization.scss @@ -70,10 +70,10 @@ flex-direction: column; } -.visChart__spinner { +.visChart__spinner, .visError { display: flex; flex: 1 1 auto; justify-content: center; align-items: center; + text-align: center; } - diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index 081399fd1fbea..7bd4466b23166 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -52,6 +52,7 @@ export { ISavedVis, VisSavedObject, VisResponseValue, + VisToExpressionAst, } from './types'; export { ExprVisAPIEvents } from './expressions/vis'; export { VisualizationListItem } from './vis_types/vis_type_alias_registry'; diff --git a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap index 959d9031853af..2c6cfc6fb7462 100644 --- a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap +++ b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap @@ -6,8 +6,6 @@ exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunct exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles metrics/tsvb function 1`] = `"tsvb params='{\\"foo\\":\\"bar\\"}' uiState='{}' "`; -exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles pie function 1`] = `"kibana_pie visConfig='{\\"dimensions\\":{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"},\\"buckets\\":[1,2]}}' "`; - exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles region_map function with buckets 1`] = `"regionmap visConfig='{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"},\\"bucket\\":1}' "`; exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles region_map function without buckets 1`] = `"regionmap visConfig='{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"}}' "`; diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts index 501a69080d93f..0c210a04d2007 100644 --- a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts @@ -21,14 +21,12 @@ import { prepareJson, prepareString, buildPipelineVisFunction, - buildVislibDimensions, buildPipeline, SchemaConfig, Schemas, } from './build_pipeline'; import { Vis } from '..'; import { dataPluginMock } from '../../../../plugins/data/public/mocks'; -import { IndexPattern, IAggConfigs } from '../../../../plugins/data/public'; import { parseExpression } from '../../../expressions/common'; describe('visualize loader pipeline helpers: build pipeline', () => { @@ -136,15 +134,6 @@ describe('visualize loader pipeline helpers: build pipeline', () => { const actual = buildPipelineVisFunction.tile_map(params, schemas, uiState); expect(actual).toMatchSnapshot(); }); - - it('handles pie function', () => { - const schemas = { - ...schemasDef, - segment: [1, 2], - }; - const actual = buildPipelineVisFunction.pie({}, schemas, uiState); - expect(actual).toMatchSnapshot(); - }); }); describe('buildPipeline', () => { @@ -174,157 +163,4 @@ describe('visualize loader pipeline helpers: build pipeline', () => { expect(expression).toMatchSnapshot(); }); }); - - describe('buildVislibDimensions', () => { - const dataStart = dataPluginMock.createStartContract(); - - let aggs: IAggConfigs; - let vis: Vis; - let params: any; - - beforeEach(() => { - aggs = dataStart.search.aggs.createAggConfigs({} as IndexPattern, [ - { - id: '0', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - ]); - - params = { - searchSource: null, - timefilter: dataStart.query.timefilter.timefilter, - timeRange: null, - }; - }); - - describe('test y dimension format for histogram chart', () => { - beforeEach(() => { - vis = { - // @ts-ignore - type: { - name: 'histogram', - }, - params: { - seriesParams: [ - { - data: { id: '0' }, - valueAxis: 'axis-y', - }, - ], - valueAxes: [ - { - id: 'axis-y', - scale: { - mode: 'normal', - }, - }, - ], - }, - data: { - aggs, - searchSource: {} as any, - }, - isHierarchical: () => { - return false; - }, - }; - }); - - it('with one numeric metric in regular moder', async () => { - const dimensions = await buildVislibDimensions(vis, params); - const expected = { id: 'number' }; - const actual = dimensions.y[0].format; - expect(actual).toEqual(expected); - }); - - it('with one numeric metric in percentage mode', async () => { - vis.params.valueAxes[0].scale.mode = 'percentage'; - const dimensions = await buildVislibDimensions(vis, params); - const expected = { id: 'percent' }; - const actual = dimensions.y[0].format; - expect(actual).toEqual(expected); - }); - - it('with two numeric metrics, mixed normal and percent mode should have corresponding formatters', async () => { - aggs.createAggConfig({ - id: '5', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }); - - vis.params = { - seriesParams: [ - { - data: { id: '0' }, - valueAxis: 'axis-y-1', - }, - { - data: { id: '5' }, - valueAxis: 'axis-y-2', - }, - ], - valueAxes: [ - { - id: 'axis-y-1', - scale: { - mode: 'normal', - }, - }, - { - id: 'axis-y-2', - scale: { - mode: 'percentage', - }, - }, - ], - }; - - const dimensions = await buildVislibDimensions(vis, params); - const expectedY1 = { id: 'number' }; - const expectedY2 = { id: 'percent' }; - expect(dimensions.y[0].format).toEqual(expectedY1); - expect(dimensions.y[1].format).toEqual(expectedY2); - }); - }); - - describe('test y dimension format for gauge chart', () => { - beforeEach(() => { - vis = { - // @ts-ignore - type: { - name: 'gauge', - }, - params: { gauge: {} }, - data: { - aggs, - searchSource: {} as any, - }, - isHierarchical: () => { - return false; - }, - }; - }); - - it('with percentageMode = false', async () => { - vis.params.gauge.percentageMode = false; - const dimensions = await buildVislibDimensions(vis, params); - const expected = { id: 'number' }; - const actual = dimensions.y[0].format; - expect(actual).toEqual(expected); - }); - - it('with percentageMode = true', async () => { - vis.params.gauge.percentageMode = true; - const dimensions = await buildVislibDimensions(vis, params); - const expected = { id: 'percent' }; - const actual = dimensions.y[0].format; - expect(actual).toEqual(expected); - }); - }); - }); }); diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.ts b/src/plugins/visualizations/public/legacy/build_pipeline.ts index b08583c376b36..3593d62b9d2e6 100644 --- a/src/plugins/visualizations/public/legacy/build_pipeline.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.ts @@ -17,8 +17,6 @@ * under the License. */ -import { get } from 'lodash'; -import moment from 'moment'; import { formatExpression, SerializedFieldFormat } from '../../../../plugins/expressions/public'; import { IAggConfig, search, TimefilterContract } from '../../../../plugins/data/public'; import { Vis, VisParams } from '../types'; @@ -76,16 +74,6 @@ export interface BuildPipelineParams { abortSignal?: AbortSignal; } -const vislibCharts: string[] = [ - 'area', - 'gauge', - 'goal', - 'heatmap', - 'histogram', - 'horizontal_bar', - 'line', -]; - export const getSchemas = ( vis: Vis, { timeRange, timefilter }: BuildPipelineParams @@ -230,29 +218,6 @@ export const prepareDimension = (variable: string, data: any) => { return expr; }; -const adjustVislibDimensionFormmaters = (vis: Vis, dimensions: { y: any[] }): void => { - const visConfig = vis.params; - const responseAggs = vis.data.aggs!.getResponseAggs().filter((agg: IAggConfig) => agg.enabled); - - (dimensions.y || []).forEach((yDimension) => { - const yAgg = responseAggs[yDimension.accessor]; - const seriesParam = (visConfig.seriesParams || []).find( - (param: any) => param.data.id === yAgg.id - ); - if (seriesParam) { - const usedValueAxis = (visConfig.valueAxes || []).find( - (valueAxis: any) => valueAxis.id === seriesParam.valueAxis - ); - if (get(usedValueAxis, 'scale.mode') === 'percentage') { - yDimension.format = { id: 'percent' }; - } - } - if (get(visConfig, 'gauge.percentageMode') === true) { - yDimension.format = { id: 'percent' }; - } - }); -}; - export const buildPipelineVisFunction: BuildPipelineVisFunction = { input_control_vis: (params) => { return `input_control_vis ${prepareJson('visConfig', params)}`; @@ -278,13 +243,6 @@ export const buildPipelineVisFunction: BuildPipelineVisFunction = { }; return `tilemap ${prepareJson('visConfig', visConfig)}`; }, - pie: (params, schemas) => { - const visConfig = { - ...params, - ...buildVisConfig.pie(schemas), - }; - return `kibana_pie ${prepareJson('visConfig', visConfig)}`; - }, }; const buildVisConfig: BuildVisConfigFunction = { @@ -305,55 +263,6 @@ const buildVisConfig: BuildVisConfigFunction = { }; return visConfig; }, - pie: (schemas) => { - const visConfig = {} as any; - visConfig.dimensions = { - metric: schemas.metric[0], - buckets: schemas.segment, - splitRow: schemas.split_row, - splitColumn: schemas.split_column, - }; - return visConfig; - }, -}; - -export const buildVislibDimensions = async (vis: any, params: BuildPipelineParams) => { - const schemas = getSchemas(vis, { - timeRange: params.timeRange, - timefilter: params.timefilter, - }); - const dimensions = { - x: schemas.segment ? schemas.segment[0] : null, - y: schemas.metric, - z: schemas.radius, - width: schemas.width, - series: schemas.group, - splitRow: schemas.split_row, - splitColumn: schemas.split_column, - }; - if (schemas.segment) { - const xAgg = vis.data.aggs.getResponseAggs()[dimensions.x.accessor]; - if (xAgg.type.name === 'date_histogram') { - dimensions.x.params.date = true; - const { esUnit, esValue } = xAgg.buckets.getInterval(); - dimensions.x.params.interval = moment.duration(esValue, esUnit); - dimensions.x.params.intervalESValue = esValue; - dimensions.x.params.intervalESUnit = esUnit; - dimensions.x.params.format = xAgg.buckets.getScaledDateFormat(); - dimensions.x.params.bounds = xAgg.buckets.getBounds(); - } else if (xAgg.type.name === 'histogram') { - const intervalParam = xAgg.type.paramByName('interval'); - const output = { params: {} as any }; - await intervalParam.modifyAggConfigOnSearchRequestStart(xAgg, vis.data.searchSource, { - abortSignal: params.abortSignal, - }); - intervalParam.write(xAgg, output); - dimensions.x.params.interval = output.params.interval; - } - } - - adjustVislibDimensionFormmaters(vis, dimensions); - return dimensions; }; export const buildPipeline = async (vis: Vis, params: BuildPipelineParams) => { @@ -396,11 +305,6 @@ export const buildPipeline = async (vis: Vis, params: BuildPipelineParams) => { schemas, uiState ); - } else if (vislibCharts.includes(vis.type.name)) { - const visConfig = { ...vis.params }; - visConfig.dimensions = await buildVislibDimensions(vis, params); - - pipeline += `vislib type='${vis.type.name}' ${prepareJson('visConfig', visConfig)}`; } else { const visConfig = { ...vis.params }; visConfig.dimensions = schemas; diff --git a/src/plugins/visualizations/public/types.ts b/src/plugins/visualizations/public/types.ts index 68ab3561d375c..3c322f5e79165 100644 --- a/src/plugins/visualizations/public/types.ts +++ b/src/plugins/visualizations/public/types.ts @@ -76,4 +76,4 @@ export interface VisToExpressionAstParams { export type VisToExpressionAst = ( vis: Vis, params: VisToExpressionAstParams -) => ExpressionAstExpression; +) => Promise | ExpressionAstExpression; diff --git a/test/functional/page_objects/visualize_chart_page.ts b/test/functional/page_objects/visualize_chart_page.ts index cb114866322db..1acea624ad4cd 100644 --- a/test/functional/page_objects/visualize_chart_page.ts +++ b/test/functional/page_objects/visualize_chart_page.ts @@ -218,7 +218,7 @@ export function VisualizeChartPageProvider({ getService, getPageObjects }: FtrPr } public async expectError() { - await testSubjects.existOrFail('visLibVisualizeError'); + await testSubjects.existOrFail('vislibVisualizeError'); } public async getVisualizationRenderingCount() { From fe807d68a6dabb735e1488c66fda6de8675f2f8b Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 29 Oct 2020 15:10:18 -0400 Subject: [PATCH 7/9] [Maps] Add readme for Maps plugins (#82023) --- .github/CODEOWNERS | 2 -- docs/developer/plugin-list.asciidoc | 16 ++++++++-------- src/plugins/maps_legacy/README.md | 7 +++++++ src/plugins/region_map/README.md | 5 +++++ src/plugins/tile_map/README.md | 5 +++++ x-pack/plugins/file_upload/README.md | 3 +++ 6 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 src/plugins/maps_legacy/README.md create mode 100644 src/plugins/region_map/README.md create mode 100644 src/plugins/tile_map/README.md create mode 100644 x-pack/plugins/file_upload/README.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 525da9d832b53..28380549c751c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -171,8 +171,6 @@ /x-pack/test/functional/apps/maps/ @elastic/kibana-gis /x-pack/test/functional/es_archives/maps/ @elastic/kibana-gis /x-pack/test/visual_regression/tests/maps/index.js @elastic/kibana-gis -#CC# /src/legacy/core_plugins/region_map @elastic/kibana-gis -#CC# /src/legacy/core_plugins/tile_map @elastic/kibana-gis #CC# /src/plugins/maps_legacy/ @elastic/kibana-gis #CC# /x-pack/plugins/file_upload @elastic/kibana-gis #CC# /x-pack/plugins/maps_legacy_licensing @elastic/kibana-gis diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index f30afce3ee02c..dee6e4777884c 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -134,8 +134,8 @@ in Kibana, e.g. visualizations. It has the form of a flyout panel. |WARNING: Missing README. -|{kib-repo}blob/{branch}/src/plugins/maps_legacy[mapsLegacy] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/src/plugins/maps_legacy/README.md[mapsLegacy] +|Internal objects used by the Coordinate, Region, and Vega visualizations. |{kib-repo}blob/{branch}/src/plugins/navigation/README.md[navigation] @@ -147,8 +147,8 @@ It also provides a stateful version of it on the start contract. |WARNING: Missing README. -|{kib-repo}blob/{branch}/src/plugins/region_map[regionMap] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/src/plugins/region_map/README.md[regionMap] +|Create choropleth maps. Display the results of a term-aggregation as e.g. countries, zip-codes, states. |{kib-repo}blob/{branch}/src/plugins/saved_objects[savedObjects] @@ -180,8 +180,8 @@ so they can properly protect the data within their clusters. |This plugin adds the Advanced Settings section for the Usage and Security Data collection (aka Telemetry). -|{kib-repo}blob/{branch}/src/plugins/tile_map[tileMap] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/src/plugins/tile_map/README.md[tileMap] +|Create a coordinate map. Display the results of a geohash_tile aggregation as bubbles, rectangles, or heatmap color blobs. |{kib-repo}blob/{branch}/src/plugins/timelion/README.md[timelion] @@ -355,8 +355,8 @@ and actions. |WARNING: Missing README. -|{kib-repo}blob/{branch}/x-pack/plugins/file_upload[fileUpload] -|WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/file_upload/README.md[fileUpload] +|Backend and core front-end react-components for GeoJson file upload. Only supports the Maps plugin. |{kib-repo}blob/{branch}/x-pack/plugins/global_search/README.md[globalSearch] diff --git a/src/plugins/maps_legacy/README.md b/src/plugins/maps_legacy/README.md new file mode 100644 index 0000000000000..4a870e4f7492d --- /dev/null +++ b/src/plugins/maps_legacy/README.md @@ -0,0 +1,7 @@ +# Maps legacy + +Internal objects used by the Coordinate, Region, and Vega visualizations. + +It exports the default Leaflet-based map and exposes the connection to the Elastic Maps service. + +This plugin is targeted for removal in 8.0. \ No newline at end of file diff --git a/src/plugins/region_map/README.md b/src/plugins/region_map/README.md new file mode 100644 index 0000000000000..540ab47c102d3 --- /dev/null +++ b/src/plugins/region_map/README.md @@ -0,0 +1,5 @@ +# Region map visualization + +Create choropleth maps. Display the results of a term-aggregation as e.g. countries, zip-codes, states. + +This plugin is targeted for removal in 8.0. \ No newline at end of file diff --git a/src/plugins/tile_map/README.md b/src/plugins/tile_map/README.md new file mode 100644 index 0000000000000..633ee7dba46d6 --- /dev/null +++ b/src/plugins/tile_map/README.md @@ -0,0 +1,5 @@ +# Coordinate map visualization + +Create a coordinate map. Display the results of a geohash_tile aggregation as bubbles, rectangles, or heatmap color blobs. + +This plugin is targeted for removal in 8.0. \ No newline at end of file diff --git a/x-pack/plugins/file_upload/README.md b/x-pack/plugins/file_upload/README.md new file mode 100644 index 0000000000000..0d4b4da61ccf6 --- /dev/null +++ b/x-pack/plugins/file_upload/README.md @@ -0,0 +1,3 @@ +# File upload + +Backend and core front-end react-components for GeoJson file upload. Only supports the Maps plugin. \ No newline at end of file From 915997e08b3c98df5afe839f19810b89f8e77db1 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 29 Oct 2020 14:37:07 -0500 Subject: [PATCH 8/9] skip 'should timeout if payload sending has too long of an idle period' --- src/core/server/http/integration_tests/router.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/server/http/integration_tests/router.test.ts b/src/core/server/http/integration_tests/router.test.ts index e19c348511f1a..ad228d9b0bb9d 100644 --- a/src/core/server/http/integration_tests/router.test.ts +++ b/src/core/server/http/integration_tests/router.test.ts @@ -384,7 +384,7 @@ describe('Options', () => { }); describe('idleSocket', () => { - it('should timeout if payload sending has too long of an idle period', async () => { + it.skip('should timeout if payload sending has too long of an idle period', async () => { const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); From ca028b79aab40a2a432b5fcd23af9581f5edf8b2 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 29 Oct 2020 19:45:37 +0000 Subject: [PATCH 9/9] Add sort order to getJourneySteps query (#82038) --- x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts b/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts index e4392480f5b72..d0bb67795d46c 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts @@ -35,6 +35,7 @@ export const getJourneySteps: UMElasticsearchQueryFn