diff --git a/.ci/Dockerfile b/.ci/Dockerfile index cf827fc0ed08..8a972c65f841 100644 --- a/.ci/Dockerfile +++ b/.ci/Dockerfile @@ -1,7 +1,7 @@ # NOTE: This Dockerfile is ONLY used to run certain tasks in CI. It is not used to run Kibana or as a distributable. # If you're looking for the Kibana Docker image distributable, please see: src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts -ARG NODE_VERSION=14.15.2 +ARG NODE_VERSION=14.15.3 FROM node:${NODE_VERSION} AS base diff --git a/.ci/jobs.yml b/.ci/jobs.yml index d4ec8a3d5a69..f62ec9510d2d 100644 --- a/.ci/jobs.yml +++ b/.ci/jobs.yml @@ -1,4 +1,4 @@ -# This file is needed by functionalTests:ensureAllTestsInCiGroup for the list of ciGroups. That must be changed before this file can be removed +# This file is needed by node scripts/ensure_all_tests_in_ci_group for the list of ciGroups. That must be changed before this file can be removed JOB: - kibana-intake diff --git a/.ci/teamcity/bootstrap.sh b/.ci/teamcity/bootstrap.sh index adb884ca064b..fc57811bb207 100755 --- a/.ci/teamcity/bootstrap.sh +++ b/.ci/teamcity/bootstrap.sh @@ -7,7 +7,7 @@ source "$(dirname "${0}")/util.sh" tc_start_block "Bootstrap" tc_start_block "yarn install and kbn bootstrap" -verify_no_git_changes yarn kbn bootstrap --prefer-offline +verify_no_git_changes yarn kbn bootstrap tc_end_block "yarn install and kbn bootstrap" tc_start_block "build kbn-pm" diff --git a/.ci/teamcity/checks/bundle_limits.sh b/.ci/teamcity/checks/bundle_limits.sh index 3f7daef6d047..751ec5a03ee7 100755 --- a/.ci/teamcity/checks/bundle_limits.sh +++ b/.ci/teamcity/checks/bundle_limits.sh @@ -4,4 +4,5 @@ set -euo pipefail source "$(dirname "${0}")/../util.sh" -node scripts/build_kibana_platform_plugins --validate-limits +checks-reporter-with-killswitch "Check Bundle Limits" \ + node scripts/build_kibana_platform_plugins --validate-limits diff --git a/.ci/teamcity/checks/commit.sh b/.ci/teamcity/checks/commit.sh new file mode 100755 index 000000000000..387ec0c12678 --- /dev/null +++ b/.ci/teamcity/checks/commit.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source "$(dirname "${0}")/../util.sh" + +# Runs pre-commit hook script for the files touched in the last commit. +# That way we can ensure a set of quick commit checks earlier as we removed +# the pre-commit hook installation by default. +# If files are more than 200 we will skip it and just use +# the further ci steps that already check linting and file casing for the entire repo. +checks-reporter-with-killswitch "Quick commit checks" \ + "$(dirname "${0}")/commit_check_runner.sh" diff --git a/.ci/teamcity/checks/commit_check_runner.sh b/.ci/teamcity/checks/commit_check_runner.sh new file mode 100755 index 000000000000..f2a4a2056821 --- /dev/null +++ b/.ci/teamcity/checks/commit_check_runner.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +echo "!!!!!!!! ATTENTION !!!!!!!! +That check is intended to provide earlier CI feedback after we remove the automatic install for the local pre-commit hook. +If you want, you can still manually install the pre-commit hook locally by running 'node scripts/register_git_hook locally' +!!!!!!!!!!!!!!!!!!!!!!!!!!! +" + +node scripts/precommit_hook.js --ref HEAD~1..HEAD --max-files 200 --verbose diff --git a/.ci/teamcity/checks/jest_configs.sh b/.ci/teamcity/checks/jest_configs.sh new file mode 100755 index 000000000000..6703ffffb565 --- /dev/null +++ b/.ci/teamcity/checks/jest_configs.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source "$(dirname "${0}")/../util.sh" + +checks-reporter-with-killswitch "Check Jest Configs" \ + node scripts/check_jest_configs diff --git a/.ci/teamcity/checks/plugins_with_circular_deps.sh b/.ci/teamcity/checks/plugins_with_circular_deps.sh new file mode 100755 index 000000000000..5acc4b2ae351 --- /dev/null +++ b/.ci/teamcity/checks/plugins_with_circular_deps.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source "$(dirname "${0}")/../util.sh" + +checks-reporter-with-killswitch "Check Plugins With Circular Dependencies" \ + node scripts/find_plugins_with_circular_deps diff --git a/.ci/teamcity/oss/plugin_functional.sh b/.ci/teamcity/oss/plugin_functional.sh index 5d1ecbcbd48e..3570bf01e49c 100755 --- a/.ci/teamcity/oss/plugin_functional.sh +++ b/.ci/teamcity/oss/plugin_functional.sh @@ -13,6 +13,21 @@ if [[ ! -d "target" ]]; then fi cd - -./test/scripts/test/plugin_functional.sh -./test/scripts/test/example_functional.sh -./test/scripts/test/interpreter_functional.sh +checks-reporter-with-killswitch "Plugin Functional Tests" \ + node scripts/functional_tests \ + --config test/plugin_functional/config.ts \ + --bail \ + --debug + +checks-reporter-with-killswitch "Example Functional Tests" \ + node scripts/functional_tests \ + --config test/examples/config.js \ + --bail \ + --debug + +checks-reporter-with-killswitch "Interpreter Functional Tests" \ + node scripts/functional_tests \ + --config test/interpreter_functional/config.ts \ + --bail \ + --debug \ + --kibana-install-dir "$KIBANA_INSTALL_DIR" diff --git a/.ci/teamcity/setup_env.sh b/.ci/teamcity/setup_env.sh index f662d36247a2..982d129dae2a 100755 --- a/.ci/teamcity/setup_env.sh +++ b/.ci/teamcity/setup_env.sh @@ -25,12 +25,14 @@ tc_set_env FORCE_COLOR 1 tc_set_env TEST_BROWSER_HEADLESS 1 tc_set_env ELASTIC_APM_ENVIRONMENT ci +tc_set_env ELASTIC_APM_TRANSACTION_SAMPLE_RATE 0.1 if [[ "${KIBANA_CI_REPORTER_KEY_BASE64-}" ]]; then tc_set_env KIBANA_CI_REPORTER_KEY "$(echo "$KIBANA_CI_REPORTER_KEY_BASE64" | base64 -d)" fi if is_pr; then + tc_set_env ELASTIC_APM_ACTIVE false tc_set_env CHECKS_REPORTER_ACTIVE true # These can be removed once we're not supporting Jenkins and TeamCity at the same time @@ -39,6 +41,7 @@ if is_pr; then tc_set_env ghprbActualCommit "$GITHUB_PR_TRIGGERED_SHA" tc_set_env BUILD_URL "$TEAMCITY_BUILD_URL" else + tc_set_env ELASTIC_APM_ACTIVE true tc_set_env CHECKS_REPORTER_ACTIVE false fi diff --git a/.node-version b/.node-version index 420568d75691..19c4c189d364 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -14.15.2 +14.15.3 diff --git a/.nvmrc b/.nvmrc index 420568d75691..19c4c189d364 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -14.15.2 +14.15.3 diff --git a/.teamcity/pom.xml b/.teamcity/pom.xml index 5fa068d0a92e..e6ec1f1c043c 100644 --- a/.teamcity/pom.xml +++ b/.teamcity/pom.xml @@ -46,6 +46,14 @@ true + + teamcity + https://artifactory.elstc.co/artifactory/teamcity + + true + always + + @@ -53,6 +61,10 @@ JetBrains https://download.jetbrains.com/teamcity-repository + + teamcity + https://artifactory.elstc.co/artifactory/teamcity + @@ -124,5 +136,10 @@ junit 4.13 + + co.elastic.teamcity + teamcity-common + 1.0.0-SNAPSHOT + diff --git a/.teamcity/settings.kts b/.teamcity/settings.kts index ec1b1c6eb94e..28108d019327 100644 --- a/.teamcity/settings.kts +++ b/.teamcity/settings.kts @@ -2,7 +2,7 @@ import jetbrains.buildServer.configs.kotlin.v2019_2.* import projects.Kibana import projects.KibanaConfiguration -version = "2020.1" +version = "2020.2" val config = KibanaConfiguration { agentNetwork = DslContext.getParameter("agentNetwork", "teamcity") diff --git a/.teamcity/src/Agents.kt b/.teamcity/src/Agents.kt new file mode 100644 index 000000000000..557cce80d0f5 --- /dev/null +++ b/.teamcity/src/Agents.kt @@ -0,0 +1,28 @@ +import co.elastic.teamcity.common.GoogleCloudAgent +import co.elastic.teamcity.common.GoogleCloudAgentDiskType +import co.elastic.teamcity.common.GoogleCloudProfile + +private val sizes = listOf("2", "4", "8", "16") + +val StandardAgents = sizes.map { size -> size to GoogleCloudAgent { + sourceImageFamily = "elastic-kibana-ci-ubuntu-1804-lts" + agentPrefix = "kibana-standard-$size-" + machineType = "n2-standard-$size" + diskSizeGb = 75 + diskType = GoogleCloudAgentDiskType.SSD +} }.toMap() + +val BuildAgent = GoogleCloudAgent { + sourceImageFamily = "elastic-kibana-ci-ubuntu-1804-lts" + agentPrefix = "kibana-c2-16-" + machineType = "c2-standard-16" + diskSizeGb = 250 + diskType = GoogleCloudAgentDiskType.SSD +} + +val CloudProfile = GoogleCloudProfile { + accessKeyId = "447fdd4d-7129-46b7-9822-2e57658c7422" + + agents(StandardAgents) + agent(BuildAgent) +} diff --git a/.teamcity/src/Extensions.kt b/.teamcity/src/Extensions.kt index 120b333d43e7..2942a6385f13 100644 --- a/.teamcity/src/Extensions.kt +++ b/.teamcity/src/Extensions.kt @@ -1,9 +1,7 @@ +import co.elastic.teamcity.common.requireAgent import jetbrains.buildServer.configs.kotlin.v2019_2.* -import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.notifications import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.ScriptBuildStep import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.script -import jetbrains.buildServer.configs.kotlin.v2019_2.ui.insert -import projects.kibanaConfiguration fun BuildFeatures.junit(dirs: String = "target/**/TEST-*.xml") { feature { @@ -13,40 +11,8 @@ fun BuildFeatures.junit(dirs: String = "target/**/TEST-*.xml") { } } -fun ProjectFeatures.kibanaAgent(init: ProjectFeature.() -> Unit) { - feature { - type = "CloudImage" - param("network", kibanaConfiguration.agentNetwork) - param("subnet", kibanaConfiguration.agentSubnet) - param("growingId", "true") - param("agent_pool_id", "-2") - param("preemptible", "false") - param("sourceProject", "elastic-images-prod") - param("sourceImageFamily", "elastic-kibana-ci-ubuntu-1804-lts") - param("zone", "us-central1-a") - param("profileId", "kibana") - param("diskType", "pd-ssd") - param("machineCustom", "false") - param("maxInstances", "200") - param("imageType", "ImageFamily") - param("diskSizeGb", "75") // TODO - init() - } -} - -fun ProjectFeatures.kibanaAgent(size: String, init: ProjectFeature.() -> Unit = {}) { - kibanaAgent { - id = "KIBANA_STANDARD_$size" - param("source-id", "kibana-standard-$size-") - param("machineType", "n2-standard-$size") - init() - } -} - fun BuildType.kibanaAgent(size: String) { - requirements { - startsWith("teamcity.agent.name", "kibana-standard-$size-", "RQ_AGENT_NAME") - } + requireAgent(StandardAgents[size]!!) } fun BuildType.kibanaAgent(size: Int) { diff --git a/.teamcity/src/builds/Checks.kt b/.teamcity/src/builds/Checks.kt index 1228ea4d94f4..37336316c4c9 100644 --- a/.teamcity/src/builds/Checks.kt +++ b/.teamcity/src/builds/Checks.kt @@ -11,16 +11,18 @@ object Checks : BuildType({ kibanaAgent(4) val checkScripts = mapOf( + "Quick Commit Checks" to ".ci/teamcity/checks/commit.sh", "Check Telemetry Schema" to ".ci/teamcity/checks/telemetry.sh", "Check TypeScript Projects" to ".ci/teamcity/checks/ts_projects.sh", "Check File Casing" to ".ci/teamcity/checks/file_casing.sh", "Check Licenses" to ".ci/teamcity/checks/licenses.sh", "Verify NOTICE" to ".ci/teamcity/checks/verify_notice.sh", - "Test Hardening" to ".ci/teamcity/checks/test_hardening.sh", "Check Types" to ".ci/teamcity/checks/type_check.sh", + "Check Jest Configs" to ".ci/teamcity/checks/jest_configs.sh", "Check Doc API Changes" to ".ci/teamcity/checks/doc_api_changes.sh", "Check Bundle Limits" to ".ci/teamcity/checks/bundle_limits.sh", - "Check i18n" to ".ci/teamcity/checks/i18n.sh" + "Check i18n" to ".ci/teamcity/checks/i18n.sh", + "Check Plugins With Circular Dependencies" to ".ci/teamcity/checks/plugins_with_circular_deps.sh" ) steps { diff --git a/.teamcity/src/builds/default/DefaultCiGroup.kt b/.teamcity/src/builds/default/DefaultCiGroup.kt index 7dbe9cd0ba84..2c3b0d348591 100755 --- a/.teamcity/src/builds/default/DefaultCiGroup.kt +++ b/.teamcity/src/builds/default/DefaultCiGroup.kt @@ -1,5 +1,7 @@ package builds.default +import StandardAgents +import co.elastic.teamcity.common.requireAgent import jetbrains.buildServer.configs.kotlin.v2019_2.* import runbld @@ -11,5 +13,7 @@ class DefaultCiGroup(val ciGroup: Int = 0, init: BuildType.() -> Unit = {}) : De runbld("Default CI Group $ciGroup", "./.ci/teamcity/default/ci_group.sh $ciGroup") } + requireAgent(StandardAgents["4"]!!) + init() }) diff --git a/.teamcity/src/builds/default/DefaultCiGroups.kt b/.teamcity/src/builds/default/DefaultCiGroups.kt index 6f1d45598c92..4f39283149e7 100644 --- a/.teamcity/src/builds/default/DefaultCiGroups.kt +++ b/.teamcity/src/builds/default/DefaultCiGroups.kt @@ -3,7 +3,7 @@ package builds.default import dependsOn import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType -const val DEFAULT_CI_GROUP_COUNT = 10 +const val DEFAULT_CI_GROUP_COUNT = 11 val defaultCiGroups = (1..DEFAULT_CI_GROUP_COUNT).map { DefaultCiGroup(it) } object DefaultCiGroups : BuildType({ diff --git a/.teamcity/src/builds/es_snapshots/Verify.kt b/.teamcity/src/builds/es_snapshots/Verify.kt index c778814af536..4c0307e9eca5 100644 --- a/.teamcity/src/builds/es_snapshots/Verify.kt +++ b/.teamcity/src/builds/es_snapshots/Verify.kt @@ -6,7 +6,7 @@ import builds.default.defaultCiGroups import builds.oss.OssBuild import builds.oss.OssPluginFunctional import builds.oss.ossCiGroups -import builds.test.ApiServerIntegration +import builds.oss.OssApiServerIntegration import builds.test.JestIntegration import dependsOn import jetbrains.buildServer.configs.kotlin.v2019_2.* @@ -49,7 +49,7 @@ val defaultBuildsToClone = listOf( val defaultCloned = defaultBuildsToClone.map { cloneForVerify(it) } val integrationsBuildsToClone = listOf( - ApiServerIntegration, + OssApiServerIntegration, JestIntegration ) diff --git a/.teamcity/src/builds/test/ApiServerIntegration.kt b/.teamcity/src/builds/oss/OssApiServerIntegration.kt similarity index 62% rename from .teamcity/src/builds/test/ApiServerIntegration.kt rename to .teamcity/src/builds/oss/OssApiServerIntegration.kt index ca58b628cbd2..a04512fb2aba 100644 --- a/.teamcity/src/builds/test/ApiServerIntegration.kt +++ b/.teamcity/src/builds/oss/OssApiServerIntegration.kt @@ -1,10 +1,8 @@ -package builds.test +package builds.oss -import addTestSettings -import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType import runbld -object ApiServerIntegration : BuildType({ +object OssApiServerIntegration : OssFunctionalBase({ name = "API/Server Integration" description = "Executes API and Server Integration Tests" @@ -12,6 +10,4 @@ object ApiServerIntegration : BuildType({ runbld("API Integration", "./.ci/teamcity/oss/api_integration.sh") runbld("Server Integration", "./.ci/teamcity/oss/server_integration.sh") } - - addTestSettings() }) diff --git a/.teamcity/src/builds/test/AllTests.kt b/.teamcity/src/builds/test/AllTests.kt index d1b5898d1a5f..9506d98cbe50 100644 --- a/.teamcity/src/builds/test/AllTests.kt +++ b/.teamcity/src/builds/test/AllTests.kt @@ -1,5 +1,6 @@ package builds.test +import builds.oss.OssApiServerIntegration import dependsOn import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType @@ -8,5 +9,5 @@ object AllTests : BuildType({ description = "All Non-Functional Tests" type = Type.COMPOSITE - dependsOn(QuickTests, Jest, XPackJest, JestIntegration, ApiServerIntegration) + dependsOn(QuickTests, Jest, XPackJest, JestIntegration, OssApiServerIntegration) }) diff --git a/.teamcity/src/builds/test/QuickTests.kt b/.teamcity/src/builds/test/QuickTests.kt index 5b1d2541480a..a294fce9599c 100644 --- a/.teamcity/src/builds/test/QuickTests.kt +++ b/.teamcity/src/builds/test/QuickTests.kt @@ -12,7 +12,7 @@ object QuickTests : BuildType({ kibanaAgent(2) val testScripts = mapOf( - "Test Hardening" to ".ci/teamcity/checkes/test_hardening.sh", + "Test Hardening" to ".ci/teamcity/checks/test_hardening.sh", "Test Projects" to ".ci/teamcity/tests/test_projects.sh", "Mocha Tests" to ".ci/teamcity/tests/mocha.sh" ) diff --git a/.teamcity/src/projects/Kibana.kt b/.teamcity/src/projects/Kibana.kt index 20c30eedf5b9..1878f49debe8 100644 --- a/.teamcity/src/projects/Kibana.kt +++ b/.teamcity/src/projects/Kibana.kt @@ -5,9 +5,10 @@ import builds.* import builds.default.* import builds.oss.* import builds.test.* +import CloudProfile +import co.elastic.teamcity.common.googleCloudProfile import jetbrains.buildServer.configs.kotlin.v2019_2.* import jetbrains.buildServer.configs.kotlin.v2019_2.projectFeatures.slackConnection -import kibanaAgent import templates.KibanaTemplate import templates.DefaultTemplate import vcs.Elasticsearch @@ -31,7 +32,7 @@ fun Kibana(config: KibanaConfiguration = KibanaConfiguration()) : Project { param("teamcity.ui.settings.readOnly", "true") // https://github.com/JetBrains/teamcity-webhooks - param("teamcity.internal.webhooks.enable", "true") + param("teamcity.internal.webhooks.enable", "false") param("teamcity.internal.webhooks.events", "BUILD_STARTED;BUILD_FINISHED;BUILD_INTERRUPTED;CHANGES_LOADED;BUILD_TYPE_ADDED_TO_QUEUE;BUILD_PROBLEMS_CHANGED") param("teamcity.internal.webhooks.url", "https://ci-stats.kibana.dev/_teamcity_webhook") param("teamcity.internal.webhooks.username", "automation") @@ -46,36 +47,9 @@ fun Kibana(config: KibanaConfiguration = KibanaConfiguration()) : Project { defaultTemplate = DefaultTemplate - features { - val sizes = listOf("2", "4", "8", "16") - for (size in sizes) { - kibanaAgent(size) - } - - kibanaAgent { - id = "KIBANA_C2_16" - param("source-id", "kibana-c2-16-") - param("machineType", "c2-standard-16") - } - - feature { - id = "kibana" - type = "CloudProfile" - param("agentPushPreset", "") - param("profileId", "kibana") - param("profileServerUrl", "") - param("name", "kibana") - param("total-work-time", "") - param("credentialsType", "key") - param("description", "") - param("next-hour", "") - param("cloud-code", "google") - param("terminate-after-build", "true") - param("terminate-idle-time", "30") - param("enabled", "true") - param("secure:accessKey", "credentialsJSON:447fdd4d-7129-46b7-9822-2e57658c7422") - } + googleCloudProfile(CloudProfile) + features { slackConnection { id = "KIBANA_SLACK" displayName = "Kibana Slack" @@ -106,7 +80,6 @@ fun Kibana(config: KibanaConfiguration = KibanaConfiguration()) : Project { buildType(JestIntegration) } - buildType(ApiServerIntegration) buildType(QuickTests) buildType(AllTests) } @@ -125,6 +98,7 @@ fun Kibana(config: KibanaConfiguration = KibanaConfiguration()) : Project { buildType(OssFirefox) buildType(OssAccessibility) buildType(OssPluginFunctional) + buildType(OssApiServerIntegration) subProject { id("CIGroups") diff --git a/.teamcity/src/templates/DefaultTemplate.kt b/.teamcity/src/templates/DefaultTemplate.kt index 762218b72ab1..1f7f364600e2 100644 --- a/.teamcity/src/templates/DefaultTemplate.kt +++ b/.teamcity/src/templates/DefaultTemplate.kt @@ -1,15 +1,14 @@ package templates +import StandardAgents +import co.elastic.teamcity.common.requireAgent import jetbrains.buildServer.configs.kotlin.v2019_2.Template import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.perfmon object DefaultTemplate : Template({ name = "Default Template" - requirements { - equals("system.cloud.profile_id", "kibana", "RQ_CLOUD_PROFILE_ID") - startsWith("teamcity.agent.name", "kibana-standard-2-", "RQ_AGENT_NAME") - } + requireAgent(StandardAgents["2"]!!) params { param("env.HOME", "/var/lib/jenkins") // TODO once the agent images are sorted out diff --git a/.teamcity/src/templates/KibanaTemplate.kt b/.teamcity/src/templates/KibanaTemplate.kt index 117c30ddb86e..83fe4fdaa1ed 100644 --- a/.teamcity/src/templates/KibanaTemplate.kt +++ b/.teamcity/src/templates/KibanaTemplate.kt @@ -1,5 +1,7 @@ package templates +import StandardAgents +import co.elastic.teamcity.common.requireAgent import vcs.Kibana import jetbrains.buildServer.configs.kotlin.v2019_2.BuildStep import jetbrains.buildServer.configs.kotlin.v2019_2.ParameterDisplay @@ -21,10 +23,7 @@ object KibanaTemplate : Template({ // checkoutDir = "/dev/shm/%system.teamcity.buildType.id%/%system.build.number%/kibana" } - requirements { - equals("system.cloud.profile_id", "kibana", "RQ_CLOUD_PROFILE_ID") - startsWith("teamcity.agent.name", "kibana-standard-2-", "RQ_AGENT_NAME") - } + requireAgent(StandardAgents["2"]!!) features { perfmon { } @@ -41,7 +40,7 @@ object KibanaTemplate : Template({ } failureConditions { - executionTimeoutMin = 120 + executionTimeoutMin = 160 testFailure = false } diff --git a/.teamcity/tests/projects/KibanaTest.kt b/.teamcity/tests/projects/KibanaTest.kt index 677effec5be6..311c15a1da7c 100644 --- a/.teamcity/tests/projects/KibanaTest.kt +++ b/.teamcity/tests/projects/KibanaTest.kt @@ -1,5 +1,7 @@ package projects +import jetbrains.buildServer.configs.kotlin.v2019_2.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2019_2.DslContext import org.junit.Assert.* import org.junit.Test @@ -18,10 +20,11 @@ class KibanaTest { @Test fun test_CloudImages_Exist() { + DslContext.projectId = AbsoluteId("My Project") val project = Kibana(TestConfig) assertTrue(project.features.items.any { - it.type == "CloudImage" && it.params.any { param -> param.name == "network" && param.value == "network"} + it.type == "CloudImage" && it.params.any { param -> param.name == "network" && param.value == "teamcity" } }) } } diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index e32984f911d9..d4d2b229eeba 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -272,7 +272,7 @@ heatmap charts. |{kib-repo}blob/{branch}/src/plugins/vis_type_xy/README.md[visTypeXy] |Contains the new xy-axis chart using the elastic-charts library, which will eventually -replace the vislib xy-axis (bar, area, line) charts. +replace the vislib xy-axis charts including bar, area, and line. |{kib-repo}blob/{branch}/src/plugins/visualizations/README.md[visualizations] diff --git a/docs/development/core/public/kibana-plugin-core-public.app.md b/docs/development/core/public/kibana-plugin-core-public.app.md index 8e8bae5ad9c5..b24ced68b7d3 100644 --- a/docs/development/core/public/kibana-plugin-core-public.app.md +++ b/docs/development/core/public/kibana-plugin-core-public.app.md @@ -24,10 +24,10 @@ export interface App | [exactRoute](./kibana-plugin-core-public.app.exactroute.md) | boolean | If set to true, the application's route will only be checked against an exact match. Defaults to false. | | [icon](./kibana-plugin-core-public.app.icon.md) | string | A URL to an image file used as an icon. Used as a fallback if euiIconType is not provided. | | [id](./kibana-plugin-core-public.app.id.md) | string | The unique identifier of the application | +| [meta](./kibana-plugin-core-public.app.meta.md) | AppMeta | Meta data for an application that represent additional information for the app. See [AppMeta](./kibana-plugin-core-public.appmeta.md) | | [mount](./kibana-plugin-core-public.app.mount.md) | AppMount<HistoryLocationState> | AppMountDeprecated<HistoryLocationState> | A mount function called when the user navigates to this app's route. May have signature of [AppMount](./kibana-plugin-core-public.appmount.md) or [AppMountDeprecated](./kibana-plugin-core-public.appmountdeprecated.md). | | [navLinkStatus](./kibana-plugin-core-public.app.navlinkstatus.md) | AppNavLinkStatus | The initial status of the application's navLink. Defaulting to visible if status is accessible and hidden if status is inaccessible See [AppNavLinkStatus](./kibana-plugin-core-public.appnavlinkstatus.md) | | [order](./kibana-plugin-core-public.app.order.md) | number | An ordinal used to sort nav links relative to one another for display. | -| [searchDeepLinks](./kibana-plugin-core-public.app.searchdeeplinks.md) | AppSearchDeepLink[] | Array of links that represent secondary in-app locations for the app. | | [status](./kibana-plugin-core-public.app.status.md) | AppStatus | The initial status of the application. Defaulting to accessible | | [title](./kibana-plugin-core-public.app.title.md) | string | The title of the application. | | [tooltip](./kibana-plugin-core-public.app.tooltip.md) | string | A tooltip shown when hovering over app link. | diff --git a/docs/development/core/public/kibana-plugin-core-public.app.meta.md b/docs/development/core/public/kibana-plugin-core-public.app.meta.md new file mode 100644 index 000000000000..574fa11605ae --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.app.meta.md @@ -0,0 +1,43 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [App](./kibana-plugin-core-public.app.md) > [meta](./kibana-plugin-core-public.app.meta.md) + +## App.meta property + +Meta data for an application that represent additional information for the app. See [AppMeta](./kibana-plugin-core-public.appmeta.md) + +Signature: + +```typescript +meta?: AppMeta; +``` + +## Remarks + +Used to populate navigational search results (where available). Can be updated using the [App.updater$](./kibana-plugin-core-public.app.updater_.md) observable. See [PublicAppSearchDeepLinkInfo](./kibana-plugin-core-public.publicappsearchdeeplinkinfo.md) for more details. + +## Example + + +```ts +core.application.register({ + id: 'my_app', + title: 'Translated title', + meta: { + keywords: ['translated keyword1', 'translated keyword2'], + searchDeepLinks: [ + { id: 'sub1', title: 'Sub1', path: '/sub1', keywords: ['subpath1'] }, + { + id: 'sub2', + title: 'Sub2', + searchDeepLinks: [ + { id: 'subsub', title: 'SubSub', path: '/sub2/sub', keywords: ['subpath2'] } + ] + } + ], + }, + mount: () => { ... } +}) + +``` + diff --git a/docs/development/core/public/kibana-plugin-core-public.app.searchdeeplinks.md b/docs/development/core/public/kibana-plugin-core-public.app.searchdeeplinks.md deleted file mode 100644 index 667fddbc212a..000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.app.searchdeeplinks.md +++ /dev/null @@ -1,42 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [App](./kibana-plugin-core-public.app.md) > [searchDeepLinks](./kibana-plugin-core-public.app.searchdeeplinks.md) - -## App.searchDeepLinks property - -Array of links that represent secondary in-app locations for the app. - -Signature: - -```typescript -searchDeepLinks?: AppSearchDeepLink[]; -``` - -## Remarks - -Used to populate navigational search results (where available). Can be updated using the [App.updater$](./kibana-plugin-core-public.app.updater_.md) observable. See for more details. - -## Example - -The `path` property on deep links should not include the application's `appRoute`: - -```ts -core.application.register({ - id: 'my_app', - title: 'My App', - searchDeepLinks: [ - { id: 'sub1', title: 'Sub1', path: '/sub1' }, - { - id: 'sub2', - title: 'Sub2', - searchDeepLinks: [ - { id: 'subsub', title: 'SubSub', path: '/sub2/sub' } - ] - } - ], - mount: () => { ... }, -}) - -``` -Will produce deep links on these paths: - `/app/my_app/sub1` - `/app/my_app/sub2/sub` - diff --git a/docs/development/core/public/kibana-plugin-core-public.appmeta.keywords.md b/docs/development/core/public/kibana-plugin-core-public.appmeta.keywords.md new file mode 100644 index 000000000000..13709df68e76 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.appmeta.keywords.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [AppMeta](./kibana-plugin-core-public.appmeta.md) > [keywords](./kibana-plugin-core-public.appmeta.keywords.md) + +## AppMeta.keywords property + +Keywords to represent this application + +Signature: + +```typescript +keywords?: string[]; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.appmeta.md b/docs/development/core/public/kibana-plugin-core-public.appmeta.md new file mode 100644 index 000000000000..a2b72f7ec799 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.appmeta.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [AppMeta](./kibana-plugin-core-public.appmeta.md) + +## AppMeta interface + +Input type for meta data for an application. + +Meta fields include `keywords` and `searchDeepLinks` Keywords is an array of string with which to associate the app, must include at least one unique string as an array. `searchDeepLinks` is an array of links that represent secondary in-app locations for the app. + +Signature: + +```typescript +export interface AppMeta +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [keywords](./kibana-plugin-core-public.appmeta.keywords.md) | string[] | Keywords to represent this application | +| [searchDeepLinks](./kibana-plugin-core-public.appmeta.searchdeeplinks.md) | AppSearchDeepLink[] | Array of links that represent secondary in-app locations for the app. | + diff --git a/docs/development/core/public/kibana-plugin-core-public.appmeta.searchdeeplinks.md b/docs/development/core/public/kibana-plugin-core-public.appmeta.searchdeeplinks.md new file mode 100644 index 000000000000..7ec0bbaa4b41 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.appmeta.searchdeeplinks.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [AppMeta](./kibana-plugin-core-public.appmeta.md) > [searchDeepLinks](./kibana-plugin-core-public.appmeta.searchdeeplinks.md) + +## AppMeta.searchDeepLinks property + +Array of links that represent secondary in-app locations for the app. + +Signature: + +```typescript +searchDeepLinks?: AppSearchDeepLink[]; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.appsearchdeeplink.md b/docs/development/core/public/kibana-plugin-core-public.appsearchdeeplink.md index 7e5ccf7d06ed..29aad675fb10 100644 --- a/docs/development/core/public/kibana-plugin-core-public.appsearchdeeplink.md +++ b/docs/development/core/public/kibana-plugin-core-public.appsearchdeeplink.md @@ -17,8 +17,10 @@ export declare type AppSearchDeepLink = { } & ({ path: string; searchDeepLinks?: AppSearchDeepLink[]; + keywords?: string[]; } | { path?: string; searchDeepLinks: AppSearchDeepLink[]; + keywords?: string[]; }); ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.appupdatablefields.md b/docs/development/core/public/kibana-plugin-core-public.appupdatablefields.md index b6f404c3d11a..55672d9339f6 100644 --- a/docs/development/core/public/kibana-plugin-core-public.appupdatablefields.md +++ b/docs/development/core/public/kibana-plugin-core-public.appupdatablefields.md @@ -9,5 +9,5 @@ Defines the list of fields that can be updated via an [AppUpdater](./kibana-plug Signature: ```typescript -export declare type AppUpdatableFields = Pick; +export declare type AppUpdatableFields = Pick; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index da1937705449..7f671d9edcd8 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -37,6 +37,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AppLeaveDefaultAction](./kibana-plugin-core-public.appleavedefaultaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-core-public.appleavehandler.md) to execute the default behaviour when leaving the application.See | | [ApplicationSetup](./kibana-plugin-core-public.applicationsetup.md) | | | [ApplicationStart](./kibana-plugin-core-public.applicationstart.md) | | +| [AppMeta](./kibana-plugin-core-public.appmeta.md) | Input type for meta data for an application.Meta fields include keywords and searchDeepLinks Keywords is an array of string with which to associate the app, must include at least one unique string as an array. searchDeepLinks is an array of links that represent secondary in-app locations for the app. | | [AppMountContext](./kibana-plugin-core-public.appmountcontext.md) | The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md). | | [AppMountParameters](./kibana-plugin-core-public.appmountparameters.md) | | | [Capabilities](./kibana-plugin-core-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | @@ -164,6 +165,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PluginInitializer](./kibana-plugin-core-public.plugininitializer.md) | The plugin export at the root of a plugin's public directory should conform to this interface. | | [PluginOpaqueId](./kibana-plugin-core-public.pluginopaqueid.md) | | | [PublicAppInfo](./kibana-plugin-core-public.publicappinfo.md) | Public information about a registered [application](./kibana-plugin-core-public.app.md) | +| [PublicAppMetaInfo](./kibana-plugin-core-public.publicappmetainfo.md) | Public information about a registered app's [keywords](./kibana-plugin-core-public.appmeta.md) | | [PublicAppSearchDeepLinkInfo](./kibana-plugin-core-public.publicappsearchdeeplinkinfo.md) | Public information about a registered app's [searchDeepLinks](./kibana-plugin-core-public.appsearchdeeplink.md) | | [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. | | [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value | diff --git a/docs/development/core/public/kibana-plugin-core-public.publicappinfo.md b/docs/development/core/public/kibana-plugin-core-public.publicappinfo.md index d56b0ac58cd9..9f45a06935fe 100644 --- a/docs/development/core/public/kibana-plugin-core-public.publicappinfo.md +++ b/docs/development/core/public/kibana-plugin-core-public.publicappinfo.md @@ -9,10 +9,10 @@ Public information about a registered [application](./kibana-plugin-core-public. Signature: ```typescript -export declare type PublicAppInfo = Omit & { +export declare type PublicAppInfo = Omit & { status: AppStatus; navLinkStatus: AppNavLinkStatus; appRoute: string; - searchDeepLinks: PublicAppSearchDeepLinkInfo[]; + meta: PublicAppMetaInfo; }; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.publicappmetainfo.md b/docs/development/core/public/kibana-plugin-core-public.publicappmetainfo.md new file mode 100644 index 000000000000..3ef0460aec46 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.publicappmetainfo.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [PublicAppMetaInfo](./kibana-plugin-core-public.publicappmetainfo.md) + +## PublicAppMetaInfo type + +Public information about a registered app's [keywords](./kibana-plugin-core-public.appmeta.md) + +Signature: + +```typescript +export declare type PublicAppMetaInfo = Omit & { + keywords: string[]; + searchDeepLinks: PublicAppSearchDeepLinkInfo[]; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.publicappsearchdeeplinkinfo.md b/docs/development/core/public/kibana-plugin-core-public.publicappsearchdeeplinkinfo.md index 9814f0408d04..e88cdb7d55ed 100644 --- a/docs/development/core/public/kibana-plugin-core-public.publicappsearchdeeplinkinfo.md +++ b/docs/development/core/public/kibana-plugin-core-public.publicappsearchdeeplinkinfo.md @@ -9,7 +9,8 @@ Public information about a registered app's [searchDeepLinks](./kibana-plugin-co Signature: ```typescript -export declare type PublicAppSearchDeepLinkInfo = Omit & { +export declare type PublicAppSearchDeepLinkInfo = Omit & { searchDeepLinks: PublicAppSearchDeepLinkInfo[]; + keywords: string[]; }; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md index 40fc1a8e05a6..7c53356615ee 100644 --- a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md @@ -9,7 +9,7 @@ Signature: ```typescript -export interface LegacyElasticsearchError extends Boom +export interface LegacyElasticsearchError extends Boom.Boom ``` ## Properties diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.apply_filter_trigger.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.apply_filter_trigger.md new file mode 100644 index 000000000000..aaed18b3b889 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.apply_filter_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [APPLY\_FILTER\_TRIGGER](./kibana-plugin-plugins-data-public.apply_filter_trigger.md) + +## APPLY\_FILTER\_TRIGGER variable + +Signature: + +```typescript +APPLY_FILTER_TRIGGER = "FILTER_TRIGGER" +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md index 027ae4209b77..dbeeeb9979aa 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md @@ -7,5 +7,5 @@ Signature: ```typescript -embeddable?: IEmbeddable; +embeddable?: unknown; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md index 62817cd0a1e3..2f844b684464 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md @@ -14,7 +14,7 @@ export interface ApplyGlobalFilterActionContext | Property | Type | Description | | --- | --- | --- | -| [embeddable](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md) | IEmbeddable | | +| [embeddable](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md) | unknown | | | [filters](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.filters.md) | Filter[] | | | [timeFieldName](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.timefieldname.md) | string | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.allownoindex.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.allownoindex.md new file mode 100644 index 000000000000..5e397d11b0a8 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.allownoindex.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [allowNoIndex](./kibana-plugin-plugins-data-public.indexpattern.allownoindex.md) + +## IndexPattern.allowNoIndex property + +prevents errors when index pattern exists before indices + +Signature: + +```typescript +readonly allowNoIndex: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getassavedobjectbody.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getassavedobjectbody.md index a37034100096..b318427012c0 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getassavedobjectbody.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getassavedobjectbody.md @@ -19,6 +19,7 @@ getAsSavedObjectBody(): { fieldFormatMap: string | undefined; type: string | undefined; typeMeta: string | undefined; + allowNoIndex: true | undefined; }; ``` Returns: @@ -33,5 +34,6 @@ getAsSavedObjectBody(): { fieldFormatMap: string | undefined; type: string | undefined; typeMeta: string | undefined; + allowNoIndex: true | undefined; }` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md index 179148265e68..b640ef1b8960 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md @@ -20,6 +20,7 @@ export declare class IndexPattern implements IIndexPattern | Property | Modifiers | Type | Description | | --- | --- | --- | --- | +| [allowNoIndex](./kibana-plugin-plugins-data-public.indexpattern.allownoindex.md) | | boolean | prevents errors when index pattern exists before indices | | [deleteFieldFormat](./kibana-plugin-plugins-data-public.indexpattern.deletefieldformat.md) | | (fieldName: string) => void | | | [fieldAttrs](./kibana-plugin-plugins-data-public.indexpattern.fieldattrs.md) | | FieldAttrs | | | [fieldFormatMap](./kibana-plugin-plugins-data-public.indexpattern.fieldformatmap.md) | | Record<string, any> | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.allownoindex.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.allownoindex.md new file mode 100644 index 000000000000..9438f3819449 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.allownoindex.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternAttributes](./kibana-plugin-plugins-data-public.indexpatternattributes.md) > [allowNoIndex](./kibana-plugin-plugins-data-public.indexpatternattributes.allownoindex.md) + +## IndexPatternAttributes.allowNoIndex property + +prevents errors when index pattern exists before indices + +Signature: + +```typescript +allowNoIndex?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.md index c5ea38278e82..1bbede565894 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.md @@ -14,6 +14,7 @@ export interface IndexPatternAttributes | Property | Type | Description | | --- | --- | --- | +| [allowNoIndex](./kibana-plugin-plugins-data-public.indexpatternattributes.allownoindex.md) | boolean | prevents errors when index pattern exists before indices | | [fieldAttrs](./kibana-plugin-plugins-data-public.indexpatternattributes.fieldattrs.md) | string | | | [fieldFormatMap](./kibana-plugin-plugins-data-public.indexpatternattributes.fieldformatmap.md) | string | | | [fields](./kibana-plugin-plugins-data-public.indexpatternattributes.fields.md) | string | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.allownoindex.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.allownoindex.md new file mode 100644 index 000000000000..50adef826869 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.allownoindex.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [allowNoIndex](./kibana-plugin-plugins-data-public.indexpatternspec.allownoindex.md) + +## IndexPatternSpec.allowNoIndex property + +Signature: + +```typescript +allowNoIndex?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.md index 06917fcac1b4..9357ad7d5077 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.md @@ -14,6 +14,7 @@ export interface IndexPatternSpec | Property | Type | Description | | --- | --- | --- | +| [allowNoIndex](./kibana-plugin-plugins-data-public.indexpatternspec.allownoindex.md) | boolean | | | [fieldAttrs](./kibana-plugin-plugins-data-public.indexpatternspec.fieldattrs.md) | FieldAttrs | | | [fieldFormats](./kibana-plugin-plugins-data-public.indexpatternspec.fieldformats.md) | Record<string, SerializedFieldFormat> | | | [fields](./kibana-plugin-plugins-data-public.indexpatternspec.fields.md) | IndexPatternFieldMap | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index 8de3821161ab..2040043d4351 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -102,6 +102,7 @@ | [ACTION\_GLOBAL\_APPLY\_FILTER](./kibana-plugin-plugins-data-public.action_global_apply_filter.md) | | | [AggGroupLabels](./kibana-plugin-plugins-data-public.agggrouplabels.md) | | | [AggGroupNames](./kibana-plugin-plugins-data-public.agggroupnames.md) | | +| [APPLY\_FILTER\_TRIGGER](./kibana-plugin-plugins-data-public.apply_filter_trigger.md) | | | [baseFormattersPublic](./kibana-plugin-plugins-data-public.baseformatterspublic.md) | | | [castEsToKbnFieldTypeName](./kibana-plugin-plugins-data-public.castestokbnfieldtypename.md) | Get the KbnFieldType name for an esType string | | [connectToQueryState](./kibana-plugin-plugins-data-public.connecttoquerystate.md) | Helper to setup two-way syncing of global data and a state container | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.allownoindex.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.allownoindex.md new file mode 100644 index 000000000000..fe7bec70196c --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.allownoindex.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [allowNoIndex](./kibana-plugin-plugins-data-server.indexpattern.allownoindex.md) + +## IndexPattern.allowNoIndex property + +prevents errors when index pattern exists before indices + +Signature: + +```typescript +readonly allowNoIndex: boolean; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getassavedobjectbody.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getassavedobjectbody.md index 274a475872b0..7d70af4b535f 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getassavedobjectbody.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getassavedobjectbody.md @@ -19,6 +19,7 @@ getAsSavedObjectBody(): { fieldFormatMap: string | undefined; type: string | undefined; typeMeta: string | undefined; + allowNoIndex: true | undefined; }; ``` Returns: @@ -33,5 +34,6 @@ getAsSavedObjectBody(): { fieldFormatMap: string | undefined; type: string | undefined; typeMeta: string | undefined; + allowNoIndex: true | undefined; }` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.md index b2cb217fecaa..54f020e57cf4 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.md @@ -20,6 +20,7 @@ export declare class IndexPattern implements IIndexPattern | Property | Modifiers | Type | Description | | --- | --- | --- | --- | +| [allowNoIndex](./kibana-plugin-plugins-data-server.indexpattern.allownoindex.md) | | boolean | prevents errors when index pattern exists before indices | | [deleteFieldFormat](./kibana-plugin-plugins-data-server.indexpattern.deletefieldformat.md) | | (fieldName: string) => void | | | [fieldAttrs](./kibana-plugin-plugins-data-server.indexpattern.fieldattrs.md) | | FieldAttrs | | | [fieldFormatMap](./kibana-plugin-plugins-data-server.indexpattern.fieldformatmap.md) | | Record<string, any> | | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.allownoindex.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.allownoindex.md new file mode 100644 index 000000000000..1255a6fe9f0c --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.allownoindex.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternAttributes](./kibana-plugin-plugins-data-server.indexpatternattributes.md) > [allowNoIndex](./kibana-plugin-plugins-data-server.indexpatternattributes.allownoindex.md) + +## IndexPatternAttributes.allowNoIndex property + +prevents errors when index pattern exists before indices + +Signature: + +```typescript +allowNoIndex?: boolean; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.md index 6559b4d7110b..b9b9f955c7ab 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.md @@ -14,6 +14,7 @@ export interface IndexPatternAttributes | Property | Type | Description | | --- | --- | --- | +| [allowNoIndex](./kibana-plugin-plugins-data-server.indexpatternattributes.allownoindex.md) | boolean | prevents errors when index pattern exists before indices | | [fieldAttrs](./kibana-plugin-plugins-data-server.indexpatternattributes.fieldattrs.md) | string | | | [fieldFormatMap](./kibana-plugin-plugins-data-server.indexpatternattributes.fieldformatmap.md) | string | | | [fields](./kibana-plugin-plugins-data-server.indexpatternattributes.fields.md) | string | | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.setup.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.setup.md index b90018c3d9cd..bd90f23b4ab5 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.setup.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.setup.md @@ -11,7 +11,7 @@ setup(core: CoreSetup, { bfetch, e __enhance: (enhancements: DataEnhancements) => void; search: ISearchSetup; fieldFormats: { - register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number; + register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number; }; }; ``` @@ -29,7 +29,7 @@ setup(core: CoreSetup, { bfetch, e __enhance: (enhancements: DataEnhancements) => void; search: ISearchSetup; fieldFormats: { - register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number; + register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number; }; }` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md index 8a3dbe5a6350..88f85eb7a7d0 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md @@ -12,7 +12,7 @@ start(core: CoreStart): { fieldFormatServiceFactory: (uiSettings: import("src/core/server").IUiSettingsClient) => Promise; }; indexPatterns: { - indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise; }; search: ISearchStart>; }; @@ -31,7 +31,7 @@ start(core: CoreStart): { fieldFormatServiceFactory: (uiSettings: import("src/core/server").IUiSettingsClient) => Promise; }; indexPatterns: { - indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise; }; search: ISearchStart>; }` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md index 06e51958a2d1..92926d10a543 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md @@ -7,5 +7,5 @@ Signature: ```typescript -embeddable: IEmbeddable; +embeddable: T; ``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.md index a2c2d9245eab..753a3ff2ec6e 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.md @@ -7,12 +7,12 @@ Signature: ```typescript -export interface EmbeddableContext +export interface EmbeddableContext ``` ## Properties | Property | Type | Description | | --- | --- | --- | -| [embeddable](./kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md) | IEmbeddable | | +| [embeddable](./kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md) | T | | diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinput.md index f36f7b4ee77a..07ede291e33d 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinput.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinput.md @@ -16,9 +16,7 @@ export declare type EmbeddableInput = { enhancements?: SerializableState; disabledActions?: string[]; disableTriggers?: boolean; - timeRange?: TimeRange; - query?: Query; - filters?: Filter[]; searchSessionId?: string; + syncColors?: boolean; }; ``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md deleted file mode 100644 index d3a62657372a..000000000000 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableSetupDependencies](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md) > [data](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md) - -## EmbeddableSetupDependencies.data property - -Signature: - -```typescript -data: DataPublicPluginSetup; -``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md index fdd31ca75be2..957e3f279ff6 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md @@ -14,6 +14,5 @@ export interface EmbeddableSetupDependencies | Property | Type | Description | | --- | --- | --- | -| [data](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md) | DataPublicPluginSetup | | | [uiActions](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.uiactions.md) | UiActionsSetup | | diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md deleted file mode 100644 index 0595609b11e4..000000000000 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStartDependencies](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md) > [data](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md) - -## EmbeddableStartDependencies.data property - -Signature: - -```typescript -data: DataPublicPluginStart; -``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md index 5a1b5d1e0686..342163ed2e41 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md @@ -14,7 +14,6 @@ export interface EmbeddableStartDependencies | Property | Type | Description | | --- | --- | --- | -| [data](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md) | DataPublicPluginStart | | | [inspector](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.inspector.md) | InspectorStart | | | [uiActions](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.uiactions.md) | UiActionsStart | | diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md index 276499b435e1..77e9c2d00b2d 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md @@ -9,7 +9,7 @@ Constructs a new instance of the `EmbeddableStateTransfer` class Signature: ```typescript -constructor(navigateToApp: ApplicationStart['navigateToApp'], appList?: ReadonlyMap | undefined, customStorage?: Storage); +constructor(navigateToApp: ApplicationStart['navigateToApp'], currentAppId$: ApplicationStart['currentAppId$'], appList?: ReadonlyMap | undefined, customStorage?: Storage); ``` ## Parameters @@ -17,6 +17,7 @@ constructor(navigateToApp: ApplicationStart['navigateToApp'], appList?: Readonly | Parameter | Type | Description | | --- | --- | --- | | navigateToApp | ApplicationStart['navigateToApp'] | | +| currentAppId$ | ApplicationStart['currentAppId$'] | | | appList | ReadonlyMap<string, PublicAppInfo> | undefined | | | customStorage | Storage | | diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.istransferinprogress.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.istransferinprogress.md new file mode 100644 index 000000000000..f00d015f316d --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.istransferinprogress.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) > [isTransferInProgress](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.istransferinprogress.md) + +## EmbeddableStateTransfer.isTransferInProgress property + +Signature: + +```typescript +isTransferInProgress: boolean; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md index 3676b744b8cc..76b6708b93bd 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md @@ -16,13 +16,14 @@ export declare class EmbeddableStateTransfer | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(navigateToApp, appList, customStorage)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md) | | Constructs a new instance of the EmbeddableStateTransfer class | +| [(constructor)(navigateToApp, currentAppId$, appList, customStorage)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md) | | Constructs a new instance of the EmbeddableStateTransfer class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [getAppNameFromId](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getappnamefromid.md) | | (appId: string) => string | undefined | Fetches an internationalized app title when given an appId. | +| [isTransferInProgress](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.istransferinprogress.md) | | boolean | | ## Methods diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iscontextmenutriggercontext.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iscontextmenutriggercontext.md index 62610624655a..2f5966f9ba94 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iscontextmenutriggercontext.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iscontextmenutriggercontext.md @@ -7,5 +7,5 @@ Signature: ```typescript -isContextMenuTriggerContext: (context: unknown) => context is EmbeddableContext +isContextMenuTriggerContext: (context: unknown) => context is EmbeddableContext> ``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md index a6aeba23cd28..b875b1fce428 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md @@ -86,6 +86,8 @@ | [PANEL\_NOTIFICATION\_TRIGGER](./kibana-plugin-plugins-embeddable-public.panel_notification_trigger.md) | | | [panelBadgeTrigger](./kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md) | | | [panelNotificationTrigger](./kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md) | | +| [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-embeddable-public.select_range_trigger.md) | | +| [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-embeddable-public.value_click_trigger.md) | | | [withEmbeddableSubscription](./kibana-plugin-plugins-embeddable-public.withembeddablesubscription.md) | | ## Type Aliases diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md index ce97f79b4beb..add464637535 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md @@ -14,7 +14,7 @@ export declare function openAddPanelFlyout(options: { overlays: OverlayStart; notifications: NotificationsStart; SavedObjectFinder: React.ComponentType; -}): Promise; +}): OverlayRef; ``` ## Parameters @@ -25,5 +25,5 @@ export declare function openAddPanelFlyout(options: { Returns: -`Promise` +`OverlayRef` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.select_range_trigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.select_range_trigger.md new file mode 100644 index 000000000000..175e3fe947a0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.select_range_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-embeddable-public.select_range_trigger.md) + +## SELECT\_RANGE\_TRIGGER variable + +Signature: + +```typescript +SELECT_RANGE_TRIGGER = "SELECT_RANGE_TRIGGER" +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.value_click_trigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.value_click_trigger.md new file mode 100644 index 000000000000..a85be3142d0f --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.value_click_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-embeddable-public.value_click_trigger.md) + +## VALUE\_CLICK\_TRIGGER variable + +Signature: + +```typescript +VALUE_CLICK_TRIGGER = "VALUE_CLICK_TRIGGER" +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md index 1565202e8467..9dfad91c3367 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md @@ -9,7 +9,7 @@ Constructs a new instance of the `ExpressionRenderHandler` class Signature: ```typescript -constructor(element: HTMLElement, { onRenderError, renderMode, hasCompatibleActions, }?: ExpressionRenderHandlerParams); +constructor(element: HTMLElement, { onRenderError, renderMode, syncColors, hasCompatibleActions, }?: ExpressionRenderHandlerParams); ``` ## Parameters @@ -17,5 +17,5 @@ constructor(element: HTMLElement, { onRenderError, renderMode, hasCompatibleActi | Parameter | Type | Description | | --- | --- | --- | | element | HTMLElement | | -| { onRenderError, renderMode, hasCompatibleActions, } | ExpressionRenderHandlerParams | | +| { onRenderError, renderMode, syncColors, hasCompatibleActions, } | ExpressionRenderHandlerParams | | diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.md index d65c06bdaed8..1a7050f3ffd4 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.md @@ -14,7 +14,7 @@ export declare class ExpressionRenderHandler | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(element, { onRenderError, renderMode, hasCompatibleActions, })](./kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md) | | Constructs a new instance of the ExpressionRenderHandler class | +| [(constructor)(element, { onRenderError, renderMode, syncColors, hasCompatibleActions, })](./kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md) | | Constructs a new instance of the ExpressionRenderHandler class | ## Properties diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md index 22a73fff039e..4ef1225ae0d7 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md @@ -25,6 +25,7 @@ export interface IExpressionLoaderParams | [renderMode](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.rendermode.md) | RenderMode | | | [searchContext](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md) | SerializableState | | | [searchSessionId](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchsessionid.md) | string | | +| [syncColors](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.synccolors.md) | boolean | | | [uiState](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.uistate.md) | unknown | | | [variables](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.variables.md) | Record<string, any> | | diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.synccolors.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.synccolors.md new file mode 100644 index 000000000000..619f54ad88ef --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.synccolors.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [syncColors](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.synccolors.md) + +## IExpressionLoaderParams.syncColors property + +Signature: + +```typescript +syncColors?: boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.issynccolorsenabled.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.issynccolorsenabled.md new file mode 100644 index 000000000000..6cdc796bf464 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.issynccolorsenabled.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) > [isSyncColorsEnabled](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.issynccolorsenabled.md) + +## IInterpreterRenderHandlers.isSyncColorsEnabled property + +Signature: + +```typescript +isSyncColorsEnabled: () => boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md index 931e474a4100..0b39a9b4b3ea 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md @@ -18,8 +18,9 @@ export interface IInterpreterRenderHandlers | [event](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.event.md) | (event: any) => void | | | [getRenderMode](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.getrendermode.md) | () => RenderMode | | | [hasCompatibleActions](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.hascompatibleactions.md) | (event: any) => Promise<boolean> | | +| [isSyncColorsEnabled](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.issynccolorsenabled.md) | () => boolean | | | [onDestroy](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.ondestroy.md) | (fn: () => void) => void | | | [reload](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.reload.md) | () => void | | -| [uiState](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md) | PersistedState | | +| [uiState](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md) | unknown | This uiState interface is actually PersistedState from the visualizations plugin, but expressions cannot know about vis or it creates a mess of circular dependencies. Downstream consumers of the uiState handler will need to cast for now. | | [update](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.update.md) | (params: any) => void | | diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md index 8d74c8e555fe..461bf861d4d5 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md @@ -4,8 +4,10 @@ ## IInterpreterRenderHandlers.uiState property +This uiState interface is actually `PersistedState` from the visualizations plugin, but expressions cannot know about vis or it creates a mess of circular dependencies. Downstream consumers of the uiState handler will need to cast for now. + Signature: ```typescript -uiState?: PersistedState; +uiState?: unknown; ``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.issynccolorsenabled.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.issynccolorsenabled.md new file mode 100644 index 000000000000..71a7e020e65a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.issynccolorsenabled.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) > [isSyncColorsEnabled](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.issynccolorsenabled.md) + +## IInterpreterRenderHandlers.isSyncColorsEnabled property + +Signature: + +```typescript +isSyncColorsEnabled: () => boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md index 273703cacca0..831c9023c7e4 100644 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md @@ -18,8 +18,9 @@ export interface IInterpreterRenderHandlers | [event](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.event.md) | (event: any) => void | | | [getRenderMode](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.getrendermode.md) | () => RenderMode | | | [hasCompatibleActions](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.hascompatibleactions.md) | (event: any) => Promise<boolean> | | +| [isSyncColorsEnabled](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.issynccolorsenabled.md) | () => boolean | | | [onDestroy](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.ondestroy.md) | (fn: () => void) => void | | | [reload](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.reload.md) | () => void | | -| [uiState](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md) | PersistedState | | +| [uiState](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md) | unknown | This uiState interface is actually PersistedState from the visualizations plugin, but expressions cannot know about vis or it creates a mess of circular dependencies. Downstream consumers of the uiState handler will need to cast for now. | | [update](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.update.md) | (params: any) => void | | diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md index b09433c6454a..ca1c8eec8c2f 100644 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md @@ -4,8 +4,10 @@ ## IInterpreterRenderHandlers.uiState property +This uiState interface is actually `PersistedState` from the visualizations plugin, but expressions cannot know about vis or it creates a mess of circular dependencies. Downstream consumers of the uiState handler will need to cast for now. + Signature: ```typescript -uiState?: PersistedState; +uiState?: unknown; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md deleted file mode 100644 index 94e66bf404f5..000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [APPLY\_FILTER\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md) - -## APPLY\_FILTER\_TRIGGER variable - -Signature: - -```typescript -APPLY_FILTER_TRIGGER = "FILTER_TRIGGER" -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md deleted file mode 100644 index e1fb6d342457..000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [applyFilterTrigger](./kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md) - -## applyFilterTrigger variable - -Signature: - -```typescript -applyFilterTrigger: Trigger<'FILTER_TRIGGER'> -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md index fd1ea7df4fb7..76e347bddd16 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md @@ -41,14 +41,8 @@ | [ACTION\_VISUALIZE\_FIELD](./kibana-plugin-plugins-ui_actions-public.action_visualize_field.md) | | | [ACTION\_VISUALIZE\_GEO\_FIELD](./kibana-plugin-plugins-ui_actions-public.action_visualize_geo_field.md) | | | [ACTION\_VISUALIZE\_LENS\_FIELD](./kibana-plugin-plugins-ui_actions-public.action_visualize_lens_field.md) | | -| [APPLY\_FILTER\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md) | | -| [applyFilterTrigger](./kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md) | | | [ROW\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.row_click_trigger.md) | | | [rowClickTrigger](./kibana-plugin-plugins-ui_actions-public.rowclicktrigger.md) | | -| [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.select_range_trigger.md) | | -| [selectRangeTrigger](./kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md) | | -| [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.value_click_trigger.md) | | -| [valueClickTrigger](./kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md) | | | [VISUALIZE\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.visualize_field_trigger.md) | | | [VISUALIZE\_GEO\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.visualize_geo_field_trigger.md) | | | [visualizeFieldTrigger](./kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md) | | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclickcontext.embeddable.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclickcontext.embeddable.md index e8baf44ff9cb..a75637e8ea9d 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclickcontext.embeddable.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclickcontext.embeddable.md @@ -7,5 +7,5 @@ Signature: ```typescript -embeddable?: IEmbeddable; +embeddable?: unknown; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclickcontext.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclickcontext.md index 74b55d85f10e..b69734cfc323 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclickcontext.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclickcontext.md @@ -15,5 +15,5 @@ export interface RowClickContext | Property | Type | Description | | --- | --- | --- | | [data](./kibana-plugin-plugins-ui_actions-public.rowclickcontext.data.md) | {
rowIndex: number;
table: Datatable;
columns?: string[];
} | | -| [embeddable](./kibana-plugin-plugins-ui_actions-public.rowclickcontext.embeddable.md) | IEmbeddable | | +| [embeddable](./kibana-plugin-plugins-ui_actions-public.rowclickcontext.embeddable.md) | unknown | | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.select_range_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.select_range_trigger.md deleted file mode 100644 index fd784ff17fa8..000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.select_range_trigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.select_range_trigger.md) - -## SELECT\_RANGE\_TRIGGER variable - -Signature: - -```typescript -SELECT_RANGE_TRIGGER = "SELECT_RANGE_TRIGGER" -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md deleted file mode 100644 index 0d9fa2d83ee5..000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [selectRangeTrigger](./kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md) - -## selectRangeTrigger variable - -Signature: - -```typescript -selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md index 426f17f9a035..5603c852ad39 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md @@ -4,7 +4,7 @@ ## Trigger.id property -Unique name of the trigger as identified in `ui_actions` plugin trigger registry, such as "SELECT\_RANGE\_TRIGGER" or "VALUE\_CLICK\_TRIGGER". +Unique name of the trigger as identified in `ui_actions` plugin trigger registry. Signature: diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md index b69bba892f47..ed76cfea9768 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md @@ -21,6 +21,6 @@ export interface Trigger | Property | Type | Description | | --- | --- | --- | | [description](./kibana-plugin-plugins-ui_actions-public.trigger.description.md) | string | A longer user friendly description of the trigger. | -| [id](./kibana-plugin-plugins-ui_actions-public.trigger.id.md) | ID | Unique name of the trigger as identified in ui_actions plugin trigger registry, such as "SELECT\_RANGE\_TRIGGER" or "VALUE\_CLICK\_TRIGGER". | +| [id](./kibana-plugin-plugins-ui_actions-public.trigger.id.md) | ID | Unique name of the trigger as identified in ui_actions plugin trigger registry. | | [title](./kibana-plugin-plugins-ui_actions-public.trigger.title.md) | string | User friendly name of the trigger. | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md deleted file mode 100644 index 0ccf8aa3d741..000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [FILTER\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md) - -## TriggerContextMapping.FILTER\_TRIGGER property - -Signature: - -```typescript -[APPLY_FILTER_TRIGGER]: ApplyGlobalFilterActionContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md index 2f0d22cf6dd7..da7a7a8bfe64 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md @@ -15,10 +15,7 @@ export interface TriggerContextMapping | Property | Type | Description | | --- | --- | --- | | [""](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md) | TriggerContext | | -| [FILTER\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md) | ApplyGlobalFilterActionContext | | | [ROW\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.row_click_trigger.md) | RowClickContext | | -| [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md) | RangeSelectContext | | -| [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md) | ValueClickContext | | | [VISUALIZE\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md) | VisualizeFieldContext | | | [VISUALIZE\_GEO\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md) | VisualizeFieldContext | | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md deleted file mode 100644 index c5ef6843390b..000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md) - -## TriggerContextMapping.SELECT\_RANGE\_TRIGGER property - -Signature: - -```typescript -[SELECT_RANGE_TRIGGER]: RangeSelectContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md deleted file mode 100644 index 129144a66cee..000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md) - -## TriggerContextMapping.VALUE\_CLICK\_TRIGGER property - -Signature: - -```typescript -[VALUE_CLICK_TRIGGER]: ValueClickContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md index ca999322b7a5..f29d487d774e 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md @@ -11,5 +11,5 @@ Signature: ```typescript -readonly addTriggerAction: (triggerId: T, action: ActionDefinition | Action) => void; +readonly addTriggerAction: (triggerId: T, action: ActionDefinition | Action) => void; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md index e95e7e1eb38b..1ebb30c49c0b 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly attachAction: (triggerId: T, actionId: string) => void; +readonly attachAction: (triggerId: T, actionId: string) => void; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md index 8e7fb8b8bbf2..b20f08520c43 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md @@ -12,5 +12,5 @@ Signature: ```typescript -readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise; +readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md index d540de763744..300c46a47c47 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">; +readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md index b996620686a2..95b737a8d6ca 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getTrigger: (triggerId: T) => TriggerContract; +readonly getTrigger: (triggerId: T) => TriggerContract; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md index f94b34ecc2d9..27c1b1eb48f1 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getTriggerActions: (triggerId: T) => Action[]; +readonly getTriggerActions: (triggerId: T) => Action[]; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md index dff958608ef9..edb7d2d3a155 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; +readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md index e35eb503ab62..4fe8431770de 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md @@ -21,19 +21,19 @@ export declare class UiActionsService | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [actions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md) | | ActionRegistry | | -| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "ROW_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, action: ActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">) => void | addTriggerAction is similar to attachAction as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.addTriggerAction also infers better typing of the action argument. | -| [attachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "ROW_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, actionId: string) => void | | +| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T, action: ActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">) => void | addTriggerAction is similar to attachAction as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.addTriggerAction also infers better typing of the action argument. | +| [attachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T, actionId: string) => void | | | [clear](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md) | | () => void | Removes all registered triggers and actions. | | [detachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md) | | (triggerId: TriggerId, actionId: string) => void | | -| [executeTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "ROW_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContext<T>) => Promise<void> | | +| [executeTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T, context: TriggerContext<T>) => Promise<void> | | | [executionService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executionservice.md) | | UiActionsExecutionService | | | [fork](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.fork.md) | | () => UiActionsService | "Fork" a separate instance of UiActionsService that inherits all existing triggers and actions, but going forward all new triggers and actions added to this instance of UiActionsService are only available within this instance. | -| [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) | | <T extends ActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV"> | | -| [getTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "ROW_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => TriggerContract<T> | | -| [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "ROW_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">[] | | -| [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "ROW_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">[]> | | +| [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) | | <T extends ActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel"> | | +| [getTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T) => TriggerContract<T> | | +| [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">[] | | +| [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">[]> | | | [hasAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.hasaction.md) | | (actionId: string) => boolean | | -| [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) | | <A extends ActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV"> | | +| [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) | | <A extends ActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel"> | | | [registerTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registertrigger.md) | | (trigger: Trigger) => void | | | [triggers](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggers.md) | | TriggerRegistry | | | [triggerToActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggertoactions.md) | | TriggerToActionsRegistry | | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md index 6f03777e1455..dee5f75f7c07 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">; +readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.value_click_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.value_click_trigger.md deleted file mode 100644 index bd8d4dc50b8f..000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.value_click_trigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.value_click_trigger.md) - -## VALUE\_CLICK\_TRIGGER variable - -Signature: - -```typescript -VALUE_CLICK_TRIGGER = "VALUE_CLICK_TRIGGER" -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md deleted file mode 100644 index 5c4fc284d83b..000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [valueClickTrigger](./kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md) - -## valueClickTrigger variable - -Signature: - -```typescript -valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'> -``` diff --git a/docs/discover/search.asciidoc b/docs/discover/search.asciidoc index 75c6fddb484a..45f0df5bd773 100644 --- a/docs/discover/search.asciidoc +++ b/docs/discover/search.asciidoc @@ -74,7 +74,7 @@ status codes, you could enter `status:[400 TO 499]`. codes and have an extension of `php` or `html`, you could enter `status:[400 TO 499] AND (extension:php OR extension:html)`. -IMPORTANT: When you use the Lucene Query Syntax in the *KQL* search bar, {kib} is unable to search on nested objects and perform aggregations across fields that contain nested objects. +IMPORTANT: When you use the Lucene Query Syntax in the *KQL* search bar, {kib} is unable to search on nested objects and perform aggregations across fields that contain nested objects. Using `include_in_parent` or `copy_to` as a workaround can cause {kib} to fail. For more detailed information about the Lucene query syntax, see the @@ -107,7 +107,8 @@ To save the current search: . Click *Save* in the Kibana toolbar. . Enter a name for the search and click *Save*. -To import, export, and delete saved searches, open the main menu, then click *Stack Management > Saved Ojbects*. +To import, export, and delete saved searches, open the main menu, +then click *Stack Management > Saved Objects*. ==== Open a saved search To load a saved search into Discover: diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 6244a43b54f7..7e7c8953fd52 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -262,6 +262,10 @@ Hides the "Time" column in *Discover* and in all saved searches on dashboards. Highlights results in *Discover* and saved searches on dashboards. Highlighting slows requests when working on big documents. +[[doctable-legacy]]`doc_table:legacy`:: +Control the way the Discover's table looks and works. Set this property to `true` to revert to the legacy implementation. + + [float] [[kibana-ml-settings]] ==== Machine learning @@ -453,6 +457,9 @@ of buckets to try to represent. ==== Visualization [horizontal] +[[visualization-visualize-chartslibrary]]`visualization:visualize:legacyChartsLibrary`:: +Enables legacy charts library for area, line and bar charts in visualize. Currently, only legacy charts library supports split chart aggregation. + [[visualization-colormapping]]`visualization:colorMapping`:: **This setting is deprecated and will not be supported as of 8.0.** Maps values to specific colors in *Visualize* charts and *TSVB*. This setting does not apply to *Lens*. diff --git a/docs/user/alerting/alerting-getting-started.asciidoc b/docs/user/alerting/alerting-getting-started.asciidoc index 4eeecad07934..cb2b9b19a072 100644 --- a/docs/user/alerting/alerting-getting-started.asciidoc +++ b/docs/user/alerting/alerting-getting-started.asciidoc @@ -123,14 +123,15 @@ image::images/alert-concepts-connectors.svg[Connectors provide a central place t [float] === Summary -An _alert_ consists of conditions, _actions_, and a schedule. When conditions are met, _alert instances_ are created that render _actions_ and invoke them. To make action setup and update easier, actions refer to _connectors_ that centralize the information used to connect with {kib} services and third-party integrations. +An _alert_ consists of conditions, _actions_, and a schedule. When conditions are met, _alert instances_ are created that render _actions_ and invoke them. To make action setup and update easier, actions refer to _connectors_ that centralize the information used to connect with {kib} services and third-party integrations. The following example ties these concepts together: image::images/alert-concepts-summary.svg[Alerts, actions, alert instances and connectors work together to convert detection into action] -* *Alert*: a specification of the conditions to be detected, the schedule for detection, and the response when detection occurs. -* *Action*: the response to a detected condition defined in the alert. Typically actions specify a service or third party integration along with alert details that will be sent to it. -* *Alert instance*: state tracked by {kib} for every occurrence of a detected condition. Actions as well as controls like muting and re-notification are controlled at the instance level. -* *Connector*: centralized configurations for services and third party integration that are referenced by actions. +. Anytime an *alert*'s conditions are met, an *alert instance* is created. This example checks for servers with average CPU > 0.9. Three servers meet the condition, so three instances are created. +. Instances create *actions* as long as they are not muted or throttled. When actions are created, the template that was setup in the alert is filled with actual values. In this example three actions are created, and the template string {{server}} is replaced with the server name for each instance. +. {kib} invokes the actions, sending them to a 3rd party *integration* like an email service. +. If the 3rd party integration has connection parameters or credentials, {kib} will fetch these from the *connector* referenced in the action. + [float] [[alerting-concepts-differences]] diff --git a/docs/user/alerting/images/alert-concepts-summary.svg b/docs/user/alerting/images/alert-concepts-summary.svg index 0d63601c0693..0aed3bf22375 100644 --- a/docs/user/alerting/images/alert-concepts-summary.svg +++ b/docs/user/alerting/images/alert-concepts-summary.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/user/dashboard/edit-dashboards.asciidoc b/docs/user/dashboard/edit-dashboards.asciidoc index 7b712b355b31..d7f7dc2d65c8 100644 --- a/docs/user/dashboard/edit-dashboards.asciidoc +++ b/docs/user/dashboard/edit-dashboards.asciidoc @@ -81,6 +81,21 @@ Put the dashboard in *Edit* mode, then use the following options: * To delete, open the panel menu, then select *Delete from dashboard*. When you delete a panel from the dashboard, the visualization or saved search from the panel is still available in Kibana. +[float] +[[sync-colors]] +=== Synchronize colors + +By default, dashboard panels that share a non-gradient based color palette will synchronize their color assignment to improve readability. +Color assignment is based on the series name, and the total number of colors is based on the number of unique series names. + +The color synchronizing logic can make the dashboard less readable when there are too many unique series names. It is possible to disable the synchronization behavior: + +. Put the dashboard in *Edit* mode. + +. Click the "Options" button in the top navigation bar. + +. Disable "Sync color palettes across panels". + [float] [[clone-panels]] === Clone panels diff --git a/docs/user/security/audit-logging.asciidoc b/docs/user/security/audit-logging.asciidoc index 4b3512ae3056..acb0f94cf878 100644 --- a/docs/user/security/audit-logging.asciidoc +++ b/docs/user/security/audit-logging.asciidoc @@ -47,9 +47,11 @@ For information on how to configure `xpack.security.audit.appender`, refer to Refer to the table of events that can be logged for auditing purposes. -Each event is broken down into `category`, `type`, `action` and `outcome` fields +Each event is broken down into <>, <>, <> and <> fields to make it easy to filter, query and aggregate the resulting logs. +Refer to <> for a table of fields that get logged with audit event. + [NOTE] ============================================================================ To ensure that a record of every operation is persisted even in case of an @@ -58,7 +60,6 @@ authorization checks have passed, but before the response from {es} is received. Refer to the corresponding {es} logs for potential write errors. ============================================================================ - [cols="3*<"] |====== 3+a| @@ -89,9 +90,12 @@ Refer to the corresponding {es} logs for potential write errors. | `failure` | User is not authorized to create a connector. .2+| `alert_create` -| `unknown` | User is creating an alert rule. -| `failure` | User is not authorized to create an alert rule. +| `unknown` | User is creating an alert. +| `failure` | User is not authorized to create an alert. +.2+| `space_create` +| `unknown` | User is creating a space. +| `failure` | User is not authorized to create a space. 3+a| ====== Type: change @@ -121,28 +125,28 @@ Refer to the corresponding {es} logs for potential write errors. | `failure` | User is not authorized to update a connector. .2+| `alert_update` -| `unknown` | User is updating an alert rule. -| `failure` | User is not authorized to update an alert rule. +| `unknown` | User is updating an alert. +| `failure` | User is not authorized to update an alert. .2+| `alert_update_api_key` -| `unknown` | User is updating the API key of an alert rule. -| `failure` | User is not authorized to update the API key of an alert rule. +| `unknown` | User is updating the API key of an alert. +| `failure` | User is not authorized to update the API key of an alert. .2+| `alert_enable` -| `unknown` | User is enabling an alert rule. -| `failure` | User is not authorized to enable an alert rule. +| `unknown` | User is enabling an alert. +| `failure` | User is not authorized to enable an alert. .2+| `alert_disable` -| `unknown` | User is disabling an alert rule. -| `failure` | User is not authorized to disable an alert rule. +| `unknown` | User is disabling an alert. +| `failure` | User is not authorized to disable an alert. .2+| `alert_mute` -| `unknown` | User is muting an alert rule. -| `failure` | User is not authorized to mute an alert rule. +| `unknown` | User is muting an alert. +| `failure` | User is not authorized to mute an alert. .2+| `alert_unmute` -| `unknown` | User is unmuting an alert rule. -| `failure` | User is not authorized to unmute an alert rule. +| `unknown` | User is unmuting an alert. +| `failure` | User is not authorized to unmute an alert. .2+| `alert_instance_mute` | `unknown` | User is muting an alert instance. @@ -152,6 +156,9 @@ Refer to the corresponding {es} logs for potential write errors. | `unknown` | User is unmuting an alert instance. | `failure` | User is not authorized to unmute an alert instance. +.2+| `space_update` +| `unknown` | User is updating a space. +| `failure` | User is not authorized to update a space. 3+a| ====== Type: deletion @@ -169,8 +176,12 @@ Refer to the corresponding {es} logs for potential write errors. | `failure` | User is not authorized to delete a connector. .2+| `alert_delete` -| `unknown` | User is deleting an alert rule. -| `failure` | User is not authorized to delete an alert rule. +| `unknown` | User is deleting an alert. +| `failure` | User is not authorized to delete an alert. + +.2+| `space_delete` +| `unknown` | User is deleting a space. +| `failure` | User is not authorized to delete a space. 3+a| ====== Type: access @@ -196,13 +207,20 @@ Refer to the corresponding {es} logs for potential write errors. | `failure` | User is not authorized to search for connectors. .2+| `alert_get` -| `success` | User has accessed an alert rule. -| `failure` | User is not authorized to access an alert rule. +| `success` | User has accessed an alert. +| `failure` | User is not authorized to access an alert. .2+| `alert_find` -| `success` | User has accessed an alert rule as part of a search operation. -| `failure` | User is not authorized to search for alert rules. +| `success` | User has accessed an alert as part of a search operation. +| `failure` | User is not authorized to search for alerts. +.2+| `space_get` +| `success` | User has accessed a space. +| `failure` | User is not authorized to access a space. + +.2+| `space_find` +| `success` | User has accessed a space as part of a search operation. +| `failure` | User is not authorized to search for spaces. 3+a| ===== Category: web @@ -214,3 +232,188 @@ Refer to the corresponding {es} logs for potential write errors. | `http_request` | `unknown` | User is making an HTTP request. |====== + + +[[xpack-security-ecs-audit-schema]] +==== ECS audit schema + +Audit logs are written in JSON using https://www.elastic.co/guide/en/ecs/1.6/index.html[Elastic Common Schema (ECS)] specification. + +[cols="2*<"] +|====== + +2+a| ===== Base Fields + +| *Field* +| *Description* + +| `@timestamp` +| Time when the event was generated. + +Example: `2016-05-23T08:05:34.853Z` + +| `message` +| Human readable description of the event. + +2+a| ===== Event Fields + +| *Field* +| *Description* + +| [[field-event-action]] `event.action` +| The action captured by the event. + +Refer to <> for a table of possible actions. + +| [[field-event-category]] `event.category` +| High level category associated with the event. + +This field is closely related to `event.type`, which is used as a subcategory. + +Possible values: +`database`, +`web`, +`authentication` + +| [[field-event-type]] `event.type` +| Subcategory associated with the event. + +This field can be used along with the `event.category` field to enable filtering events down to a level appropriate for single visualization. + +Possible values: +`creation`, +`access`, +`change`, +`deletion` + +| [[field-event-outcome]] `event.outcome` +| Denotes whether the event represents a success or failure. + +Possible values: +`success`, +`failure`, +`unknown` + +2+a| ===== User Fields + +| *Field* +| *Description* + +| `user.name` +| Login name of the user. + +Example: `jdoe` + +| `user.roles[]` +| Set of user roles at the time of the event. + +Example: `[kibana_admin, reporting_user]` + +2+a| ===== Kibana Fields + +| *Field* +| *Description* + +| `kibana.space_id` +| ID of the space associated with the event. + +Example: `default` + +| `kibana.session_id` +| ID of the user session associated with the event. + +Each login attempt results in a unique session id. + +| `kibana.saved_object.type` +| Type of saved object associated with the event. + +Example: `dashboard` + +| `kibana.saved_object.id` +| ID of the saved object associated with the event. + +| `kibana.authentication_provider` +| Name of the authentication provider associated with the event. + +Example: `my-saml-provider` + +| `kibana.authentication_type` +| Type of the authentication provider associated with the event. + +Example: `saml` + +| `kibana.authentication_realm` +| Name of the Elasticsearch realm that has authenticated the user. + +Example: `native` + +| `kibana.lookup_realm` +| Name of the Elasticsearch realm where the user details were retrieved from. + +Example: `native` + +| `kibana.add_to_spaces[]` +| Set of space IDs that a saved object is being shared to as part of the event. + +Example: `[default, marketing]` + +| `kibana.delete_from_spaces[]` +| Set of space IDs that a saved object is being removed from as part of the event. + +Example: `[marketing]` + +2+a| ===== Error Fields + +| *Field* +| *Description* + +| `error.code` +| Error code describing the error. + +| `error.message` +| Error message. + +2+a| ===== HTTP and URL Fields + +| *Field* +| *Description* + +| `http.request.method` +| HTTP request method. + +Example: `get`, `post`, `put`, `delete` + +| `url.domain` +| Domain of the url. + +Example: `www.elastic.co` + +| `url.path` +| Path of the request. + +Example: `/search` + +| `url.port` +| Port of the request. + +Example: `443` + +| `url.query` +| The query field describes the query string of the request. + +Example: `q=elasticsearch` + +| `url.scheme` +| Scheme of the request. + +Example: `https` + +2+a| ===== Tracing Fields + +| *Field* +| *Description* + +| `trace.id` +| Unique identifier allowing events of the same transaction from {kib} and {es} to be be correlated. + +|====== diff --git a/docs/user/security/encryption-keys/index.asciidoc b/docs/user/security/encryption-keys/index.asciidoc new file mode 100644 index 000000000000..58c0c0bb775c --- /dev/null +++ b/docs/user/security/encryption-keys/index.asciidoc @@ -0,0 +1,44 @@ +[[kibana-encryption-keys]] +=== Set up encryptions keys to protect sensitive information + +The `kibana-encryption-keys` command helps you set up encryption keys that {kib} uses +to protect sensitive information. + +[discrete] +=== Synopsis + +[source,shell] +-------------------------------------------------- +bin/kibana-encryption-keys generate +[-i, --interactive] [-q, --quiet] +[-f, --force] [-h, --help] +-------------------------------------------------- + +[discrete] +=== Description + +{kib} uses encryption keys in several areas, ranging from encrypting data +in {kib} associated indices to storing session information. By defining these +encryption keys in your configuration, you'll ensure consistent operations +across restarts. + +[discrete] +[[encryption-key-parameters]] +=== Parameters + +`generate`:: Randomly generates passwords to the console. + +`-i, --interactive`:: Prompts you for which encryption keys to set and optionally +where to save a sample configuration file. + +`-q, --quiet`:: Outputs the encryption keys without helper information. + +`-f, --force`:: Shows help information. + +[discrete] +=== Examples + +[source,shell] +-------------------------------------------------- +bin/kibana-encryption-keys generate +-------------------------------------------------- diff --git a/docs/user/security/index.asciidoc b/docs/user/security/index.asciidoc index f84e9de87c73..6a5c4a83aa3a 100644 --- a/docs/user/security/index.asciidoc +++ b/docs/user/security/index.asciidoc @@ -45,5 +45,6 @@ cause Kibana's authorization to behave unexpectedly. include::authorization/index.asciidoc[] include::authorization/kibana-privileges.asciidoc[] include::api-keys/index.asciidoc[] +include::encryption-keys/index.asciidoc[] include::role-mappings/index.asciidoc[] include::rbac_tutorial.asciidoc[] diff --git a/package.json b/package.json index b4b3cbe22b71..61b13a06bffe 100644 --- a/package.json +++ b/package.json @@ -73,10 +73,6 @@ "url": "https://github.com/elastic/kibana.git" }, "resolutions": { - "**/@hapi/iron": "^5.1.4", - "**/@types/hapi__boom": "^7.4.1", - "**/@types/hapi__hapi": "^18.2.6", - "**/@types/hapi__mimos": "4.1.0", "**/@types/node": "14.14.14", "**/chokidar": "^3.4.3", "**/cross-fetch/node-fetch": "^2.6.1", @@ -97,16 +93,16 @@ "**/typescript": "4.1.2" }, "engines": { - "node": "14.15.2", + "node": "14.15.3", "yarn": "^1.21.1" }, "dependencies": { "@babel/core": "^7.11.6", "@babel/runtime": "^7.11.2", "@elastic/datemath": "link:packages/elastic-datemath", - "@elastic/elasticsearch": "7.10.0", + "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary", "@elastic/ems-client": "7.11.0", - "@elastic/eui": "30.6.0", + "@elastic/eui": "31.0.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "^9.0.1-kibana3", "@elastic/node-crypto": "1.2.1", @@ -115,17 +111,17 @@ "@elastic/request-crypto": "1.1.4", "@elastic/safer-lodash-set": "link:packages/elastic-safer-lodash-set", "@elastic/search-ui-app-search-connector": "^1.5.0", - "@hapi/boom": "^7.4.11", - "@hapi/cookie": "^10.1.2", - "@hapi/good-squeeze": "5.2.1", - "@hapi/h2o2": "^8.3.2", - "@hapi/hapi": "^18.4.1", - "@hapi/hoek": "^8.5.1", - "@hapi/inert": "^5.2.2", - "@hapi/podium": "^3.4.3", - "@hapi/statehood": "^6.1.2", - "@hapi/vision": "^5.5.4", - "@hapi/wreck": "^15.0.2", + "@hapi/boom": "^9.1.1", + "@hapi/cookie": "^11.0.2", + "@hapi/good-squeeze": "6.0.0", + "@hapi/h2o2": "^9.0.2", + "@hapi/hapi": "^20.0.3", + "@hapi/hoek": "^9.1.0", + "@hapi/inert": "^6.0.3", + "@hapi/podium": "^4.1.1", + "@hapi/statehood": "^7.0.3", + "@hapi/vision": "^6.0.1", + "@hapi/wreck": "^17.1.0", "@kbn/ace": "link:packages/kbn-ace", "@kbn/analytics": "link:packages/kbn-analytics", "@kbn/apm-config-loader": "link:packages/kbn-apm-config-loader", @@ -381,6 +377,7 @@ "@mapbox/geojson-rewind": "^0.5.0", "@mapbox/mapbox-gl-draw": "^1.2.0", "@mapbox/mapbox-gl-rtl-text": "^0.2.3", + "@mapbox/vector-tile": "1.3.1", "@microsoft/api-documenter": "7.7.2", "@microsoft/api-extractor": "7.7.0", "@octokit/rest": "^16.35.0", @@ -451,14 +448,11 @@ "@types/graphql": "^0.13.2", "@types/gulp": "^4.0.6", "@types/gulp-zip": "^4.0.1", - "@types/hapi__boom": "^7.4.1", "@types/hapi__cookie": "^10.1.1", - "@types/hapi__h2o2": "8.3.0", - "@types/hapi__hapi": "^18.2.6", - "@types/hapi__hoek": "^6.2.0", - "@types/hapi__inert": "^5.2.1", + "@types/hapi__h2o2": "^8.3.2", + "@types/hapi__hapi": "^20.0.2", + "@types/hapi__inert": "^5.2.2", "@types/hapi__podium": "^3.4.1", - "@types/hapi__wreck": "^15.0.1", "@types/has-ansi": "^3.0.0", "@types/he": "^1.1.1", "@types/history": "^4.7.3", @@ -750,6 +744,7 @@ "ora": "^4.0.4", "p-limit": "^3.0.1", "parse-link-header": "^1.0.1", + "pbf": "3.2.1", "pirates": "^4.0.1", "pixelmatch": "^5.1.0", "pkg-up": "^2.0.0", @@ -829,7 +824,7 @@ "url-loader": "^2.2.0", "use-resize-observer": "^6.0.0", "val-loader": "^1.1.1", - "vega": "^5.17.0", + "vega": "^5.17.3", "vega-lite": "^4.17.0", "vega-schema-url-parser": "^2.1.0", "vega-tooltip": "^0.24.2", diff --git a/packages/kbn-apm-config-loader/src/config.ts b/packages/kbn-apm-config-loader/src/config.ts index 6e5a830d04b1..5e3d52cfd27d 100644 --- a/packages/kbn-apm-config-loader/src/config.ts +++ b/packages/kbn-apm-config-loader/src/config.ts @@ -153,8 +153,8 @@ export class ApmConfiguration { return { globalLabels: { - branch: process.env.ghprbSourceBranch || '', - targetBranch: process.env.ghprbTargetBranch || '', + branch: process.env.GIT_BRANCH || '', + targetBranch: process.env.PR_TARGET_BRANCH || '', ciBuildNumber: process.env.BUILD_NUMBER || '', isPr: process.env.GITHUB_PR_NUMBER ? true : false, prId: process.env.GITHUB_PR_NUMBER || '', diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index 68bcc37c6560..eaf353b3e55d 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -275,6 +275,15 @@ exports.Cluster = class Cluster { this._log.debug('%s %s', ES_BIN, args.join(' ')); + options.esEnvVars = options.esEnvVars || {}; + + // ES now automatically sets heap size to 50% of the machine's available memory + // so we need to set it to a smaller size for local dev and CI + // especially because we currently run many instances of ES on the same machine during CI + options.esEnvVars.ES_JAVA_OPTS = + (options.esEnvVars.ES_JAVA_OPTS ? `${options.esEnvVars.ES_JAVA_OPTS} ` : '') + + '-Xms1g -Xmx1g'; + this._process = execa(ES_BIN, args, { cwd: installPath, env: { diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index c58d010a1f31..08d883a7cbb4 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -6,7 +6,7 @@ pageLoadAssetSize: beatsManagement: 188135 bfetch: 41874 canvas: 1066647 - charts: 159211 + charts: 195358 cloud: 21076 console: 46091 core: 692106 @@ -98,7 +98,7 @@ pageLoadAssetSize: visTypeTimeseries: 155203 visTypeVega: 153573 visTypeVislib: 242838 - visTypeXy: 20255 + visTypeXy: 113478 visualizations: 295025 visualize: 57431 watcher: 43598 diff --git a/packages/kbn-test/jest-preset.js b/packages/kbn-test/jest-preset.js index 89ed60909aa5..55514da3e231 100644 --- a/packages/kbn-test/jest-preset.js +++ b/packages/kbn-test/jest-preset.js @@ -111,7 +111,7 @@ module.exports = { // An array of regexp pattern strings that are matched against all source file paths, matched files to include/exclude for code coverage collectCoverageFrom: [ '**/*.{js,mjs,jsx,ts,tsx}', - '!**/{__test__,__snapshots__,__examples__,mocks,tests,test_helpers,integration_tests,types}/**/*', + '!**/{__test__,__snapshots__,__examples__,*mock*,tests,test_helpers,integration_tests,types}/**/*', '!**/*mock*.ts', '!**/*.test.ts', '!**/*.d.ts', diff --git a/packages/kbn-test/src/functional_test_runner/cli.ts b/packages/kbn-test/src/functional_test_runner/cli.ts index 8f53d6f7cf58..2dfc9ded6620 100644 --- a/packages/kbn-test/src/functional_test_runner/cli.ts +++ b/packages/kbn-test/src/functional_test_runner/cli.ts @@ -141,22 +141,27 @@ export function runFtrCli() { config: 'test/functional/config.js', }, help: ` - --config=path path to a config file - --bail stop tests after the first failure - --grep pattern used to select which tests to run - --invert invert grep to exclude tests - --include=file a test file to be included, pass multiple times for multiple files - --exclude=file a test file to be excluded, pass multiple times for multiple files - --include-tag=tag a tag to be included, pass multiple times for multiple tags - --exclude-tag=tag a tag to be excluded, pass multiple times for multiple tags - --test-stats print the number of tests (included and excluded) to STDERR - --updateBaselines replace baseline screenshots with whatever is generated from the test - --updateSnapshots replace inline and file snapshots with whatever is generated from the test - -u replace both baseline screenshots and snapshots - --kibana-install-dir directory where the Kibana install being tested resides - --throttle enable network throttling in Chrome browser - --headless run browser in headless mode - `, + --config=path path to a config file + --bail stop tests after the first failure + --grep pattern used to select which tests to run + --invert invert grep to exclude tests + --include=file a test file to be included, pass multiple times for multiple files + --exclude=file a test file to be excluded, pass multiple times for multiple files + --include-tag=tag a tag to be included, pass multiple times for multiple tags. Only + suites which have one of the passed include-tag tags will be executed. + When combined with the --exclude-tag flag both conditions must be met + for a suite to run. + --exclude-tag=tag a tag to be excluded, pass multiple times for multiple tags. Any suite + which has any of the exclude-tags will be excluded. When combined with + the --include-tag flag both conditions must be met for a suite to run. + --test-stats print the number of tests (included and excluded) to STDERR + --updateBaselines replace baseline screenshots with whatever is generated from the test + --updateSnapshots replace inline and file snapshots with whatever is generated from the test + -u replace both baseline screenshots and snapshots + --kibana-install-dir directory where the Kibana install being tested resides + --throttle enable network throttling in Chrome browser + --headless run browser in headless mode + `, }, } ); diff --git a/scripts/ensure_all_tests_in_ci_group.js b/scripts/ensure_all_tests_in_ci_group.js new file mode 100644 index 000000000000..d189aac8f62e --- /dev/null +++ b/scripts/ensure_all_tests_in_ci_group.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); +require('../src/dev/run_ensure_all_tests_in_ci_group'); diff --git a/src/core/public/application/index.ts b/src/core/public/application/index.ts index b39aa70c888f..96d669a7b96f 100644 --- a/src/core/public/application/index.ts +++ b/src/core/public/application/index.ts @@ -31,6 +31,7 @@ export { AppNavLinkStatus, AppUpdatableFields, AppUpdater, + AppMeta, AppSearchDeepLink, ApplicationSetup, ApplicationStart, @@ -41,6 +42,7 @@ export { AppLeaveConfirmAction, NavigateToAppOptions, PublicAppInfo, + PublicAppMetaInfo, PublicAppSearchDeepLinkInfo, // Internal types InternalApplicationSetup, diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index c161a7f16654..0a31490ad664 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -83,7 +83,7 @@ export enum AppNavLinkStatus { */ export type AppUpdatableFields = Pick< App, - 'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath' | 'searchDeepLinks' + 'status' | 'navLinkStatus' | 'tooltip' | 'defaultPath' | 'meta' >; /** @@ -237,39 +237,76 @@ export interface App { exactRoute?: boolean; /** - * Array of links that represent secondary in-app locations for the app. + * Meta data for an application that represent additional information for the app. + * See {@link AppMeta} * * @remarks * Used to populate navigational search results (where available). - * Can be updated using the {@link App.updater$} observable. See {@link AppSubLink} for more details. + * Can be updated using the {@link App.updater$} observable. See {@link PublicAppSearchDeepLinkInfo} for more details. * * @example - * The `path` property on deep links should not include the application's `appRoute`: * ```ts * core.application.register({ * id: 'my_app', - * title: 'My App', - * searchDeepLinks: [ - * { id: 'sub1', title: 'Sub1', path: '/sub1' }, + * title: 'Translated title', + * meta: { + * keywords: ['translated keyword1', 'translated keyword2'], + * searchDeepLinks: [ + * { id: 'sub1', title: 'Sub1', path: '/sub1', keywords: ['subpath1'] }, * { * id: 'sub2', * title: 'Sub2', * searchDeepLinks: [ - * { id: 'subsub', title: 'SubSub', path: '/sub2/sub' } + * { id: 'subsub', title: 'SubSub', path: '/sub2/sub', keywords: ['subpath2'] } * ] * } * ], - * mount: () => { ... }, + * }, + * mount: () => { ... } * }) * ``` - * - * Will produce deep links on these paths: - * - `/app/my_app/sub1` - * - `/app/my_app/sub2/sub` */ + meta?: AppMeta; +} + +/** + * Input type for meta data for an application. + * + * Meta fields include `keywords` and `searchDeepLinks` + * Keywords is an array of string with which to associate the app, must include at least one unique string as an array. + * `searchDeepLinks` is an array of links that represent secondary in-app locations for the app. + * @public + */ +export interface AppMeta { + /** Keywords to represent this application */ + keywords?: string[]; + /** Array of links that represent secondary in-app locations for the app. */ searchDeepLinks?: AppSearchDeepLink[]; } +/** + * Public information about a registered app's {@link AppMeta | keywords } + * + * @public + */ +export type PublicAppMetaInfo = Omit & { + keywords: string[]; + searchDeepLinks: PublicAppSearchDeepLinkInfo[]; +}; + +/** + * Public information about a registered app's {@link AppSearchDeepLink | searchDeepLinks} + * + * @public + */ +export type PublicAppSearchDeepLinkInfo = Omit< + AppSearchDeepLink, + 'searchDeepLinks' | 'keywords' +> & { + searchDeepLinks: PublicAppSearchDeepLinkInfo[]; + keywords: string[]; +}; + /** * Input type for registering secondary in-app locations for an application. * @@ -289,35 +326,30 @@ export type AppSearchDeepLink = { path: string; /** Optional array of links that are 'underneath' this section in the hierarchy */ searchDeepLinks?: AppSearchDeepLink[]; + /** Optional keywords to match with in deep links search for the page at the path */ + keywords?: string[]; } | { /** Optional path to access this section. Omit if this part of the hierarchy does not have a page URL. */ path?: string; /** Array links that are 'underneath' this section in this hierarchy. */ searchDeepLinks: AppSearchDeepLink[]; + /** Optional keywords to match with in deep links search. Omit if this part of the hierarchy does not have a page URL. */ + keywords?: string[]; } ); -/** - * Public information about a registered app's {@link AppSearchDeepLink | searchDeepLinks} - * - * @public - */ -export type PublicAppSearchDeepLinkInfo = Omit & { - searchDeepLinks: PublicAppSearchDeepLinkInfo[]; -}; - /** * Public information about a registered {@link App | application} * * @public */ -export type PublicAppInfo = Omit & { +export type PublicAppInfo = Omit & { // remove optional on fields populated with default values status: AppStatus; navLinkStatus: AppNavLinkStatus; appRoute: string; - searchDeepLinks: PublicAppSearchDeepLinkInfo[]; + meta: PublicAppMetaInfo; }; /** diff --git a/src/core/public/application/utils/get_app_info.test.ts b/src/core/public/application/utils/get_app_info.test.ts index ee0bd4f1eadf..ff09a18c8b65 100644 --- a/src/core/public/application/utils/get_app_info.test.ts +++ b/src/core/public/application/utils/get_app_info.test.ts @@ -43,19 +43,24 @@ describe('getAppInfo', () => { status: AppStatus.accessible, navLinkStatus: AppNavLinkStatus.visible, appRoute: `/app/some-id`, - searchDeepLinks: [], + meta: { + keywords: [], + searchDeepLinks: [], + }, }); }); it('populates default values for nested searchDeepLinks', () => { const app = createApp({ - searchDeepLinks: [ - { - id: 'sub-id', - title: 'sub-title', - searchDeepLinks: [{ id: 'sub-sub-id', title: 'sub-sub-title', path: '/sub-sub' }], - }, - ], + meta: { + searchDeepLinks: [ + { + id: 'sub-id', + title: 'sub-title', + searchDeepLinks: [{ id: 'sub-sub-id', title: 'sub-sub-title', path: '/sub-sub' }], + }, + ], + }, }); const info = getAppInfo(app); @@ -65,20 +70,25 @@ describe('getAppInfo', () => { status: AppStatus.accessible, navLinkStatus: AppNavLinkStatus.visible, appRoute: `/app/some-id`, - searchDeepLinks: [ - { - id: 'sub-id', - title: 'sub-title', - searchDeepLinks: [ - { - id: 'sub-sub-id', - title: 'sub-sub-title', - path: '/sub-sub', - searchDeepLinks: [], // default empty array added - }, - ], - }, - ], + meta: { + keywords: [], + searchDeepLinks: [ + { + id: 'sub-id', + title: 'sub-title', + keywords: [], + searchDeepLinks: [ + { + id: 'sub-sub-id', + title: 'sub-sub-title', + path: '/sub-sub', + keywords: [], + searchDeepLinks: [], // default empty array added + }, + ], + }, + ], + }, }); }); @@ -108,4 +118,53 @@ describe('getAppInfo', () => { }) ); }); + + it('adds default meta fields to sublinks when needed', () => { + const app = createApp({ + meta: { + searchDeepLinks: [ + { + id: 'sub-id', + title: 'sub-title', + searchDeepLinks: [ + { + id: 'sub-sub-id', + title: 'sub-sub-title', + path: '/sub-sub', + keywords: ['sub sub'], + }, + ], + }, + ], + }, + }); + const info = getAppInfo(app); + + expect(info).toEqual({ + id: 'some-id', + title: 'some-title', + status: AppStatus.accessible, + navLinkStatus: AppNavLinkStatus.visible, + appRoute: `/app/some-id`, + meta: { + keywords: [], + searchDeepLinks: [ + { + id: 'sub-id', + title: 'sub-title', + keywords: [], // default empty array + searchDeepLinks: [ + { + id: 'sub-sub-id', + title: 'sub-sub-title', + path: '/sub-sub', + keywords: ['sub sub'], + searchDeepLinks: [], + }, + ], + }, + ], + }, + }); + }); }); diff --git a/src/core/public/application/utils/get_app_info.ts b/src/core/public/application/utils/get_app_info.ts index 7316080816da..574696c3bd5f 100644 --- a/src/core/public/application/utils/get_app_info.ts +++ b/src/core/public/application/utils/get_app_info.ts @@ -39,7 +39,10 @@ export function getAppInfo(app: App): PublicAppInfo { status: app.status!, navLinkStatus, appRoute: app.appRoute!, - searchDeepLinks: getSearchDeepLinkInfos(app, app.searchDeepLinks), + meta: { + keywords: app.meta?.keywords ?? [], + searchDeepLinks: getSearchDeepLinkInfos(app, app.meta?.searchDeepLinks), + }, }; } @@ -57,6 +60,7 @@ function getSearchDeepLinkInfos( id: rawDeepLink.id, title: rawDeepLink.title, path: rawDeepLink.path, + keywords: rawDeepLink.keywords ?? [], searchDeepLinks: getSearchDeepLinkInfos(app, rawDeepLink.searchDeepLinks), }; } diff --git a/src/core/public/chrome/nav_links/to_nav_link.test.ts b/src/core/public/chrome/nav_links/to_nav_link.test.ts index 606370c5afd0..44feb133cfce 100644 --- a/src/core/public/chrome/nav_links/to_nav_link.test.ts +++ b/src/core/public/chrome/nav_links/to_nav_link.test.ts @@ -28,7 +28,10 @@ const app = (props: Partial = {}): PublicAppInfo => ({ status: AppStatus.accessible, navLinkStatus: AppNavLinkStatus.default, appRoute: `/app/some-id`, - searchDeepLinks: [], + meta: { + keywords: [], + searchDeepLinks: [], + }, ...props, }); diff --git a/src/core/public/chrome/ui/header/_index.scss b/src/core/public/chrome/ui/header/_index.scss index 44cd86427832..b11e7e47f4ae 100644 --- a/src/core/public/chrome/ui/header/_index.scss +++ b/src/core/public/chrome/ui/header/_index.scss @@ -1,5 +1,19 @@ @include euiHeaderAffordForFixed; +.euiDataGrid__restrictBody { + .headerGlobalNav, + .kbnQueryBar { + display: none; + } +} + +.euiDataGrid__restrictBody.euiBody--headerIsFixed { + .euiFlyout { + top: 0; + height: 100%; + } +} + .chrHeaderHelpMenu__version { text-transform: none; } diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index b8843b5c8559..2893f4c9a987 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -147,6 +147,7 @@ export class DocLinksService { featureImportance: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-feature-importance.html`, outlierDetectionRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-roc`, regressionEvaluation: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-regression-evaluation`, + classificationAucRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-class-aucroc`, }, transforms: { guide: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/transforms.html`, diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 2e1238df350e..51375072d3e5 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -108,10 +108,12 @@ export { AppLeaveConfirmAction, AppStatus, AppNavLinkStatus, + AppMeta, AppUpdatableFields, AppUpdater, AppSearchDeepLink, PublicAppInfo, + PublicAppMetaInfo, PublicAppSearchDeepLinkInfo, ScopedHistory, NavigateToAppOptions, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index defe43377172..0303eb62b641 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -56,11 +56,10 @@ export interface App { exactRoute?: boolean; icon?: string; id: string; + meta?: AppMeta; mount: AppMount | AppMountDeprecated; navLinkStatus?: AppNavLinkStatus; order?: number; - // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "AppSubLink" - searchDeepLinks?: AppSearchDeepLink[]; status?: AppStatus; title: string; tooltip?: string; @@ -137,6 +136,12 @@ export interface ApplicationStart { registerMountContext(contextName: T, provider: IContextProvider): void; } +// @public +export interface AppMeta { + keywords?: string[]; + searchDeepLinks?: AppSearchDeepLink[]; +} + // @public export type AppMount = (params: AppMountParameters) => AppUnmount | Promise; @@ -186,9 +191,11 @@ export type AppSearchDeepLink = { } & ({ path: string; searchDeepLinks?: AppSearchDeepLink[]; + keywords?: string[]; } | { path?: string; searchDeepLinks: AppSearchDeepLink[]; + keywords?: string[]; }); // @public @@ -201,7 +208,7 @@ export enum AppStatus { export type AppUnmount = () => void; // @public -export type AppUpdatableFields = Pick; +export type AppUpdatableFields = Pick; // @public export type AppUpdater = (app: App) => Partial | undefined; @@ -1008,16 +1015,23 @@ export interface PluginInitializerContext export type PluginOpaqueId = symbol; // @public -export type PublicAppInfo = Omit & { +export type PublicAppInfo = Omit & { status: AppStatus; navLinkStatus: AppNavLinkStatus; appRoute: string; + meta: PublicAppMetaInfo; +}; + +// @public +export type PublicAppMetaInfo = Omit & { + keywords: string[]; searchDeepLinks: PublicAppSearchDeepLinkInfo[]; }; // @public -export type PublicAppSearchDeepLinkInfo = Omit & { +export type PublicAppSearchDeepLinkInfo = Omit & { searchDeepLinks: PublicAppSearchDeepLinkInfo[]; + keywords: string[]; }; // @public diff --git a/src/core/server/elasticsearch/legacy/errors.ts b/src/core/server/elasticsearch/legacy/errors.ts index e557e7395fe5..adc1fa072878 100644 --- a/src/core/server/elasticsearch/legacy/errors.ts +++ b/src/core/server/elasticsearch/legacy/errors.ts @@ -30,7 +30,7 @@ enum ErrorCode { * @deprecated. The new elasticsearch client doesn't wrap errors anymore. * @public * */ -export interface LegacyElasticsearchError extends Boom { +export interface LegacyElasticsearchError extends Boom.Boom { [code]?: string; } @@ -86,7 +86,7 @@ export class LegacyElasticsearchErrorHelpers { const decoratedError = decorate(error, ErrorCode.NOT_AUTHORIZED, 401, reason); const wwwAuthHeader = get(error, 'body.error.header[WWW-Authenticate]') as string; - decoratedError.output.headers['WWW-Authenticate'] = + (decoratedError.output.headers as { [key: string]: string })['WWW-Authenticate'] = wwwAuthHeader || 'Basic realm="Authorization Required"'; return decoratedError; diff --git a/src/core/server/http/http_config.ts b/src/core/server/http/http_config.ts index 2bd296fe338a..61a9b5f04b23 100644 --- a/src/core/server/http/http_config.ts +++ b/src/core/server/http/http_config.ts @@ -195,7 +195,13 @@ export class HttpConfig { rawExternalUrlConfig: ExternalUrlConfig ) { this.autoListen = rawHttpConfig.autoListen; - this.host = rawHttpConfig.host; + // TODO: Consider dropping support for '0' in v8.0.0. This value is passed + // to hapi, which validates it. Prior to hapi v20, '0' was considered a + // valid host, however the validation logic internally in hapi was + // re-written for v20 and hapi no longer considers '0' a valid host. For + // details, see: + // https://github.com/elastic/kibana/issues/86716#issuecomment-749623781 + this.host = rawHttpConfig.host === '0' ? '0.0.0.0' : rawHttpConfig.host; this.port = rawHttpConfig.port; this.cors = rawHttpConfig.cors; this.customResponseHeaders = Object.entries(rawHttpConfig.customResponseHeaders ?? {}).reduce( diff --git a/src/core/server/http/http_server.test.ts b/src/core/server/http/http_server.test.ts index 71040598d34b..cbb60480c4cf 100644 --- a/src/core/server/http/http_server.test.ts +++ b/src/core/server/http/http_server.test.ts @@ -1214,7 +1214,7 @@ describe('timeout options', () => { router.get( { path: '/', - validate: { body: schema.any() }, + validate: { body: schema.maybe(schema.any()) }, }, (context, req, res) => { return res.ok({ @@ -1247,7 +1247,7 @@ describe('timeout options', () => { router.get( { path: '/', - validate: { body: schema.any() }, + validate: { body: schema.maybe(schema.any()) }, options: { timeout: { idleSocket: 12000 } }, }, (context, req, res) => { diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index 43f5264ff22e..42e89b66d9c5 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Server } from '@hapi/hapi'; +import { Server, ServerRoute } from '@hapi/hapi'; import HapiStaticFiles from '@hapi/inert'; import url from 'url'; import uuid from 'uuid'; @@ -167,8 +167,6 @@ export class HttpServer { for (const router of this.registeredRouters) { for (const route of router.getRoutes()) { this.log.debug(`registering route handler for [${route.path}]`); - // Hapi does not allow payload validation to be specified for 'head' or 'get' requests - const validate = isSafeMethod(route.method) ? undefined : { payload: true }; const { authRequired, tags, body = {}, timeout } = route.options; const { accepts: allow, maxBytes, output, parse } = body; @@ -176,57 +174,45 @@ export class HttpServer { xsrfRequired: route.options.xsrfRequired ?? !isSafeMethod(route.method), }; - // To work around https://github.com/hapijs/hapi/issues/4122 until v20, set the socket - // timeout on the route to a fake timeout only when the payload timeout is specified. - // Within the onPreAuth lifecycle of the route itself, we'll override the timeout with the - // real socket timeout. - const fakeSocketTimeout = timeout?.payload ? timeout.payload + 1 : undefined; - - this.server.route({ + const routeOpts: ServerRoute = { handler: route.handler, method: route.method, path: route.path, options: { auth: this.getAuthOption(authRequired), app: kibanaRouteOptions, - ext: { - onPreAuth: { - method: (request, h) => { - // At this point, the socket timeout has only been set to work-around the HapiJS bug. - // We need to either set the real per-route timeout or use the default idle socket timeout - if (timeout?.idleSocket) { - request.raw.req.socket.setTimeout(timeout.idleSocket); - } else if (fakeSocketTimeout) { - // NodeJS uses a socket timeout of `0` to denote "no timeout" - request.raw.req.socket.setTimeout(this.config!.socketTimeout ?? 0); - } - - return h.continue; - }, - }, - }, tags: tags ? Array.from(tags) : undefined, - // TODO: This 'validate' section can be removed once the legacy platform is completely removed. - // We are telling Hapi that NP routes can accept any payload, so that it can bypass the default - // validation applied in ./http_tools#getServerOptions - // (All NP routes are already required to specify their own validation in order to access the payload) - validate, - payload: [allow, maxBytes, output, parse, timeout?.payload].some( - (v) => typeof v !== 'undefined' - ) + // @ts-expect-error Types are outdated and doesn't allow `payload.multipart` to be `true` + payload: [allow, maxBytes, output, parse, timeout?.payload].some((x) => x !== undefined) ? { allow, maxBytes, output, parse, timeout: timeout?.payload, + multipart: true, } : undefined, timeout: { - socket: fakeSocketTimeout, + socket: timeout?.idleSocket ?? this.config!.socketTimeout, }, }, - }); + }; + + // Hapi does not allow payload validation to be specified for 'head' or 'get' requests + if (!isSafeMethod(route.method)) { + // TODO: This 'validate' section can be removed once the legacy platform is completely removed. + // We are telling Hapi that NP routes can accept any payload, so that it can bypass the default + // validation applied in ./http_tools#getServerOptions + // (All NP routes are already required to specify their own validation in order to access the payload) + // TODO: Move the setting of the validate option back up to being set at `routeOpts` creation-time once + // https://github.com/hapijs/hoek/pull/365 is merged and released in @hapi/hoek v9.1.1. At that point I + // imagine the ts-error below will go away as well. + // @ts-expect-error "Property 'validate' does not exist on type 'RouteOptions'" <-- ehh?!? yes it does! + routeOpts.options!.validate = { payload: true }; + } + + this.server.route(routeOpts); } } diff --git a/src/core/server/http/lifecycle/on_pre_response.ts b/src/core/server/http/lifecycle/on_pre_response.ts index 42179374ec67..9efcf46148e1 100644 --- a/src/core/server/http/lifecycle/on_pre_response.ts +++ b/src/core/server/http/lifecycle/on_pre_response.ts @@ -142,7 +142,11 @@ export function adoptToHapiOnPreResponseFormat(fn: OnPreResponseHandler, log: Lo if (preResponseResult.isNext(result)) { if (result.headers) { if (isBoom(response)) { - findHeadersIntersection(response.output.headers, result.headers, log); + findHeadersIntersection( + response.output.headers as { [key: string]: string }, + result.headers, + log + ); // hapi wraps all error response in Boom object internally response.output.headers = { ...response.output.headers, @@ -157,7 +161,7 @@ export function adoptToHapiOnPreResponseFormat(fn: OnPreResponseHandler, log: Lo const overriddenResponse = responseToolkit.response(result.body).code(statusCode); const originalHeaders = isBoom(response) ? response.output.headers : response.headers; - setHeaders(overriddenResponse, originalHeaders); + setHeaders(overriddenResponse, originalHeaders as { [key: string]: string }); if (result.headers) { setHeaders(overriddenResponse, result.headers); } @@ -178,8 +182,8 @@ export function adoptToHapiOnPreResponseFormat(fn: OnPreResponseHandler, log: Lo }; } -function isBoom(response: any): response is Boom { - return response instanceof Boom; +function isBoom(response: any): response is Boom.Boom { + return response instanceof Boom.Boom; } function setHeaders(response: ResponseObject, headers: ResponseHeaders) { diff --git a/src/core/server/http/router/error_wrapper.ts b/src/core/server/http/router/error_wrapper.ts index 5a4b7e9f7758..7d141e81ddf3 100644 --- a/src/core/server/http/router/error_wrapper.ts +++ b/src/core/server/http/router/error_wrapper.ts @@ -29,7 +29,7 @@ export const wrapErrors: RequestHandlerWrapper = (handler) => { return response.customError({ body: e.output.payload, statusCode: e.output.statusCode, - headers: e.output.headers, + headers: e.output.headers as { [key: string]: string }, }); } throw e; diff --git a/src/core/server/http/router/response_adapter.ts b/src/core/server/http/router/response_adapter.ts index 63acd2207ac3..d80c21bde8de 100644 --- a/src/core/server/http/router/response_adapter.ts +++ b/src/core/server/http/router/response_adapter.ts @@ -56,7 +56,7 @@ export class HapiResponseAdapter { } public toInternalError() { - const error = new Boom('', { + const error = new Boom.Boom('', { statusCode: 500, }); @@ -129,7 +129,7 @@ export class HapiResponseAdapter { } // we use for BWC with Boom payload for error responses - {error: string, message: string, statusCode: string} - const error = new Boom('', { + const error = new Boom.Boom('', { statusCode: kibanaResponse.status, }); @@ -142,8 +142,7 @@ export class HapiResponseAdapter { const headers = kibanaResponse.options.headers; if (headers) { - // Hapi typings for header accept only strings, although string[] is a valid value - error.output.headers = headers as any; + error.output.headers = headers; } return error; diff --git a/src/core/server/http/router/router.ts b/src/core/server/http/router/router.ts index b1e092ba5786..ebc41a793f3b 100644 --- a/src/core/server/http/router/router.ts +++ b/src/core/server/http/router/router.ts @@ -44,7 +44,10 @@ interface RouterRoute { method: RouteMethod; path: string; options: RouteConfigOptions; - handler: (req: Request, responseToolkit: ResponseToolkit) => Promise>; + handler: ( + req: Request, + responseToolkit: ResponseToolkit + ) => Promise>; } /** diff --git a/src/core/server/logging/layouts/json_layout.ts b/src/core/server/logging/layouts/json_layout.ts index 7573d0b83741..34c3c325e732 100644 --- a/src/core/server/logging/layouts/json_layout.ts +++ b/src/core/server/logging/layouts/json_layout.ts @@ -18,7 +18,7 @@ */ import moment from 'moment-timezone'; -import { merge } from 'lodash'; +import { merge } from '@kbn/std'; import { schema } from '@kbn/config-schema'; import { LogRecord, Layout } from '@kbn/logging'; @@ -53,22 +53,19 @@ export class JsonLayout implements Layout { } public format(record: LogRecord): string { - return JSON.stringify( - merge( - { - '@timestamp': moment(record.timestamp).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), - message: record.message, - error: JsonLayout.errorToSerializableObject(record.error), - log: { - level: record.level.id.toUpperCase(), - logger: record.context, - }, - process: { - pid: record.pid, - }, - }, - record.meta - ) - ); + const log = { + '@timestamp': moment(record.timestamp).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), + message: record.message, + error: JsonLayout.errorToSerializableObject(record.error), + log: { + level: record.level.id.toUpperCase(), + logger: record.context, + }, + process: { + pid: record.pid, + }, + }; + const output = record.meta ? merge(log, record.meta) : log; + return JSON.stringify(output); } } diff --git a/src/core/server/saved_objects/migrationsv2/actions/catch_retryable_es_client_errors.test.ts b/src/core/server/saved_objects/migrationsv2/actions/catch_retryable_es_client_errors.test.ts index 3186d7456383..33787e3fce53 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/catch_retryable_es_client_errors.test.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/catch_retryable_es_client_errors.test.ts @@ -22,14 +22,14 @@ import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors'; describe('catchRetryableEsClientErrors', () => { - it('rejects non-retryable response errors', () => { + it('rejects non-retryable response errors', async () => { const error = new esErrors.ResponseError( elasticsearchClientMock.createApiResponse({ body: { error: { type: 'cluster_block_exception' } }, statusCode: 400, }) ); - return expect(Promise.reject(error).catch(catchRetryableEsClientErrors)).rejects.toBe(error); + await expect(Promise.reject(error).catch(catchRetryableEsClientErrors)).rejects.toBe(error); }); describe('returns left retryable_es_client_error for', () => { it('NoLivingConnectionsError', async () => { diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts index 937172272f17..05432d65c055 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts @@ -100,8 +100,9 @@ describe('migration actions', () => { describe('fetchIndices', () => { it('resolves right empty record if no indices were found', async () => { + expect.assertions(1); const task = fetchIndices(client, ['no_such_index']); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", "right": Object {}, @@ -109,12 +110,13 @@ describe('migration actions', () => { `); }); it('resolves right record with found indices', async () => { + expect.assertions(1); const res = (await fetchIndices(client, [ 'no_such_index', 'existing_index_with_docs', ])()) as Either.Right; - return expect(res.right).toEqual( + expect(res.right).toEqual( expect.objectContaining({ existing_index_with_docs: { aliases: {}, @@ -131,17 +133,19 @@ describe('migration actions', () => { await createIndex(client, 'new_index_without_write_block', { properties: {} })(); }); it('resolves right when setting the write block succeeds', async () => { + expect.assertions(1); const task = setWriteBlock(client, 'new_index_without_write_block'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", "right": "set_write_block_succeeded", } `); }); - it('resolves right when setting a write block on an index that already has one', () => { + it('resolves right when setting a write block on an index that already has one', async () => { + expect.assertions(1); const task = setWriteBlock(client, 'existing_index_with_write_block'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", "right": "set_write_block_succeeded", @@ -149,6 +153,7 @@ describe('migration actions', () => { `); }); it('once resolved, prevents further writes to the index', async () => { + expect.assertions(1); const task = setWriteBlock(client, 'new_index_without_write_block'); await task(); const sourceDocs = ([ @@ -157,13 +162,14 @@ describe('migration actions', () => { { _source: { title: 'doc 3' } }, { _source: { title: 'doc 4' } }, ] as unknown) as SavedObjectsRawDoc[]; - return expect( + await expect( bulkOverwriteTransformedDocuments(client, 'new_index_without_write_block', sourceDocs)() ).rejects.toMatchObject(expect.anything()); }); - it('resolves left index_not_found_exception when the index does not exist', () => { + it('resolves left index_not_found_exception when the index does not exist', async () => { + expect.assertions(1); const task = setWriteBlock(client, 'no_such_index'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -180,43 +186,51 @@ describe('migration actions', () => { await createIndex(client, 'existing_index_with_write_block_2', { properties: {} })(); await setWriteBlock(client, 'existing_index_with_write_block_2')(); }); - it('resolves right if successful when an index already has a write block', () => { + it('resolves right if successful when an index already has a write block', async () => { + expect.assertions(1); const task = removeWriteBlock(client, 'existing_index_with_write_block_2'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", "right": "remove_write_block_succeeded", } `); }); - it('resolves right if successful when an index does not have a write block', () => { + it('resolves right if successful when an index does not have a write block', async () => { + expect.assertions(1); const task = removeWriteBlock(client, 'existing_index_without_write_block_2'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", "right": "remove_write_block_succeeded", } `); }); - it('rejects if there is a non-retryable error', () => { + it('rejects if there is a non-retryable error', async () => { + expect.assertions(1); const task = removeWriteBlock(client, 'no_such_index'); - return expect(task()).rejects.toMatchInlineSnapshot( + await expect(task()).rejects.toMatchInlineSnapshot( `[ResponseError: index_not_found_exception]` ); }); }); describe('cloneIndex', () => { - afterEach(async () => { + afterAll(async () => { try { - await client.indices.delete({ index: 'yellow_then_green_index' }); + await client.indices.delete({ index: 'clone_*' }); } catch (e) { /** ignore */ } }); - it('resolves right if cloning into a new target index', () => { - const task = cloneIndex(client, 'existing_index_with_write_block', 'yellow_then_green_index'); - expect(task()).resolves.toMatchInlineSnapshot(` + it('resolves right if cloning into a new target index', async () => { + expect.assertions(1); + const task = cloneIndex( + client, + 'existing_index_with_write_block', + 'clone_yellow_then_green_index_1' + ); + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", "right": Object { @@ -226,10 +240,11 @@ describe('migration actions', () => { } `); }); - it.skip('resolves right after waiting for index status to be green if clone target already existed', async () => { + it('resolves right after waiting for index status to be green if clone target already existed', async () => { + expect.assertions(2); // Create a yellow index await client.indices.create({ - index: 'yellow_then_green_index', + index: 'clone_yellow_then_green_index_2', body: { mappings: { properties: {} }, settings: { @@ -243,7 +258,7 @@ describe('migration actions', () => { const cloneIndexPromise = cloneIndex( client, 'existing_index_with_write_block', - 'yellow_then_green_index' + 'clone_yellow_then_green_index_2' )(); let indexGreen = false; @@ -258,7 +273,7 @@ describe('migration actions', () => { indexGreen = true; }, 10); - return cloneIndexPromise.then((res) => { + await cloneIndexPromise.then((res) => { // Assert that the promise didn't resolve before the index became green expect(indexGreen).toBe(true); expect(res).toMatchInlineSnapshot(` @@ -272,9 +287,10 @@ describe('migration actions', () => { `); }); }); - it('resolves left index_not_found_exception if the source index does not exist', () => { - const task = cloneIndex(client, 'no_such_index', 'yellow_then_green_index'); - expect(task()).resolves.toMatchInlineSnapshot(` + it('resolves left index_not_found_exception if the source index does not exist', async () => { + expect.assertions(1); + const task = cloneIndex(client, 'no_such_index', 'clone_yellow_then_green_index_3'); + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -289,6 +305,7 @@ describe('migration actions', () => { // Reindex doesn't return any errors on it's own, so we have to test // together with waitForReindexTask describe('reindex & waitForReindexTask', () => { + expect.assertions(2); it('resolves right when reindex succeeds without reindex script', async () => { const res = (await reindex( client, @@ -320,6 +337,7 @@ describe('migration actions', () => { `); }); it('resolves right when reindex succeeds with reindex script', async () => { + expect.assertions(2); const res = (await reindex( client, 'existing_index_with_docs', @@ -349,6 +367,7 @@ describe('migration actions', () => { `); }); it('resolves right, ignores version conflicts and does not update existing docs when reindex multiple times', async () => { + expect.assertions(3); // Reindex with a script let res = (await reindex( client, @@ -397,6 +416,7 @@ describe('migration actions', () => { `); }); it('resolves right and proceeds to add missing documents if there are some existing docs conflicts', async () => { + expect.assertions(2); // Simulate a reindex that only adds some of the documents from the // source index into the target index await createIndex(client, 'reindex_target_4', { properties: {} })(); @@ -444,6 +464,7 @@ describe('migration actions', () => { `); }); it('resolves left incompatible_mapping_exception if all reindex failures are due to a strict_dynamic_mapping_exception', async () => { + expect.assertions(1); // Simulates one instance having completed the UPDATE_TARGET_MAPPINGS // step which makes the mappings incompatible with outdated documents. // If another instance then tries a reindex it will get a @@ -479,6 +500,7 @@ describe('migration actions', () => { `); }); it('resolves left incompatible_mapping_exception if all reindex failures are due to a mapper_parsing_exception', async () => { + expect.assertions(1); // Simulates one instance having completed the UPDATE_TARGET_MAPPINGS // step which makes the mappings incompatible with outdated documents. // If another instance then tries a reindex it will get a @@ -512,6 +534,7 @@ describe('migration actions', () => { `); }); it('resolves left index_not_found_exception if source index does not exist', async () => { + expect.assertions(1); const res = (await reindex( client, 'no_such_index', @@ -520,7 +543,7 @@ describe('migration actions', () => { false )()) as Either.Right; const task = waitForReindexTask(client, res.right.taskId, '10s'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -531,6 +554,7 @@ describe('migration actions', () => { `); }); it('resolves left target_index_had_write_block if all failures are due to a write block', async () => { + expect.assertions(1); const res = (await reindex( client, 'existing_index_with_docs', @@ -541,7 +565,7 @@ describe('migration actions', () => { const task = waitForReindexTask(client, res.right.taskId, '10s'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -551,6 +575,7 @@ describe('migration actions', () => { `); }); it('resolves left if requireAlias=true and the target is not an alias', async () => { + expect.assertions(1); const res = (await reindex( client, 'existing_index_with_docs', @@ -561,7 +586,7 @@ describe('migration actions', () => { const task = waitForReindexTask(client, res.right.taskId, '10s'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -575,6 +600,7 @@ describe('migration actions', () => { describe('verifyReindex', () => { it('resolves right if source and target indices have the same amount of documents', async () => { + expect.assertions(1); const res = (await reindex( client, 'existing_index_with_docs', @@ -592,9 +618,10 @@ describe('migration actions', () => { } `); }); - it('resolves left if source and target indices have different amount of documents', () => { + it('resolves left if source and target indices have different amount of documents', async () => { + expect.assertions(1); const task = verifyReindex(client, 'existing_index_with_docs', 'existing_index_2'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -604,6 +631,7 @@ describe('migration actions', () => { `); }); it('rejects if source or target index does not exist', async () => { + expect.assertions(2); let task = verifyReindex(client, 'no_such_index', 'existing_index_2'); await expect(task()).rejects.toMatchInlineSnapshot( `[ResponseError: index_not_found_exception]` @@ -618,6 +646,7 @@ describe('migration actions', () => { describe('searchForOutdatedDocuments', () => { it('only returns documents that match the outdatedDocumentsQuery', async () => { + expect.assertions(2); const resultsWithQuery = ((await searchForOutdatedDocuments( client, 'existing_index_with_docs', @@ -635,6 +664,7 @@ describe('migration actions', () => { expect(resultsWithoutQuery.length).toBe(4); }); it('resolves with _id, _source, _seq_no and _primary_term', async () => { + expect.assertions(1); const results = ((await searchForOutdatedDocuments(client, 'existing_index_with_docs', { match: { title: { query: 'doc' } }, })()) as Either.Right).right.outdatedDocuments; @@ -655,6 +685,7 @@ describe('migration actions', () => { describe('waitForPickupUpdatedMappingsTask', () => { it('rejects if there are failures', async () => { + expect.assertions(1); const res = (await pickupUpdatedMappings( client, 'existing_index_with_write_block' @@ -664,11 +695,12 @@ describe('migration actions', () => { // We can't do a snapshot match because the response includes an index // id which ES assigns dynamically - return expect(task()).rejects.toMatchObject({ + await expect(task()).rejects.toMatchObject({ message: /pickupUpdatedMappings task failed with the following failures:\n\[\{\"index\":\"existing_index_with_write_block\"/, }); }); it('rejects if there is an error', async () => { + expect.assertions(1); const res = (await pickupUpdatedMappings( client, 'no_such_index' @@ -676,12 +708,13 @@ describe('migration actions', () => { const task = waitForPickupUpdatedMappingsTask(client, res.right.taskId, '10s'); - return expect(task()).rejects.toMatchInlineSnapshot(` + await expect(task()).rejects.toMatchInlineSnapshot(` [Error: pickupUpdatedMappings task failed with the following error: {"type":"index_not_found_exception","reason":"no such index [no_such_index]","resource.type":"index_or_alias","resource.id":"no_such_index","index_uuid":"_na_","index":"no_such_index"}] `); }); it('resolves right when successful', async () => { + expect.assertions(1); const res = (await pickupUpdatedMappings( client, 'existing_index_with_docs' @@ -689,7 +722,7 @@ describe('migration actions', () => { const task = waitForPickupUpdatedMappingsTask(client, res.right.taskId, '10s'); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", "right": "pickup_updated_mappings_succeeded", @@ -700,6 +733,7 @@ describe('migration actions', () => { describe('updateAndPickupMappings', () => { it('resolves right when mappings were updated and picked up', async () => { + expect.assertions(3); // Create an index without any mappings and insert documents into it await createIndex(client, 'existing_index_without_mappings', { dynamic: false as any, @@ -741,13 +775,14 @@ describe('migration actions', () => { 'existing_index_without_mappings', { match: { title: { query: 'doc' } } } )()) as Either.Right).right.outdatedDocuments; - return expect(pickedUpSearchResults.length).toBe(4); + expect(pickedUpSearchResults.length).toBe(4); }); }); describe('updateAliases', () => { describe('remove', () => { - it('resolves left index_not_found_exception when the index does not exist', () => { + it('resolves left index_not_found_exception when the index does not exist', async () => { + expect.assertions(1); const task = updateAliases(client, [ { remove: { @@ -757,7 +792,7 @@ describe('migration actions', () => { }, }, ]); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -769,6 +804,7 @@ describe('migration actions', () => { }); describe('with must_exist=false', () => { it('resolves left alias_not_found_exception when alias does not exist', async () => { + expect.assertions(1); const task = updateAliases(client, [ { remove: { @@ -778,7 +814,7 @@ describe('migration actions', () => { }, }, ]); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -790,6 +826,7 @@ describe('migration actions', () => { }); describe('with must_exist=true', () => { it('resolves left alias_not_found_exception when alias does not exist on specified index', async () => { + expect.assertions(1); const task = updateAliases(client, [ { remove: { @@ -799,7 +836,7 @@ describe('migration actions', () => { }, }, ]); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -809,6 +846,7 @@ describe('migration actions', () => { `); }); it('resolves left alias_not_found_exception when alias does not exist', async () => { + expect.assertions(1); const task = updateAliases(client, [ { remove: { @@ -818,7 +856,7 @@ describe('migration actions', () => { }, }, ]); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -830,7 +868,8 @@ describe('migration actions', () => { }); }); describe('remove_index', () => { - it('left index_not_found_exception if index does not exist', () => { + it('left index_not_found_exception if index does not exist', async () => { + expect.assertions(1); const task = updateAliases(client, [ { remove_index: { @@ -838,7 +877,7 @@ describe('migration actions', () => { }, }, ]); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -848,7 +887,8 @@ describe('migration actions', () => { } `); }); - it('left remove_index_not_a_concrete_index when remove_index targets an alias', () => { + it('left remove_index_not_a_concrete_index when remove_index targets an alias', async () => { + expect.assertions(1); const task = updateAliases(client, [ { remove_index: { @@ -856,7 +896,7 @@ describe('migration actions', () => { }, }, ]); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", "left": Object { @@ -872,7 +912,8 @@ describe('migration actions', () => { afterAll(async () => { await client.indices.delete({ index: 'yellow_then_green_index' }); }); - it.skip('resolves right after waiting for an index status to be green if the index already existed', async () => { + it('resolves right after waiting for an index status to be green if the index already existed', async () => { + expect.assertions(2); // Create a yellow index await client.indices.create( { @@ -903,7 +944,7 @@ describe('migration actions', () => { indexGreen = true; }, 10); - return createIndexPromise.then((res) => { + await createIndexPromise.then((res) => { // Assert that the promise didn't resolve before the index became green expect(indexGreen).toBe(true); expect(res).toMatchInlineSnapshot(` @@ -914,24 +955,26 @@ describe('migration actions', () => { `); }); }); - it('rejects when there is an unexpected error creating the index', () => { + it('rejects when there is an unexpected error creating the index', async () => { + expect.assertions(1); // Creating an index with the same name as an existing alias to induce // failure - expect( + await expect( createIndex(client, 'existing_index_2_alias', undefined as any)() ).rejects.toMatchInlineSnapshot(`[ResponseError: invalid_index_name_exception]`); }); }); describe('bulkOverwriteTransformedDocuments', () => { - it('resolves right when documents do not yet exist in the index', () => { + it('resolves right when documents do not yet exist in the index', async () => { + expect.assertions(1); const newDocs = ([ { _source: { title: 'doc 5' } }, { _source: { title: 'doc 6' } }, { _source: { title: 'doc 7' } }, ] as unknown) as SavedObjectsRawDoc[]; const task = bulkOverwriteTransformedDocuments(client, 'existing_index_with_docs', newDocs); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", "right": "bulk_index_succeeded", @@ -939,6 +982,7 @@ describe('migration actions', () => { `); }); it('resolves right even if there were some version_conflict_engine_exception', async () => { + expect.assertions(1); const existingDocs = ((await searchForOutdatedDocuments( client, 'existing_index_with_docs', @@ -949,20 +993,21 @@ describe('migration actions', () => { ...existingDocs, ({ _source: { title: 'doc 8' } } as unknown) as SavedObjectsRawDoc, ]); - return expect(task()).resolves.toMatchInlineSnapshot(` + await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", "right": "bulk_index_succeeded", } `); }); - it('rejects if there are errors', () => { + it('rejects if there are errors', async () => { + expect.assertions(1); const newDocs = ([ { _source: { title: 'doc 5' } }, { _source: { title: 'doc 6' } }, { _source: { title: 'doc 7' } }, ] as unknown) as SavedObjectsRawDoc[]; - return expect( + await expect( bulkOverwriteTransformedDocuments(client, 'existing_index_with_write_block', newDocs)() ).rejects.toMatchObject(expect.anything()); }); diff --git a/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts b/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts index 6dbb986e868e..2baf27e94edb 100644 --- a/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts +++ b/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts @@ -142,8 +142,8 @@ describe('migrationsStateActionMachine', () => { } `); }); - it('resolves when reaching the DONE state', () => { - return expect( + it('resolves when reaching the DONE state', async () => { + await expect( migrationStateActionMachine({ initialState, logger: mockLogger.get(), @@ -152,8 +152,8 @@ describe('migrationsStateActionMachine', () => { }) ).resolves.toEqual(expect.anything()); }); - it('resolves with migrated status if some sourceIndex in the DONE state', () => { - return expect( + it('resolves with migrated status if some sourceIndex in the DONE state', async () => { + await expect( migrationStateActionMachine({ initialState: { ...initialState, ...{ sourceIndex: Option.some('source-index') } }, logger: mockLogger.get(), @@ -162,8 +162,8 @@ describe('migrationsStateActionMachine', () => { }) ).resolves.toEqual(expect.objectContaining({ status: 'migrated' })); }); - it('resolves with patched status if none sourceIndex in the DONE state', () => { - return expect( + it('resolves with patched status if none sourceIndex in the DONE state', async () => { + await expect( migrationStateActionMachine({ initialState: { ...initialState, ...{ sourceIndex: Option.none } }, logger: mockLogger.get(), @@ -172,8 +172,8 @@ describe('migrationsStateActionMachine', () => { }) ).resolves.toEqual(expect.objectContaining({ status: 'patched' })); }); - it('rejects with error message when reaching the FATAL state', () => { - return expect( + it('rejects with error message when reaching the FATAL state', async () => { + await expect( migrationStateActionMachine({ initialState: { ...initialState, reason: 'the fatal reason' } as State, logger: mockLogger.get(), diff --git a/src/core/server/saved_objects/migrationsv2/state_action_machine.test.ts b/src/core/server/saved_objects/migrationsv2/state_action_machine.test.ts index 15dde10eb21e..3760b9259134 100644 --- a/src/core/server/saved_objects/migrationsv2/state_action_machine.test.ts +++ b/src/core/server/saved_objects/migrationsv2/state_action_machine.test.ts @@ -86,14 +86,14 @@ describe('state action machine', () => { }); }); - test('rejects if an exception is throw from inside an action', () => { - return expect( + test('rejects if an exception is throw from inside an action', async () => { + await expect( stateActionMachine({ ...state, controlState: 'THROW' }, next, countUntilThree) ).rejects.toThrowErrorMatchingInlineSnapshot(`"Invalid control state"`); }); - test('resolve with the final state once all steps are completed', () => { - return expect(finalStateP).resolves.toMatchInlineSnapshot(` + test('resolve with the final state once all steps are completed', async () => { + await expect(finalStateP).resolves.toMatchInlineSnapshot(` Object { "controlState": "DONE", "count": 3, @@ -101,8 +101,8 @@ describe('state action machine', () => { `); }); - test("rejects if control state doesn't change after 50 steps", () => { - return expect( + test("rejects if control state doesn't change after 50 steps", async () => { + await expect( stateActionMachine(state, next, countUntilModel(51)) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Control state didn't change after 50 steps aborting."` diff --git a/src/core/server/saved_objects/service/lib/errors.ts b/src/core/server/saved_objects/service/lib/errors.ts index e8836dbd8f7a..c6c8eee003e4 100644 --- a/src/core/server/saved_objects/service/lib/errors.ts +++ b/src/core/server/saved_objects/service/lib/errors.ts @@ -44,7 +44,7 @@ const CODE_GENERAL_ERROR = 'SavedObjectsClient/generalError'; const code = Symbol('SavedObjectsClientErrorCode'); -export interface DecoratedError extends Boom { +export interface DecoratedError extends Boom.Boom { [code]?: string; } diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 5f07a4b52305..cef5f33726ed 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -1541,7 +1541,7 @@ export type LegacyElasticsearchClientConfig = Pick id.startsWith('kibana-ciGroup')) .map((id) => id.replace(/^kibana-/, '')); -grunt.registerTask( - 'functionalTests:ensureAllTestsInCiGroup', - 'Check that all of the functional tests are in a CI group', - async function () { - const done = this.async(); - - try { - const result = await execa(process.execPath, [ - 'scripts/functional_test_runner', - ...TEST_TAGS.map((tag) => `--include-tag=${tag}`), - '--config', - 'test/functional/config.js', - '--test-stats', - ]); - const stats = JSON.parse(result.stderr); - - if (stats.excludedTests.length > 0) { - grunt.fail.fatal(` +run(async ({ log }) => { + try { + const result = await execa(process.execPath, [ + 'scripts/functional_test_runner', + ...TEST_TAGS.map((tag) => `--include-tag=${tag}`), + '--config', + 'test/functional/config.js', + '--test-stats', + ]); + const stats = JSON.parse(result.stderr); + + if (stats.excludedTests.length > 0) { + log.error(` ${stats.excludedTests.length} tests are excluded by the ciGroup tags, make sure that all test suites have a "ciGroup{X}" tag and that "tasks/functional_test_groups.js" knows about the tag that you are using. @@ -55,12 +51,11 @@ grunt.registerTask( - ${stats.excludedTests.join('\n - ')} `); - return; - } - - done(); - } catch (error) { - grunt.fail.fatal(error.stack); + process.exitCode = 1; + return; } + } catch (error) { + log.error(error.stack); + process.exitCode = 1; } -); +}); diff --git a/src/dev/run_find_plugins_with_circular_deps.ts b/src/dev/run_find_plugins_with_circular_deps.ts index f4662820a1fb..5afb8df8502d 100644 --- a/src/dev/run_find_plugins_with_circular_deps.ts +++ b/src/dev/run_find_plugins_with_circular_deps.ts @@ -31,15 +31,7 @@ interface Options { type CircularDepList = Set; const allowedList: CircularDepList = new Set([ - 'src/plugins/charts -> src/plugins/expressions', - 'src/plugins/charts -> src/plugins/vis_default_editor', - 'src/plugins/data -> src/plugins/embeddable', - 'src/plugins/data -> src/plugins/expressions', - 'src/plugins/data -> src/plugins/ui_actions', - 'src/plugins/embeddable -> src/plugins/ui_actions', - 'src/plugins/expressions -> src/plugins/visualizations', 'src/plugins/vis_default_editor -> src/plugins/visualizations', - 'src/plugins/vis_default_editor -> src/plugins/visualize', 'src/plugins/visualizations -> src/plugins/visualize', 'x-pack/plugins/actions -> x-pack/plugins/case', 'x-pack/plugins/case -> x-pack/plugins/security_solution', diff --git a/src/plugins/apm_oss/server/tutorial/index_pattern.json b/src/plugins/apm_oss/server/tutorial/index_pattern.json index b9f3b43b67b8..6eb040f2758a 100644 --- a/src/plugins/apm_oss/server/tutorial/index_pattern.json +++ b/src/plugins/apm_oss/server/tutorial/index_pattern.json @@ -1,7 +1,7 @@ { "attributes": { "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.limit.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.usage.bytes\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", - "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.build.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reason\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.url\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"file.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hosts\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.author\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.client.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.server.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.limit.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.usage.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"child.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.cls\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.fid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.tbt\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.sum\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.max\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.histogram\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"metricset.period\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", + "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.build.original\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.original_file_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reason\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.url\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.original_file_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"file.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.file.path\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.original_file_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.original_file_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.original_file_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hosts\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.author\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.client.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.server.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.limit.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.usage.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"child.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.cls\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.fid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.tbt\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.sum\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.max\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.histogram\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"metricset.period\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", "sourceFilters": "[{\"value\":\"sourcemap.sourcemap\"}]", "timeFieldName": "@timestamp" }, diff --git a/src/plugins/charts/kibana.json b/src/plugins/charts/kibana.json index a6d4dbba7238..4510a1ea7d06 100644 --- a/src/plugins/charts/kibana.json +++ b/src/plugins/charts/kibana.json @@ -3,6 +3,5 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["expressions"], - "requiredBundles": ["visDefaultEditor"] + "requiredPlugins": ["expressions"] } diff --git a/src/plugins/charts/public/services/legacy_colors/colors.test.ts b/src/plugins/charts/public/services/legacy_colors/colors.test.ts index 89cf7a481737..b94918426c52 100644 --- a/src/plugins/charts/public/services/legacy_colors/colors.test.ts +++ b/src/plugins/charts/public/services/legacy_colors/colors.test.ts @@ -62,14 +62,17 @@ describe('Vislib Color Service', () => { it('should throw an error if input is not an array', () => { expect(() => { + // @ts-expect-error colors.createColorLookupFunction(200); }).toThrowError(); expect(() => { + // @ts-expect-error colors.createColorLookupFunction('help'); }).toThrowError(); expect(() => { + // @ts-expect-error colors.createColorLookupFunction(true); }).toThrowError(); @@ -78,10 +81,12 @@ describe('Vislib Color Service', () => { }).toThrowError(); expect(() => { + // @ts-expect-error colors.createColorLookupFunction(nullValue); }).toThrowError(); expect(() => { + // @ts-expect-error colors.createColorLookupFunction(emptyObject); }).toThrowError(); }); @@ -89,14 +94,17 @@ describe('Vislib Color Service', () => { describe('when array is not composed of numbers, strings, or undefined values', () => { it('should throw an error', () => { expect(() => { + // @ts-expect-error colors.createColorLookupFunction(arrayOfObjects); }).toThrowError(); expect(() => { + // @ts-expect-error colors.createColorLookupFunction(arrayOfBooleans); }).toThrowError(); expect(() => { + // @ts-expect-error colors.createColorLookupFunction(arrayOfNullValues); }).toThrowError(); }); @@ -113,6 +121,7 @@ describe('Vislib Color Service', () => { }).not.toThrowError(); expect(() => { + // @ts-expect-error colors.createColorLookupFunction(arrayOfUndefinedValues); }).not.toThrowError(); }); diff --git a/src/plugins/charts/public/services/legacy_colors/colors.ts b/src/plugins/charts/public/services/legacy_colors/colors.ts index e1342a114f8d..e367a780fb29 100644 --- a/src/plugins/charts/public/services/legacy_colors/colors.ts +++ b/src/plugins/charts/public/services/legacy_colors/colors.ts @@ -48,7 +48,7 @@ export class LegacyColorsService { } createColorLookupFunction( - arrayOfStringsOrNumbers?: any, + arrayOfStringsOrNumbers?: Array, colorMapping: Partial> = {} ) { if (!Array.isArray(arrayOfStringsOrNumbers)) { @@ -67,7 +67,7 @@ export class LegacyColorsService { this.mappedColors.mapKeys(arrayOfStringsOrNumbers); - return (value: string) => { + return (value: string | number) => { return colorMapping[value] || this.mappedColors.get(value); }; } diff --git a/src/plugins/charts/public/services/mapped_colors/mapped_colors.ts b/src/plugins/charts/public/services/mapped_colors/mapped_colors.ts index 2934d4208d22..7848cdd3f314 100644 --- a/src/plugins/charts/public/services/mapped_colors/mapped_colors.ts +++ b/src/plugins/charts/public/services/mapped_colors/mapped_colors.ts @@ -37,15 +37,15 @@ export class MappedColors { private _mapping: any; constructor( - private uiSettings: CoreSetup['uiSettings'], + private uiSettings?: CoreSetup['uiSettings'], private colorPaletteFn: (num: number) => string[] = createColorPalette ) { this._oldMap = {}; this._mapping = {}; } - private getConfigColorMapping() { - return _.mapValues(this.uiSettings.get(COLOR_MAPPING_SETTING), standardizeColor); + private getConfigColorMapping(): Record { + return _.mapValues(this.uiSettings?.get(COLOR_MAPPING_SETTING) || {}, standardizeColor); } public get oldMap(): any { diff --git a/src/plugins/charts/public/services/palettes/palettes.test.tsx b/src/plugins/charts/public/services/palettes/palettes.test.tsx index 5d9337f1ee68..7356f13fddf9 100644 --- a/src/plugins/charts/public/services/palettes/palettes.test.tsx +++ b/src/plugins/charts/public/services/palettes/palettes.test.tsx @@ -18,9 +18,11 @@ */ import { coreMock } from '../../../../../core/public/mocks'; +import { createColorPalette as createLegacyColorPalette } from '../../../../../../src/plugins/charts/public'; import { PaletteDefinition } from './types'; import { buildPalettes } from './palettes'; import { colorsServiceMock } from '../legacy_colors/mock'; +import { euiPaletteColorBlind, euiPaletteColorBlindBehindText } from '@elastic/eui'; describe('palettes', () => { const palettes: Record = buildPalettes( @@ -28,79 +30,257 @@ describe('palettes', () => { colorsServiceMock ); describe('default palette', () => { - it('should return different colors based on behind text flag', () => { - const palette = palettes.default; + describe('syncColors: false', () => { + it('should return different colors based on behind text flag', () => { + const palette = palettes.default; - const color1 = palette.getColor([ - { - name: 'abc', - rankAtDepth: 0, - totalSeriesAtDepth: 5, - }, - ]); - const color2 = palette.getColor( - [ + const color1 = palette.getColor([ { name: 'abc', rankAtDepth: 0, totalSeriesAtDepth: 5, }, - ], - { - behindText: true, - } - ); - expect(color1).not.toEqual(color2); - }); + ]); + const color2 = palette.getColor( + [ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + ], + { + behindText: true, + } + ); + expect(color1).not.toEqual(color2); + }); - it('should return different colors based on rank at current series', () => { - const palette = palettes.default; + it('should return different colors based on rank at current series', () => { + const palette = palettes.default; - const color1 = palette.getColor([ - { - name: 'abc', - rankAtDepth: 0, - totalSeriesAtDepth: 5, - }, - ]); - const color2 = palette.getColor([ - { - name: 'abc', - rankAtDepth: 1, - totalSeriesAtDepth: 5, - }, - ]); - expect(color1).not.toEqual(color2); + const color1 = palette.getColor([ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + ]); + const color2 = palette.getColor([ + { + name: 'abc', + rankAtDepth: 1, + totalSeriesAtDepth: 5, + }, + ]); + expect(color1).not.toEqual(color2); + }); + + it('should return the same color for different positions on outer series layers', () => { + const palette = palettes.default; + + const color1 = palette.getColor([ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + { + name: 'def', + rankAtDepth: 0, + totalSeriesAtDepth: 2, + }, + ]); + const color2 = palette.getColor([ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + { + name: 'ghj', + rankAtDepth: 1, + totalSeriesAtDepth: 1, + }, + ]); + expect(color1).toEqual(color2); + }); }); - it('should return the same color for different positions on outer series layers', () => { - const palette = palettes.default; + describe('syncColors: true', () => { + it('should return different colors based on behind text flag', () => { + const palette = palettes.default; - const color1 = palette.getColor([ - { - name: 'abc', - rankAtDepth: 0, - totalSeriesAtDepth: 5, - }, - { - name: 'def', - rankAtDepth: 0, - totalSeriesAtDepth: 2, - }, - ]); - const color2 = palette.getColor([ - { - name: 'abc', - rankAtDepth: 0, - totalSeriesAtDepth: 5, - }, - { - name: 'ghj', - rankAtDepth: 1, - totalSeriesAtDepth: 1, - }, - ]); - expect(color1).toEqual(color2); + const color1 = palette.getColor( + [ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + ], + { + syncColors: true, + } + ); + const color2 = palette.getColor( + [ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + ], + { + behindText: true, + syncColors: true, + } + ); + expect(color1).not.toEqual(color2); + }); + + it('should return different colors for different keys', () => { + const palette = palettes.default; + + const color1 = palette.getColor( + [ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + ], + { + syncColors: true, + } + ); + const color2 = palette.getColor( + [ + { + name: 'def', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + ], + { + syncColors: true, + } + ); + expect(color1).not.toEqual(color2); + }); + + it('should return the same color for the same key, irregardless of rank', () => { + const palette = palettes.default; + + const color1 = palette.getColor( + [ + { + name: 'hij', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + ], + { + syncColors: true, + } + ); + const color2 = palette.getColor( + [ + { + name: 'hij', + rankAtDepth: 5, + totalSeriesAtDepth: 5, + }, + ], + { + syncColors: true, + } + ); + expect(color1).toEqual(color2); + }); + + it('should return the same color for different positions on outer series layers', () => { + const palette = palettes.default; + + const color1 = palette.getColor( + [ + { + name: 'klm', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + { + name: 'def', + rankAtDepth: 0, + totalSeriesAtDepth: 2, + }, + ], + { + syncColors: true, + } + ); + const color2 = palette.getColor( + [ + { + name: 'klm', + rankAtDepth: 3, + totalSeriesAtDepth: 5, + }, + { + name: 'ghj', + rankAtDepth: 1, + totalSeriesAtDepth: 1, + }, + ], + { + syncColors: true, + } + ); + expect(color1).toEqual(color2); + }); + + it('should return the same index of the behind text palette for same key', () => { + const palette = palettes.default; + + const color1 = palette.getColor( + [ + { + name: 'klm', + rankAtDepth: 0, + totalSeriesAtDepth: 5, + }, + { + name: 'def', + rankAtDepth: 0, + totalSeriesAtDepth: 2, + }, + ], + { + syncColors: true, + } + ); + const color2 = palette.getColor( + [ + { + name: 'klm', + rankAtDepth: 3, + totalSeriesAtDepth: 5, + }, + { + name: 'ghj', + rankAtDepth: 1, + totalSeriesAtDepth: 1, + }, + ], + { + syncColors: true, + behindText: true, + } + ); + const color1Index = euiPaletteColorBlind({ rotations: 2 }).indexOf(color1!); + const color2Index = euiPaletteColorBlindBehindText({ rotations: 2 }).indexOf(color2!); + expect(color1Index).toEqual(color2Index); + }); }); }); @@ -136,35 +316,87 @@ describe('palettes', () => { (colorsServiceMock.mappedColors.get as jest.Mock).mockClear(); }); - it('should query legacy color service', () => { - palette.getColor([ - { - name: 'abc', - rankAtDepth: 0, - totalSeriesAtDepth: 10, - }, - ]); - expect(colorsServiceMock.mappedColors.mapKeys).toHaveBeenCalledWith(['abc']); - expect(colorsServiceMock.mappedColors.get).toHaveBeenCalledWith('abc'); + describe('syncColors: false', () => { + it('should not query legacy color service', () => { + palette.getColor( + [ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 10, + }, + ], + { + syncColors: false, + } + ); + expect(colorsServiceMock.mappedColors.mapKeys).not.toHaveBeenCalled(); + expect(colorsServiceMock.mappedColors.get).not.toHaveBeenCalled(); + }); + + it('should return a color from the legacy palette based on position of first series', () => { + const result = palette.getColor( + [ + { + name: 'abc', + rankAtDepth: 2, + totalSeriesAtDepth: 10, + }, + { + name: 'def', + rankAtDepth: 0, + totalSeriesAtDepth: 10, + }, + ], + { + syncColors: false, + } + ); + expect(result).toEqual(createLegacyColorPalette(20)[2]); + }); }); - it('should always use root series', () => { - palette.getColor([ - { - name: 'abc', - rankAtDepth: 0, - totalSeriesAtDepth: 10, - }, - { - name: 'def', - rankAtDepth: 0, - totalSeriesAtDepth: 10, - }, - ]); - expect(colorsServiceMock.mappedColors.mapKeys).toHaveBeenCalledTimes(1); - expect(colorsServiceMock.mappedColors.mapKeys).toHaveBeenCalledWith(['abc']); - expect(colorsServiceMock.mappedColors.get).toHaveBeenCalledTimes(1); - expect(colorsServiceMock.mappedColors.get).toHaveBeenCalledWith('abc'); + describe('syncColors: true', () => { + it('should query legacy color service', () => { + palette.getColor( + [ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 10, + }, + ], + { + syncColors: true, + } + ); + expect(colorsServiceMock.mappedColors.mapKeys).toHaveBeenCalledWith(['abc']); + expect(colorsServiceMock.mappedColors.get).toHaveBeenCalledWith('abc'); + }); + + it('should always use root series', () => { + palette.getColor( + [ + { + name: 'abc', + rankAtDepth: 0, + totalSeriesAtDepth: 10, + }, + { + name: 'def', + rankAtDepth: 0, + totalSeriesAtDepth: 10, + }, + ], + { + syncColors: true, + } + ); + expect(colorsServiceMock.mappedColors.mapKeys).toHaveBeenCalledTimes(1); + expect(colorsServiceMock.mappedColors.mapKeys).toHaveBeenCalledWith(['abc']); + expect(colorsServiceMock.mappedColors.get).toHaveBeenCalledTimes(1); + expect(colorsServiceMock.mappedColors.get).toHaveBeenCalledWith('abc'); + }); }); }); diff --git a/src/plugins/charts/public/services/palettes/palettes.tsx b/src/plugins/charts/public/services/palettes/palettes.tsx index c1fd7c3cc739..ffb237904b36 100644 --- a/src/plugins/charts/public/services/palettes/palettes.tsx +++ b/src/plugins/charts/public/services/palettes/palettes.tsx @@ -28,26 +28,45 @@ import { euiPaletteNegative, euiPalettePositive, euiPaletteWarm, - euiPaletteColorBlindBehindText, euiPaletteForStatus, euiPaletteForTemperature, euiPaletteComplimentary, + euiPaletteColorBlindBehindText, } from '@elastic/eui'; -import { ChartsPluginSetup } from '../../../../../../src/plugins/charts/public'; +import { flatten, zip } from 'lodash'; +import { + ChartsPluginSetup, + createColorPalette as createLegacyColorPalette, +} from '../../../../../../src/plugins/charts/public'; import { lightenColor } from './lighten_color'; import { ChartColorConfiguration, PaletteDefinition, SeriesLayer } from './types'; import { LegacyColorsService } from '../legacy_colors'; +import { MappedColors } from '../mapped_colors'; function buildRoundRobinCategoricalWithMappedColors(): Omit { const colors = euiPaletteColorBlind({ rotations: 2 }); const behindTextColors = euiPaletteColorBlindBehindText({ rotations: 2 }); + const behindTextColorMap: Record = Object.fromEntries( + zip(colors, behindTextColors) + ); + const mappedColors = new MappedColors(undefined, (num: number) => { + return flatten(new Array(Math.ceil(num / 10)).fill(colors)).map((color) => color.toLowerCase()); + }); function getColor( series: SeriesLayer[], chartConfiguration: ChartColorConfiguration = { behindText: false } ) { - const outputColor = chartConfiguration.behindText - ? behindTextColors[series[0].rankAtDepth % behindTextColors.length] - : colors[series[0].rankAtDepth % colors.length]; + let outputColor: string; + if (chartConfiguration.syncColors) { + const colorKey = series[0].name; + mappedColors.mapKeys([colorKey]); + const mappedColor = mappedColors.get(colorKey); + outputColor = chartConfiguration.behindText ? behindTextColorMap[mappedColor] : mappedColor; + } else { + outputColor = chartConfiguration.behindText + ? behindTextColors[series[0].rankAtDepth % behindTextColors.length] + : colors[series[0].rankAtDepth % colors.length]; + } if (!chartConfiguration.maxDepth || chartConfiguration.maxDepth === 1) { return outputColor; @@ -115,9 +134,15 @@ function buildGradient( function buildSyncedKibanaPalette( colors: ChartsPluginSetup['legacyColors'] ): Omit { + const staticColors = createLegacyColorPalette(20); function getColor(series: SeriesLayer[], chartConfiguration: ChartColorConfiguration = {}) { - colors.mappedColors.mapKeys([series[0].name]); - const outputColor = colors.mappedColors.get(series[0].name); + let outputColor: string; + if (chartConfiguration.syncColors) { + colors.mappedColors.mapKeys([series[0].name]); + outputColor = colors.mappedColors.get(series[0].name); + } else { + outputColor = staticColors[series[0].rankAtDepth % staticColors.length]; + } if (!chartConfiguration.maxDepth || chartConfiguration.maxDepth === 1) { return outputColor; diff --git a/src/plugins/charts/public/services/palettes/types.ts b/src/plugins/charts/public/services/palettes/types.ts index f92bcb4bd082..15989578518f 100644 --- a/src/plugins/charts/public/services/palettes/types.ts +++ b/src/plugins/charts/public/services/palettes/types.ts @@ -55,6 +55,11 @@ export interface ChartColorConfiguration { * adjust colors for better a11y. Might be ignored depending on the palette. */ behindText?: boolean; + /** + * Flag whether a color assignment to a given key should be remembered and re-used the next time the key shows up. + * This setting might be ignored based on the palette. + */ + syncColors?: boolean; } /** diff --git a/src/plugins/charts/public/static/components/collections.ts b/src/plugins/charts/public/static/components/collections.ts index 9dde50f2b44c..16d875836a20 100644 --- a/src/plugins/charts/public/static/components/collections.ts +++ b/src/plugins/charts/public/static/components/collections.ts @@ -18,17 +18,22 @@ */ import { $Values } from '@kbn/utility-types'; +import { i18n } from '@kbn/i18n'; -export const ColorModes = Object.freeze({ - BACKGROUND: 'Background' as 'Background', - LABELS: 'Labels' as 'Labels', - NONE: 'None' as 'None', +export const ColorMode = Object.freeze({ + Background: 'Background' as 'Background', + Labels: 'Labels' as 'Labels', + None: 'None' as 'None', }); -export type ColorModes = $Values; +export type ColorMode = $Values; -export const Rotates = Object.freeze({ - HORIZONTAL: 0, - VERTICAL: 90, - ANGLED: 75, +export const LabelRotation = Object.freeze({ + Horizontal: 0, + Vertical: 90, + Angled: 75, +}); +export type LabelRotation = $Values; + +export const defaultCountLabel = i18n.translate('charts.countText', { + defaultMessage: 'Count', }); -export type Rotates = $Values; diff --git a/src/plugins/charts/public/static/components/color_picker.scss b/src/plugins/charts/public/static/components/color_picker.scss new file mode 100644 index 000000000000..85bfefca41a0 --- /dev/null +++ b/src/plugins/charts/public/static/components/color_picker.scss @@ -0,0 +1,18 @@ +$visColorPickerWidth: $euiSizeL * 8; // 8 columns + +.visColorPicker__value { + width: $visColorPickerWidth; +} + +.visColorPicker__valueDot { + cursor: pointer; + + &:hover { + transform: scale(1.4); + } + + &-isSelected { + border: $euiSizeXS solid; + border-radius: 100%; + } +} diff --git a/src/plugins/charts/public/static/components/color_picker.tsx b/src/plugins/charts/public/static/components/color_picker.tsx new file mode 100644 index 000000000000..d785a9c9ad4b --- /dev/null +++ b/src/plugins/charts/public/static/components/color_picker.tsx @@ -0,0 +1,138 @@ +/* + * 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 classNames from 'classnames'; +import React, { BaseSyntheticEvent } from 'react'; + +import { EuiButtonEmpty, EuiFlexItem, EuiIcon } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import './color_picker.scss'; + +export const legendColors: string[] = [ + '#3F6833', + '#967302', + '#2F575E', + '#99440A', + '#58140C', + '#052B51', + '#511749', + '#3F2B5B', + '#508642', + '#CCA300', + '#447EBC', + '#C15C17', + '#890F02', + '#0A437C', + '#6D1F62', + '#584477', + '#629E51', + '#E5AC0E', + '#64B0C8', + '#E0752D', + '#BF1B00', + '#0A50A1', + '#962D82', + '#614D93', + '#7EB26D', + '#EAB839', + '#6ED0E0', + '#EF843C', + '#E24D42', + '#1F78C1', + '#BA43A9', + '#705DA0', + '#9AC48A', + '#F2C96D', + '#65C5DB', + '#F9934E', + '#EA6460', + '#5195CE', + '#D683CE', + '#806EB7', + '#B7DBAB', + '#F4D598', + '#70DBED', + '#F9BA8F', + '#F29191', + '#82B5D8', + '#E5A8E2', + '#AEA2E0', + '#E0F9D7', + '#FCEACA', + '#CFFAFF', + '#F9E2D2', + '#FCE2DE', + '#BADFF4', + '#F9D9F9', + '#DEDAF7', +]; + +interface ColorPickerProps { + id?: string; + label: string | number | null; + onChange: (color: string | null, event: BaseSyntheticEvent) => void; + color: string; +} + +export const ColorPicker = ({ onChange, color: selectedColor, id, label }: ColorPickerProps) => ( +
+ + + +
+ {legendColors.map((color) => ( + onChange(color, e)} + onKeyPress={(e) => onChange(color, e)} + className={classNames('visColorPicker__valueDot', { + // eslint-disable-next-line @typescript-eslint/naming-convention + 'visColorPicker__valueDot-isSelected': color === selectedColor, + })} + style={{ color }} + data-test-subj={`visColorPickerColor-${color}`} + /> + ))} +
+ {legendColors.some((c) => c === selectedColor) && ( + + onChange(null, e)} + onKeyPress={(e: any) => onChange(null, e)} + > + + + + )} +
+); diff --git a/src/plugins/charts/public/static/components/current_time.tsx b/src/plugins/charts/public/static/components/current_time.tsx new file mode 100644 index 000000000000..00c1a74a7bfd --- /dev/null +++ b/src/plugins/charts/public/static/components/current_time.tsx @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import moment, { Moment } from 'moment'; +import React, { FC } from 'react'; + +import { LineAnnotation, AnnotationDomainTypes, LineAnnotationStyle } from '@elastic/charts'; +import lightEuiTheme from '@elastic/eui/dist/eui_theme_light.json'; +import darkEuiTheme from '@elastic/eui/dist/eui_theme_dark.json'; + +interface CurrentTimeProps { + isDarkMode: boolean; + domainEnd?: number | Moment; +} + +/** + * Render current time line annotation on @elastic/charts `Chart` + */ +export const CurrentTime: FC = ({ isDarkMode, domainEnd }) => { + const lineAnnotationStyle: Partial = { + line: { + strokeWidth: 2, + stroke: isDarkMode ? darkEuiTheme.euiColorDanger : lightEuiTheme.euiColorDanger, + opacity: 0.7, + }, + }; + + // Domain end of 'now' will be milliseconds behind current time, so we extend time by 1 minute and check if + // the annotation is within this range; if so, the line annotation uses the domainEnd as its value + const now = moment(); + const isAnnotationAtEdge = domainEnd + ? moment(domainEnd).add(1, 'm').isAfter(now) && now.isAfter(domainEnd) + : false; + const lineAnnotationData = [ + { + dataValue: isAnnotationAtEdge ? domainEnd : now.valueOf(), + }, + ]; + + return ( + + ); +}; diff --git a/src/plugins/charts/public/static/components/endzones.tsx b/src/plugins/charts/public/static/components/endzones.tsx new file mode 100644 index 000000000000..db68f72c18c0 --- /dev/null +++ b/src/plugins/charts/public/static/components/endzones.tsx @@ -0,0 +1,197 @@ +/* + * 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, { FC } from 'react'; +import moment, { unitOfTime } from 'moment'; + +import { + TooltipValue, + RectAnnotation, + RectAnnotationDatum, + RectAnnotationStyle, +} from '@elastic/charts'; +import { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer } from '@elastic/eui'; +import lightEuiTheme from '@elastic/eui/dist/eui_theme_light.json'; +import darkEuiTheme from '@elastic/eui/dist/eui_theme_dark.json'; + +interface EndzonesProps { + isDarkMode: boolean; + domainStart: number; + domainEnd: number; + interval: number; + domainMin: number; + domainMax: number; + hideTooltips?: boolean; + /** + * used to toggle full bin endzones for multiple non-stacked bars + */ + isFullBin?: boolean; +} + +export const Endzones: FC = ({ + isDarkMode, + domainStart, + domainEnd, + interval, + domainMin, + domainMax, + hideTooltips = true, + isFullBin = false, +}) => { + const rectAnnotationStyle: Partial = { + stroke: isDarkMode ? darkEuiTheme.euiColorLightShade : lightEuiTheme.euiColorDarkShade, + strokeWidth: 0, + opacity: isDarkMode ? 0.6 : 0.2, + fill: isDarkMode ? darkEuiTheme.euiColorLightShade : lightEuiTheme.euiColorDarkShade, + }; + + const rectAnnotations: RectAnnotationDatum[] = []; + + if (domainStart > domainMin) { + rectAnnotations.push({ + coordinates: { + x1: isFullBin ? domainMin : domainStart, + }, + }); + } + + if (domainEnd - interval < domainMax) { + rectAnnotations.push({ + coordinates: { + x0: isFullBin ? domainMax : domainEnd, + }, + }); + } + + return ( + + ); +}; + +const findIntervalFromDuration = ( + dateValue: number, + esValue: number, + esUnit: unitOfTime.Base, + timeZone: string +) => { + const date = moment.tz(dateValue, timeZone); + const startOfDate = moment.tz(date, timeZone).startOf(esUnit); + const endOfDate = moment.tz(date, timeZone).startOf(esUnit).add(esValue, esUnit); + return endOfDate.valueOf() - startOfDate.valueOf(); +}; + +const getIntervalInMs = ( + value: number, + esValue: number, + esUnit: unitOfTime.Base, + timeZone: string +): number => { + switch (esUnit) { + case 's': + return 1000 * esValue; + case 'ms': + return 1 * esValue; + default: + return findIntervalFromDuration(value, esValue, esUnit, timeZone); + } +}; + +/** + * Returns the adjusted interval based on the data + * + * @param xValues sorted and unquie x values + * @param esValue + * @param esUnit + * @param timeZone + */ +export const getAdjustedInterval = ( + xValues: number[], + esValue: number, + esUnit: unitOfTime.Base, + timeZone: string +): number => { + const newInterval = xValues.reduce((minInterval, currentXvalue, index) => { + let currentDiff = minInterval; + + if (index > 0) { + currentDiff = Math.abs(xValues[index - 1] - currentXvalue); + } + + const singleUnitInterval = getIntervalInMs(currentXvalue, esValue, esUnit, timeZone); + return Math.min(minInterval, singleUnitInterval, currentDiff); + }, Number.MAX_SAFE_INTEGER); + + return newInterval > 0 ? newInterval : moment.duration(esValue, esUnit).asMilliseconds(); +}; + +const partialDataText = i18n.translate('charts.partialData.bucketTooltipText', { + defaultMessage: + 'The selected time range does not include this entire bucket. It might contain partial data.', +}); + +const Prompt = () => ( + + + + + {partialDataText} + +); + +export const renderEndzoneTooltip = ( + xInterval?: number, + domainStart?: number, + domainEnd?: number, + formatter?: (v: any) => string, + renderValue = true +) => (headerData: TooltipValue): JSX.Element | string => { + const headerDataValue = headerData.value; + const formattedValue = formatter ? formatter(headerDataValue) : headerDataValue; + + if ( + (domainStart !== undefined && domainStart > headerDataValue) || + (domainEnd !== undefined && xInterval !== undefined && domainEnd - xInterval < headerDataValue) + ) { + return ( + <> + + {renderValue && ( + <> + +

{formattedValue}

+ + )} + + ); + } + + return renderValue ? formattedValue : null; +}; diff --git a/src/plugins/charts/public/static/components/index.ts b/src/plugins/charts/public/static/components/index.ts index 48c9e4014548..0d5d7bf3ba27 100644 --- a/src/plugins/charts/public/static/components/index.ts +++ b/src/plugins/charts/public/static/components/index.ts @@ -17,14 +17,9 @@ * under the License. */ -export { BasicOptions } from './basic_options'; -export { ColorModes, Rotates } from './collections'; -export { ColorRanges, SetColorRangeValue } from './color_ranges'; -export { ColorSchemaOptions, SetColorSchemaOptionsValue } from './color_schema'; +export { ColorMode, LabelRotation, defaultCountLabel } from './collections'; export { ColorSchemaParams, Labels, Style } from './types'; -export { NumberInputOption } from './number_input'; -export { RangeOption } from './range'; -export { RequiredNumberInputOption } from './required_number_input'; -export { SelectOption } from './select'; -export { SwitchOption } from './switch'; -export { TextInputOption } from './text_input'; +export { LegendToggle } from './legend_toggle'; +export { ColorPicker } from './color_picker'; +export { CurrentTime } from './current_time'; +export * from './endzones'; diff --git a/src/plugins/charts/public/static/components/legend_toggle.scss b/src/plugins/charts/public/static/components/legend_toggle.scss new file mode 100644 index 000000000000..7eb85a5e08ec --- /dev/null +++ b/src/plugins/charts/public/static/components/legend_toggle.scss @@ -0,0 +1,20 @@ +.echLegend__toggle { + position: absolute; + bottom: 0; + left: 0; + z-index: 1; + margin: $euiSizeXS; + + &--isOpen { + background-color: $euiColorLightestShade; + } + + &--position-left, + &--position-bottom { + left: auto; + bottom: auto; + right: 0; + top: 0; + } +} + diff --git a/src/plugins/charts/public/static/components/legend_toggle.tsx b/src/plugins/charts/public/static/components/legend_toggle.tsx new file mode 100644 index 000000000000..12742b6da6e6 --- /dev/null +++ b/src/plugins/charts/public/static/components/legend_toggle.tsx @@ -0,0 +1,62 @@ +/* + * 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, { memo, useMemo } from 'react'; +import classNames from 'classnames'; + +import { i18n } from '@kbn/i18n'; +import { htmlIdGenerator, EuiButtonIcon } from '@elastic/eui'; +import { Position } from '@elastic/charts'; + +import './legend_toggle.scss'; + +interface LegendToggleProps { + onClick: () => void; + showLegend: boolean; + legendPosition: Position; +} + +const LegendToggleComponent = ({ onClick, showLegend, legendPosition }: LegendToggleProps) => { + const legendId = useMemo(() => htmlIdGenerator()('legend'), []); + + return ( + + ); +}; + +export const LegendToggle = memo(LegendToggleComponent); diff --git a/src/plugins/charts/public/static/components/types.ts b/src/plugins/charts/public/static/components/types.ts index 196eb60b06ae..a4c384141daf 100644 --- a/src/plugins/charts/public/static/components/types.ts +++ b/src/plugins/charts/public/static/components/types.ts @@ -18,7 +18,7 @@ */ import { ColorSchemas } from '../color_maps'; -import { Rotates } from './collections'; +import { LabelRotation } from './collections'; export interface ColorSchemaParams { colorSchema: ColorSchemas; @@ -29,8 +29,8 @@ export interface Labels { color?: string; filter?: boolean; overwriteColor?: boolean; - rotate?: Rotates; - show: boolean; + rotate?: LabelRotation; + show?: boolean; truncate?: number | null; } diff --git a/src/plugins/charts/public/static/index.ts b/src/plugins/charts/public/static/index.ts index b8a8406c375d..638e119d8be4 100644 --- a/src/plugins/charts/public/static/index.ts +++ b/src/plugins/charts/public/static/index.ts @@ -20,3 +20,4 @@ export * from './color_maps'; export * from './colors'; export * from './components'; +export * from './utils'; diff --git a/src/plugins/charts/public/static/utils/index.ts b/src/plugins/charts/public/static/utils/index.ts new file mode 100644 index 000000000000..777deb326125 --- /dev/null +++ b/src/plugins/charts/public/static/utils/index.ts @@ -0,0 +1,20 @@ +/* + * 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 * from './transform_click_event'; diff --git a/src/plugins/charts/public/static/utils/transform_click_event.ts b/src/plugins/charts/public/static/utils/transform_click_event.ts new file mode 100644 index 000000000000..21460eb51e3f --- /dev/null +++ b/src/plugins/charts/public/static/utils/transform_click_event.ts @@ -0,0 +1,238 @@ +/* + * 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 { + XYChartSeriesIdentifier, + GeometryValue, + XYBrushArea, + Accessor, + AccessorFn, + Datum, +} from '@elastic/charts'; + +import { RangeSelectContext, ValueClickContext } from '../../../../embeddable/public'; +import { Datatable } from '../../../../expressions/public'; + +export interface ClickTriggerEvent { + name: 'filterBucket'; + data: ValueClickContext['data']; +} + +export interface BrushTriggerEvent { + name: 'brush'; + data: RangeSelectContext['data']; +} + +type AllSeriesAccessors = Array<[accessor: Accessor | AccessorFn, value: string | number]>; + +/** + * returns accessor value from string or function accessor + * @param datum + * @param accessor + */ +function getAccessorValue(datum: Datum, accessor: Accessor | AccessorFn) { + if (typeof accessor === 'function') { + return accessor(datum); + } + + return datum[accessor]; +} + +/** + * This is a little unorthodox, but using functional accessors makes it + * difficult to match the correct column. This creates a test object to throw + * an error when the target id is accessed, thus matcing the target column. + */ +function validateAccessorId(id: string, accessor: Accessor | AccessorFn) { + if (typeof accessor !== 'function') { + return id === accessor; + } + + const matchedMessage = 'validateAccessorId matched'; + + try { + accessor({ + get [id]() { + throw new Error(matchedMessage); + }, + }); + return false; + } catch ({ message }) { + return message === matchedMessage; + } +} + +/** + * Groups split accessors by their accessor string or function and related value + * + * @param splitAccessors + * @param splitSeriesAccessorFnMap + */ +const getAllSplitAccessors = ( + splitAccessors: Map, + splitSeriesAccessorFnMap?: Map +): Array<[accessor: Accessor | AccessorFn, value: string | number]> => + [...splitAccessors.entries()].map(([key, value]) => [ + splitSeriesAccessorFnMap?.get?.(key) ?? key, + value, + ]); + +/** + * Reduces matching column indexes + * + * @param xAccessor + * @param yAccessor + * @param splitAccessors + */ +const columnReducer = ( + xAccessor: Accessor | AccessorFn | null, + yAccessor: Accessor | AccessorFn | null, + splitAccessors: AllSeriesAccessors +) => ( + acc: Array<[index: number, id: string]>, + { id }: Datatable['columns'][number], + index: number +): Array<[index: number, id: string]> => { + if ( + (xAccessor !== null && validateAccessorId(id, xAccessor)) || + (yAccessor !== null && validateAccessorId(id, yAccessor)) || + splitAccessors.some(([accessor]) => validateAccessorId(id, accessor)) + ) { + acc.push([index, id]); + } + + return acc; +}; + +/** + * Finds matching row index for given accessors and geometry values + * + * @param geometry + * @param xAccessor + * @param yAccessor + * @param splitAccessors + */ +const rowFindPredicate = ( + geometry: GeometryValue | null, + xAccessor: Accessor | AccessorFn | null, + yAccessor: Accessor | AccessorFn | null, + splitAccessors: AllSeriesAccessors +) => (row: Datatable['rows'][number]): boolean => + (geometry === null || + (xAccessor !== null && + getAccessorValue(row, xAccessor) === geometry.x && + yAccessor !== null && + getAccessorValue(row, yAccessor) === geometry.y)) && + [...splitAccessors].every(([accessor, value]) => getAccessorValue(row, accessor) === value); + +/** + * Helper function to transform `@elastic/charts` click event into filter action event + * + * @param table + * @param xAccessor + * @param splitSeriesAccessorFnMap needed when using `splitSeriesAccessors` as `AccessorFn` + * @param negate + */ +export const getFilterFromChartClickEventFn = ( + table: Datatable, + xAccessor: Accessor | AccessorFn, + splitSeriesAccessorFnMap?: Map, + negate: boolean = false +) => (points: Array<[GeometryValue, XYChartSeriesIdentifier]>): ClickTriggerEvent => { + const data: ValueClickContext['data']['data'] = []; + + points.forEach((point) => { + const [geometry, { yAccessor, splitAccessors }] = point; + const allSplitAccessors = getAllSplitAccessors(splitAccessors, splitSeriesAccessorFnMap); + const columns = table.columns.reduce>( + columnReducer(xAccessor, yAccessor, allSplitAccessors), + [] + ); + const row = table.rows.findIndex( + rowFindPredicate(geometry, xAccessor, yAccessor, allSplitAccessors) + ); + const newData = columns.map(([column, id]) => ({ + table, + column, + row, + value: table.rows?.[row]?.[id] ?? null, + })); + + data.push(...newData); + }); + + return { + name: 'filterBucket', + data: { + negate, + data, + }, + }; +}; + +/** + * Helper function to get filter action event from series + */ +export const getFilterFromSeriesFn = (table: Datatable) => ( + { splitAccessors }: XYChartSeriesIdentifier, + splitSeriesAccessorFnMap?: Map, + negate = false +): ClickTriggerEvent => { + const allSplitAccessors = getAllSplitAccessors(splitAccessors, splitSeriesAccessorFnMap); + const columns = table.columns.reduce>( + columnReducer(null, null, allSplitAccessors), + [] + ); + const row = table.rows.findIndex(rowFindPredicate(null, null, null, allSplitAccessors)); + const data: ValueClickContext['data']['data'] = columns.map(([column, id]) => ({ + table, + column, + row, + value: table.rows?.[row]?.[id] ?? null, + })); + + return { + name: 'filterBucket', + data: { + negate, + data, + }, + }; +}; + +/** + * Helper function to transform `@elastic/charts` brush event into brush action event + */ +export const getBrushFromChartBrushEventFn = ( + table: Datatable, + xAccessor: Accessor | AccessorFn +) => ({ x: selectedRange }: XYBrushArea): BrushTriggerEvent => { + const [start, end] = selectedRange ?? [0, 0]; + const range: [number, number] = [start, end]; + const column = table.columns.findIndex(({ id }) => validateAccessorId(id, xAccessor)); + + return { + data: { + table, + column, + range, + }, + name: 'brush', + }; +}; diff --git a/src/plugins/dashboard/public/application/dashboard_app.tsx b/src/plugins/dashboard/public/application/dashboard_app.tsx index 8eff48251b37..845d64c16500 100644 --- a/src/plugins/dashboard/public/application/dashboard_app.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app.tsx @@ -45,6 +45,7 @@ import { removeQueryParam } from '../services/kibana_utils'; import { IndexPattern } from '../services/data'; import { EmbeddableRenderer } from '../services/embeddable'; import { DashboardContainerInput } from '.'; +import { leaveConfirmStrings } from '../dashboard_strings'; export interface DashboardAppProps { history: History; @@ -64,8 +65,9 @@ export function DashboardApp({ core, onAppLeave, uiSettings, - indexPatterns: indexPatternService, + embeddable, dashboardCapabilities, + indexPatterns: indexPatternService, } = useKibana().services; const [lastReloadTime, setLastReloadTime] = useState(0); @@ -196,9 +198,14 @@ export function DashboardApp({ return; } onAppLeave((actions) => { - if (dashboardStateManager?.getIsDirty()) { - // TODO: Finish App leave handler with overrides when redirecting to an editor. - // return actions.confirm(leaveConfirmStrings.leaveSubtitle, leaveConfirmStrings.leaveTitle); + if ( + dashboardStateManager?.getIsDirty() && + !embeddable.getStateTransfer().isTransferInProgress + ) { + return actions.confirm( + leaveConfirmStrings.getLeaveSubtitle(), + leaveConfirmStrings.getLeaveTitle() + ); } return actions.default(); }); @@ -206,7 +213,7 @@ export function DashboardApp({ // reset on app leave handler so leaving from the listing page doesn't trigger a confirmation onAppLeave((actions) => actions.default()); }; - }, [dashboardStateManager, dashboardContainer, onAppLeave]); + }, [dashboardStateManager, dashboardContainer, onAppLeave, embeddable]); // Refresh the dashboard container when lastReloadTime changes useEffect(() => { diff --git a/src/plugins/dashboard/public/application/dashboard_app_functions.ts b/src/plugins/dashboard/public/application/dashboard_app_functions.ts index 0381fdb2e55b..af7a485296ea 100644 --- a/src/plugins/dashboard/public/application/dashboard_app_functions.ts +++ b/src/plugins/dashboard/public/application/dashboard_app_functions.ts @@ -151,6 +151,7 @@ export const getDashboardContainerInput = ({ description: dashboardStateManager.getDescription(), id: dashboardStateManager.savedDashboard.id || '', useMargins: dashboardStateManager.getUseMargins(), + syncColors: dashboardStateManager.getSyncColors(), viewMode: dashboardStateManager.getViewMode(), filters: query.filterManager.getFilters(), query: dashboardStateManager.getQuery(), diff --git a/src/plugins/dashboard/public/application/dashboard_state.test.ts b/src/plugins/dashboard/public/application/dashboard_state.test.ts index b07ea762f35e..f31ed30f8eb8 100644 --- a/src/plugins/dashboard/public/application/dashboard_state.test.ts +++ b/src/plugins/dashboard/public/application/dashboard_state.test.ts @@ -68,6 +68,7 @@ describe('DashboardState', function () { query: {} as DashboardContainerInput['query'], timeRange: {} as DashboardContainerInput['timeRange'], useMargins: true, + syncColors: false, title: 'ultra awesome test dashboard', isFullScreenMode: false, panels: {} as DashboardContainerInput['panels'], diff --git a/src/plugins/dashboard/public/application/dashboard_state_manager.ts b/src/plugins/dashboard/public/application/dashboard_state_manager.ts index daa0bbdfc9f8..dfcbfcafd3db 100644 --- a/src/plugins/dashboard/public/application/dashboard_state_manager.ts +++ b/src/plugins/dashboard/public/application/dashboard_state_manager.ts @@ -404,6 +404,15 @@ export class DashboardStateManager { this.stateContainer.transitions.setOption('useMargins', useMargins); } + public getSyncColors() { + // Existing dashboards that don't define this should default to true. + return this.appState.options.syncColors === undefined ? true : this.appState.options.syncColors; + } + + public setSyncColors(syncColors: boolean) { + this.stateContainer.transitions.setOption('syncColors', syncColors); + } + public getHidePanelTitles() { return this.appState.options.hidePanelTitles; } diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx index 01b4e81fc484..a3b67ede9f3f 100644 --- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx @@ -59,6 +59,7 @@ export interface DashboardContainerInput extends ContainerInput { timeRange: TimeRange; description?: string; useMargins: boolean; + syncColors?: boolean; viewMode: ViewMode; filters: Filter[]; title: string; @@ -93,6 +94,7 @@ export interface InheritedChildInput extends IndexSignature { hidePanelTitles?: boolean; id: string; searchSessionId?: string; + syncColors?: boolean; } export type DashboardReactContextValue = KibanaReactContextValue; @@ -269,6 +271,7 @@ export class DashboardContainer extends Container
{ (async function loadSavedDashboard() { @@ -46,7 +46,7 @@ export const useSavedDashboard = (savedDashboardId: string | undefined, history: pathname: DashboardConstants.CREATE_NEW_DASHBOARD_URL, }); - showWarningToast(getDashboard60Warning()); + toasts.addWarning(getDashboard60Warning()); return; } @@ -63,7 +63,7 @@ export const useSavedDashboard = (savedDashboardId: string | undefined, history: setSavedDashboard(dashboard); } catch (error) { // E.g. a corrupt or deleted dashboard - showDangerToast(error.message); + toasts.addDanger(error.message); history.push(DashboardConstants.LANDING_PAGE_PATH); } })(); @@ -75,8 +75,7 @@ export const useSavedDashboard = (savedDashboardId: string | undefined, history: recentlyAccessedPaths, savedDashboardId, savedDashboards, - showDangerToast, - showWarningToast, + toasts, ]); return savedDashboard; diff --git a/src/plugins/dashboard/public/application/listing/__snapshots__/dashboard_listing.test.tsx.snap b/src/plugins/dashboard/public/application/listing/__snapshots__/dashboard_listing.test.tsx.snap index fad7d8ddaabf..bce8a661634f 100644 --- a/src/plugins/dashboard/public/application/listing/__snapshots__/dashboard_listing.test.tsx.snap +++ b/src/plugins/dashboard/public/application/listing/__snapshots__/dashboard_listing.test.tsx.snap @@ -126,7 +126,7 @@ exports[`after fetch When given a title that matches multiple dashboards, filter restrictWidth={true} >
@@ -218,7 +218,7 @@ exports[`after fetch hideWriteControls 1`] = ` restrictWidth={true} >
@@ -358,7 +358,7 @@ exports[`after fetch initialFilter 1`] = ` restrictWidth={true} >
@@ -497,7 +497,7 @@ exports[`after fetch renders all table rows 1`] = ` restrictWidth={true} >
@@ -636,7 +636,7 @@ exports[`after fetch renders call to action when no dashboards exist 1`] = ` restrictWidth={true} >
@@ -775,7 +775,7 @@ exports[`after fetch renders warning when listingLimit is exceeded 1`] = ` restrictWidth={true} >
diff --git a/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx b/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx index 937e6737d271..87ccbf29b99f 100644 --- a/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx +++ b/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx @@ -27,6 +27,7 @@ import { useKibana } from '../../services/kibana_react'; import { IndexPattern, SavedQuery, TimefilterContract } from '../../services/data'; import { EmbeddableFactoryNotFoundError, + EmbeddableInput, isErrorEmbeddable, openAddPanelFlyout, ViewMode, @@ -56,10 +57,12 @@ import { showOptionsPopover } from './show_options_popover'; import { TopNavIds } from './top_nav_ids'; import { ShowShareModal } from './show_share_modal'; import { PanelToolbar } from './panel_toolbar'; +import { OverlayRef } from '../../../../../core/public'; import { DashboardContainer } from '..'; export interface DashboardTopNavState { chromeIsVisible: boolean; + addPanelOverlay?: OverlayRef; savedQuery?: SavedQuery; } @@ -110,14 +113,17 @@ export function DashboardTopNav({ const addFromLibrary = useCallback(() => { if (!isErrorEmbeddable(dashboardContainer)) { - openAddPanelFlyout({ - embeddable: dashboardContainer, - getAllFactories: embeddable.getEmbeddableFactories, - getFactory: embeddable.getEmbeddableFactory, - notifications: core.notifications, - overlays: core.overlays, - SavedObjectFinder: getSavedObjectFinder(core.savedObjects, uiSettings), - }); + setState((s) => ({ + ...s, + addPanelOverlay: openAddPanelFlyout({ + embeddable: dashboardContainer, + getAllFactories: embeddable.getEmbeddableFactories, + getFactory: embeddable.getEmbeddableFactory, + notifications: core.notifications, + overlays: core.overlays, + SavedObjectFinder: getSavedObjectFinder(core.savedObjects, uiSettings), + }), + })); } }, [ embeddable.getEmbeddableFactories, @@ -135,14 +141,19 @@ export function DashboardTopNav({ if (!factory) { throw new EmbeddableFactoryNotFoundError(type); } - const explicitInput = await factory.getExplicitInput(); - if (dashboardContainer) { - await dashboardContainer.addNewEmbeddable(type, explicitInput); - } + await factory.create({} as EmbeddableInput, dashboardContainer); }, [dashboardContainer, embeddable]); + const clearAddPanel = useCallback(() => { + if (state.addPanelOverlay) { + state.addPanelOverlay.close(); + setState((s) => ({ ...s, addPanelOverlay: undefined })); + } + }, [state.addPanelOverlay]); + const onChangeViewMode = useCallback( (newMode: ViewMode) => { + clearAddPanel(); const isPageRefresh = newMode === dashboardStateManager.getViewMode(); const isLeavingEditMode = !isPageRefresh && newMode === ViewMode.VIEW; const willLoseChanges = isLeavingEditMode && dashboardStateManager.getIsDirty(timefilter); @@ -180,7 +191,7 @@ export function DashboardTopNav({ } }); }, - [redirectTo, timefilter, core.overlays, savedDashboard.id, dashboardStateManager] + [redirectTo, timefilter, core.overlays, savedDashboard.id, dashboardStateManager, clearAddPanel] ); /** @@ -303,8 +314,16 @@ export function DashboardTopNav({ showCopyOnSave={lastDashboardId ? true : false} /> ); + clearAddPanel(); showSaveModal(dashboardSaveModal, core.i18n.Context); - }, [save, core.i18n.Context, savedObjectsTagging, dashboardStateManager, lastDashboardId]); + }, [ + save, + clearAddPanel, + lastDashboardId, + core.i18n.Context, + savedObjectsTagging, + dashboardStateManager, + ]); const runClone = useCallback(() => { const currentTitle = dashboardStateManager.getTitle(); @@ -350,6 +369,10 @@ export function DashboardTopNav({ onUseMarginsChange: (isChecked: boolean) => { dashboardStateManager.setUseMargins(isChecked); }, + syncColors: dashboardStateManager.getSyncColors(), + onSyncColorsChange: (isChecked: boolean) => { + dashboardStateManager.setSyncColors(isChecked); + }, hidePanelTitles: dashboardStateManager.getHidePanelTitles(), onHidePanelTitlesChange: (isChecked: boolean) => { dashboardStateManager.setHidePanelTitles(isChecked); diff --git a/src/plugins/dashboard/public/application/top_nav/options.tsx b/src/plugins/dashboard/public/application/top_nav/options.tsx index 3398696ff40d..86409cdeba74 100644 --- a/src/plugins/dashboard/public/application/top_nav/options.tsx +++ b/src/plugins/dashboard/public/application/top_nav/options.tsx @@ -27,17 +27,21 @@ interface Props { onUseMarginsChange: (useMargins: boolean) => void; hidePanelTitles: boolean; onHidePanelTitlesChange: (hideTitles: boolean) => void; + syncColors: boolean; + onSyncColorsChange: (syncColors: boolean) => void; } interface State { useMargins: boolean; hidePanelTitles: boolean; + syncColors: boolean; } export class OptionsMenu extends Component { state = { useMargins: this.props.useMargins, hidePanelTitles: this.props.hidePanelTitles, + syncColors: this.props.syncColors, }; constructor(props: Props) { @@ -56,6 +60,12 @@ export class OptionsMenu extends Component { this.setState({ hidePanelTitles: isChecked }); }; + handleSyncColorsChange = (evt: any) => { + const isChecked = evt.target.checked; + this.props.onSyncColorsChange(isChecked); + this.setState({ syncColors: isChecked }); + }; + render() { return ( @@ -80,6 +90,17 @@ export class OptionsMenu extends Component { data-test-subj="dashboardPanelTitlesCheckbox" /> + + + + ); } diff --git a/src/plugins/dashboard/public/application/top_nav/show_options_popover.tsx b/src/plugins/dashboard/public/application/top_nav/show_options_popover.tsx index 7c23e4808fbe..6c519ccad327 100644 --- a/src/plugins/dashboard/public/application/top_nav/show_options_popover.tsx +++ b/src/plugins/dashboard/public/application/top_nav/show_options_popover.tsx @@ -39,10 +39,14 @@ export function showOptionsPopover({ onUseMarginsChange, hidePanelTitles, onHidePanelTitlesChange, + syncColors, + onSyncColorsChange, }: { anchorElement: HTMLElement; useMargins: boolean; onUseMarginsChange: (useMargins: boolean) => void; + syncColors: boolean; + onSyncColorsChange: (syncColors: boolean) => void; hidePanelTitles: boolean; onHidePanelTitlesChange: (hideTitles: boolean) => void; }) { @@ -62,6 +66,8 @@ export function showOptionsPopover({ onUseMarginsChange={onUseMarginsChange} hidePanelTitles={hidePanelTitles} onHidePanelTitlesChange={onHidePanelTitlesChange} + syncColors={syncColors} + onSyncColorsChange={onSyncColorsChange} /> diff --git a/src/plugins/dashboard/public/types.ts b/src/plugins/dashboard/public/types.ts index 7e859a81d9d4..882c5b428626 100644 --- a/src/plugins/dashboard/public/types.ts +++ b/src/plugins/dashboard/public/types.ts @@ -78,6 +78,7 @@ export interface DashboardAppState { options: { hidePanelTitles: boolean; useMargins: boolean; + syncColors?: boolean; }; query: Query | string; filters: Filter[]; diff --git a/src/plugins/data/common/index_patterns/index_pattern.stub.ts b/src/plugins/data/common/index_patterns/index_pattern.stub.ts index e7384e09494a..c47a8b605ada 100644 --- a/src/plugins/data/common/index_patterns/index_pattern.stub.ts +++ b/src/plugins/data/common/index_patterns/index_pattern.stub.ts @@ -25,6 +25,7 @@ export const stubIndexPattern: IIndexPattern = { fields: stubFields, title: 'logstash-*', timeFieldName: '@timestamp', + getTimeField: () => ({ name: '@timestamp', type: 'date' }), }; export const stubIndexPatternWithFields: IIndexPattern = { diff --git a/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_pattern.test.ts.snap b/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_pattern.test.ts.snap index 19ec286307a0..76de2b2662bb 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_pattern.test.ts.snap +++ b/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_pattern.test.ts.snap @@ -2,6 +2,7 @@ exports[`IndexPattern toSpec should match snapshot 1`] = ` Object { + "allowNoIndex": false, "fieldAttrs": Object {}, "fieldFormats": Object {}, "fields": Object { diff --git a/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_patterns.test.ts.snap b/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_patterns.test.ts.snap index c020e7595c56..bad74430b896 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_patterns.test.ts.snap +++ b/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_patterns.test.ts.snap @@ -2,6 +2,7 @@ exports[`IndexPatterns savedObjectToSpec 1`] = ` Object { + "allowNoIndex": undefined, "fieldAttrs": Object {}, "fieldFormats": Object { "field": Object {}, diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts index 4c89cbeb446a..590ff872f3bf 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts @@ -74,6 +74,10 @@ export class IndexPattern implements IIndexPattern { private fieldFormats: FieldFormatsStartCommon; // make private once manual field refresh is removed public fieldAttrs: FieldAttrs; + /** + * prevents errors when index pattern exists before indices + */ + public readonly allowNoIndex: boolean = false; constructor({ spec = {}, @@ -110,6 +114,7 @@ export class IndexPattern implements IIndexPattern { this.typeMeta = spec.typeMeta; this.fieldAttrs = spec.fieldAttrs || {}; this.intervalName = spec.intervalName; + this.allowNoIndex = spec.allowNoIndex || false; } /** @@ -204,6 +209,7 @@ export class IndexPattern implements IIndexPattern { fieldFormats: this.fieldFormatMap, fieldAttrs: this.fieldAttrs, intervalName: this.intervalName, + allowNoIndex: this.allowNoIndex, }; } @@ -309,6 +315,7 @@ export class IndexPattern implements IIndexPattern { fieldFormatMap, type: this.type, typeMeta: this.typeMeta ? JSON.stringify(this.typeMeta) : undefined, + allowNoIndex: this.allowNoIndex ? this.allowNoIndex : undefined, }; } diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.test.ts b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.test.ts index 2a203b57d201..3d32742c168a 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.test.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.test.ts @@ -114,6 +114,21 @@ describe('IndexPatterns', () => { SOClientGetDelay = 0; }); + test('allowNoIndex flag preserves existing fields when index is missing', async () => { + const id = '2'; + setDocsourcePayload(id, { + id: 'foo', + version: 'foo', + attributes: { + title: 'something', + allowNoIndex: true, + fields: '[{"name":"field"}]', + }, + }); + + expect((await indexPatterns.get(id)).fields.length).toBe(1); + }); + test('savedObjectCache pre-fetches only title', async () => { expect(await indexPatterns.getIds()).toEqual(['id']); expect(savedObjectsClient.find).toHaveBeenCalledWith({ diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts index 0235f748ec1e..3333dba36fe6 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts @@ -222,6 +222,7 @@ export class IndexPatternsService { metaFields, type: options.type, rollupIndex: options.rollupIndex, + allowNoIndex: options.allowNoIndex, }); }; @@ -281,10 +282,21 @@ export class IndexPatternsService { options: GetFieldsOptions, fieldAttrs: FieldAttrs = {} ) => { - const scriptedFields = Object.values(fields).filter((field) => field.scripted); + const fieldsAsArr = Object.values(fields); + const scriptedFields = fieldsAsArr.filter((field) => field.scripted); try { + let updatedFieldList: FieldSpec[]; const newFields = (await this.getFieldsForWildcard(options)) as FieldSpec[]; - return this.fieldArrayToMap([...newFields, ...scriptedFields], fieldAttrs); + + // If allowNoIndex, only update field list if field caps finds fields. To support + // beats creating index pattern and dashboard before docs + if (!options.allowNoIndex || (newFields && newFields.length > 5)) { + updatedFieldList = [...newFields, ...scriptedFields]; + } else { + updatedFieldList = fieldsAsArr; + } + + return this.fieldArrayToMap(updatedFieldList, fieldAttrs); } catch (err) { if (err instanceof IndexPatternMissingIndices) { this.onNotification({ title: (err as any).message, color: 'danger', iconType: 'alert' }); @@ -334,6 +346,7 @@ export class IndexPatternsService { typeMeta, type, fieldAttrs, + allowNoIndex, }, } = savedObject; @@ -355,6 +368,7 @@ export class IndexPatternsService { type, fieldFormats: parsedFieldFormatMap, fieldAttrs: parsedFieldAttrs, + allowNoIndex, }; }; @@ -384,6 +398,7 @@ export class IndexPatternsService { metaFields: await this.config.get(UI_SETTINGS.META_FIELDS), type, rollupIndex: typeMeta?.params?.rollup_index, + allowNoIndex: spec.allowNoIndex, }, spec.fieldAttrs ); diff --git a/src/plugins/data/common/index_patterns/types.ts b/src/plugins/data/common/index_patterns/types.ts index 8d9b29175162..12496b07d348 100644 --- a/src/plugins/data/common/index_patterns/types.ts +++ b/src/plugins/data/common/index_patterns/types.ts @@ -49,6 +49,10 @@ export interface IndexPatternAttributes { sourceFilters?: string; fieldFormatMap?: string; fieldAttrs?: string; + /** + * prevents errors when index pattern exists before indices + */ + allowNoIndex?: boolean; } export interface FieldAttrs { @@ -101,6 +105,7 @@ export interface GetFieldsOptions { lookBack?: boolean; metaFields?: string[]; rollupIndex?: string; + allowNoIndex?: boolean; } export interface GetFieldsOptionsTimePattern { @@ -193,6 +198,7 @@ export interface IndexPatternSpec { type?: string; fieldFormats?: Record; fieldAttrs?: FieldAttrs; + allowNoIndex?: boolean; } export interface SourceFilter { diff --git a/src/plugins/data/common/search/aggs/buckets/date_histogram.ts b/src/plugins/data/common/search/aggs/buckets/date_histogram.ts index ba79a4264d60..6b7f1522d19a 100644 --- a/src/plugins/data/common/search/aggs/buckets/date_histogram.ts +++ b/src/plugins/data/common/search/aggs/buckets/date_histogram.ts @@ -149,7 +149,7 @@ export const getDateHistogramBucketAgg = ({ type: 'field', filterFieldTypes: KBN_FIELD_TYPES.DATE, default(agg: IBucketDateHistogramAggConfig) { - return agg.getIndexPattern().timeFieldName; + return agg.getIndexPattern().getTimeField?.()?.name; }, onChange(agg: IBucketDateHistogramAggConfig) { if (isAutoInterval(get(agg, 'params.interval')) && !agg.fieldIsTimeField()) { diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts index 78d169e8529c..9d0c63a8dc7a 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts @@ -150,7 +150,8 @@ describe('esaggs expression function - public', () => { }); }); - test('calls agg.postFlightRequest if it exiests', async () => { + test('calls agg.postFlightRequest if it exiests and agg is enabled', async () => { + mockParams.aggs.aggs[0].enabled = true; await handleRequest(mockParams); expect(mockParams.aggs.aggs[0].type.postFlightRequest).toHaveBeenCalledTimes(1); @@ -160,6 +161,12 @@ describe('esaggs expression function - public', () => { expect(async () => await handleRequest(mockParams)).not.toThrowError(); }); + test('should skip agg.postFlightRequest call if the agg is disabled', async () => { + mockParams.aggs.aggs[0].enabled = false; + await handleRequest(mockParams); + expect(mockParams.aggs.aggs[0].type.postFlightRequest).toHaveBeenCalledTimes(0); + }); + test('tabifies response data', async () => { await handleRequest(mockParams); expect(tabifyAggResponse).toHaveBeenCalledWith( diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts index e4385526ee6e..b773aad67c3f 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts @@ -170,7 +170,7 @@ export const handleRequest = async ({ // response data incorrectly in the inspector. let response = (searchSource as any).rawResponse; for (const agg of aggs.aggs) { - if (typeof agg.type.postFlightRequest === 'function') { + if (agg.enabled && typeof agg.type.postFlightRequest === 'function') { response = await agg.type.postFlightRequest( response, aggs, diff --git a/src/plugins/data/public/actions/apply_filter_action.ts b/src/plugins/data/public/actions/apply_filter_action.ts index 944da72bd11d..84ce5b038262 100644 --- a/src/plugins/data/public/actions/apply_filter_action.ts +++ b/src/plugins/data/public/actions/apply_filter_action.ts @@ -22,7 +22,6 @@ import { toMountPoint } from '../../../kibana_react/public'; import { ActionByType, createAction, IncompatibleActionError } from '../../../ui_actions/public'; import { getOverlays, getIndexPatterns } from '../services'; import { applyFiltersPopover } from '../ui/apply_filters'; -import type { IEmbeddable } from '../../../embeddable/public'; import { Filter, FilterManager, TimefilterContract, esFilters } from '..'; export const ACTION_GLOBAL_APPLY_FILTER = 'ACTION_GLOBAL_APPLY_FILTER'; @@ -30,7 +29,9 @@ export const ACTION_GLOBAL_APPLY_FILTER = 'ACTION_GLOBAL_APPLY_FILTER'; export interface ApplyGlobalFilterActionContext { filters: Filter[]; timeFieldName?: string; - embeddable?: IEmbeddable; + // Need to make this unknown to prevent circular dependencies. + // Apps using this property will need to cast to `IEmbeddable`. + embeddable?: unknown; } async function isCompatible(context: ApplyGlobalFilterActionContext) { diff --git a/src/plugins/data/public/actions/filters/create_filters_from_range_select.ts b/src/plugins/data/public/actions/filters/create_filters_from_range_select.ts index 2d7aeff79a68..2b0911b72abd 100644 --- a/src/plugins/data/public/actions/filters/create_filters_from_range_select.ts +++ b/src/plugins/data/public/actions/filters/create_filters_from_range_select.ts @@ -19,12 +19,20 @@ import { last } from 'lodash'; import moment from 'moment'; +import { Datatable } from 'src/plugins/expressions'; import { esFilters, IFieldType, RangeFilterParams } from '../../../public'; import { getIndexPatterns, getSearchService } from '../../../public/services'; -import { RangeSelectContext } from '../../../../embeddable/public'; import { AggConfigSerialized } from '../../../common/search/aggs'; -export async function createFiltersFromRangeSelectAction(event: RangeSelectContext['data']) { +/** @internal */ +export interface RangeSelectDataContext { + table: Datatable; + column: number; + range: number[]; + timeFieldName?: string; +} + +export async function createFiltersFromRangeSelectAction(event: RangeSelectDataContext) { const column: Record = event.table.columns[event.column]; if (!column || !column.meta) { diff --git a/src/plugins/data/public/actions/filters/create_filters_from_value_click.test.ts b/src/plugins/data/public/actions/filters/create_filters_from_value_click.test.ts index 23d2ab080d75..04801a5ee1ce 100644 --- a/src/plugins/data/public/actions/filters/create_filters_from_value_click.test.ts +++ b/src/plugins/data/public/actions/filters/create_filters_from_value_click.test.ts @@ -25,8 +25,10 @@ import { } from '../../../public'; import { dataPluginMock } from '../../../public/mocks'; import { setIndexPatterns, setSearchService } from '../../../public/services'; -import { createFiltersFromValueClickAction } from './create_filters_from_value_click'; -import { ValueClickContext } from '../../../../embeddable/public'; +import { + createFiltersFromValueClickAction, + ValueClickDataContext, +} from './create_filters_from_value_click'; const mockField = { name: 'bytes', @@ -34,7 +36,7 @@ const mockField = { }; describe('createFiltersFromValueClick', () => { - let dataPoints: ValueClickContext['data']['data']; + let dataPoints: ValueClickDataContext['data']; beforeEach(() => { dataPoints = [ diff --git a/src/plugins/data/public/actions/filters/create_filters_from_value_click.ts b/src/plugins/data/public/actions/filters/create_filters_from_value_click.ts index ce7ecf434056..30fef7e3a7c6 100644 --- a/src/plugins/data/public/actions/filters/create_filters_from_value_click.ts +++ b/src/plugins/data/public/actions/filters/create_filters_from_value_click.ts @@ -20,9 +20,20 @@ import { Datatable } from '../../../../../plugins/expressions/public'; import { esFilters, Filter } from '../../../public'; import { getIndexPatterns, getSearchService } from '../../../public/services'; -import { ValueClickContext } from '../../../../embeddable/public'; import { AggConfigSerialized } from '../../../common/search/aggs'; +/** @internal */ +export interface ValueClickDataContext { + data: Array<{ + table: Pick; + column: number; + row: number; + value: any; + }>; + timeFieldName?: string; + negate?: boolean; +} + /** * For terms aggregations on `__other__` buckets, this assembles a list of applicable filter * terms based on a specific cell in the tabified data. @@ -120,7 +131,7 @@ const createFilter = async ( export const createFiltersFromValueClickAction = async ({ data, negate, -}: ValueClickContext['data']) => { +}: ValueClickDataContext) => { const filters: Filter[] = []; await Promise.all( diff --git a/src/plugins/data/public/actions/select_range_action.ts b/src/plugins/data/public/actions/select_range_action.ts index 1781da980dc3..3b84523d782f 100644 --- a/src/plugins/data/public/actions/select_range_action.ts +++ b/src/plugins/data/public/actions/select_range_action.ts @@ -17,16 +17,22 @@ * under the License. */ -import { - ActionByType, - APPLY_FILTER_TRIGGER, - createAction, - UiActionsStart, -} from '../../../../plugins/ui_actions/public'; +import { Datatable } from 'src/plugins/expressions/public'; +import { ActionByType, createAction, UiActionsStart } from '../../../../plugins/ui_actions/public'; +import { APPLY_FILTER_TRIGGER } from '../triggers'; import { createFiltersFromRangeSelectAction } from './filters/create_filters_from_range_select'; -import type { RangeSelectContext } from '../../../embeddable/public'; -export type SelectRangeActionContext = RangeSelectContext; +export interface SelectRangeActionContext { + // Need to make this unknown to prevent circular dependencies. + // Apps using this property will need to cast to `IEmbeddable`. + embeddable?: unknown; + data: { + table: Datatable; + column: number; + range: number[]; + timeFieldName?: string; + }; +} export const ACTION_SELECT_RANGE = 'ACTION_SELECT_RANGE'; diff --git a/src/plugins/data/public/actions/value_click_action.ts b/src/plugins/data/public/actions/value_click_action.ts index 81e62380eacf..8f207e94e8fb 100644 --- a/src/plugins/data/public/actions/value_click_action.ts +++ b/src/plugins/data/public/actions/value_click_action.ts @@ -17,19 +17,31 @@ * under the License. */ -import { - ActionByType, - APPLY_FILTER_TRIGGER, - createAction, - UiActionsStart, -} from '../../../../plugins/ui_actions/public'; +import { Datatable } from 'src/plugins/expressions/public'; +import { ActionByType, createAction, UiActionsStart } from '../../../../plugins/ui_actions/public'; +import { APPLY_FILTER_TRIGGER } from '../triggers'; import { createFiltersFromValueClickAction } from './filters/create_filters_from_value_click'; import type { Filter } from '../../common/es_query/filters'; -import type { ValueClickContext } from '../../../embeddable/public'; export type ValueClickActionContext = ValueClickContext; export const ACTION_VALUE_CLICK = 'ACTION_VALUE_CLICK'; +export interface ValueClickContext { + // Need to make this unknown to prevent circular dependencies. + // Apps using this property will need to cast to `IEmbeddable`. + embeddable?: unknown; + data: { + data: Array<{ + table: Pick; + column: number; + row: number; + value: any; + }>; + timeFieldName?: string; + negate?: boolean; + }; +} + export function createValueClickAction( getStartServices: () => { uiActions: UiActionsStart } ): ActionByType { diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 3dda04d738c9..7b15e2576e70 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -483,6 +483,7 @@ export { export { isTimeRange, isQuery, isFilter, isFilters } from '../common'; export { ACTION_GLOBAL_APPLY_FILTER, ApplyGlobalFilterActionContext } from './actions'; +export { APPLY_FILTER_TRIGGER } from './triggers'; /* * Plugin setup diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts b/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts index ca0f35d6612b..36a193a4f6f9 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts @@ -64,12 +64,13 @@ export class IndexPatternsApiClient implements IIndexPatternsApiClient { }).then((resp: any) => resp.fields); } - getFieldsForWildcard({ pattern, metaFields, type, rollupIndex }: GetFieldsOptions) { + getFieldsForWildcard({ pattern, metaFields, type, rollupIndex, allowNoIndex }: GetFieldsOptions) { return this._request(this._getUrl(['_fields_for_wildcard']), { pattern, meta_fields: metaFields, type, rollup_index: rollupIndex, - }).then((resp: any) => resp.fields); + allow_no_index: allowNoIndex, + }).then((resp: any) => resp.fields || []); } } diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index eb3a053b78a2..c60a1efabf98 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -48,11 +48,6 @@ import { setUiSettings, } from './services'; import { createSearchBar } from './ui/search_bar/create_search_bar'; -import { - SELECT_RANGE_TRIGGER, - VALUE_CLICK_TRIGGER, - APPLY_FILTER_TRIGGER, -} from '../../ui_actions/public'; import { ACTION_GLOBAL_APPLY_FILTER, createFilterAction, @@ -66,13 +61,18 @@ import { createValueClickAction, createSelectRangeAction, } from './actions'; - +import { APPLY_FILTER_TRIGGER, applyFilterTrigger } from './triggers'; import { SavedObjectsClientPublicToCommon } from './index_patterns'; import { getIndexPatternLoad } from './index_patterns/expressions'; import { UsageCollectionSetup } from '../../usage_collection/public'; import { getTableViewDescription } from './utils/table_inspector_view'; +import { TriggerId } from '../../ui_actions/public'; declare module '../../ui_actions/public' { + export interface TriggerContextMapping { + [APPLY_FILTER_TRIGGER]: ApplyGlobalFilterActionContext; + } + export interface ActionContextMapping { [ACTION_GLOBAL_APPLY_FILTER]: ApplyGlobalFilterActionContext; [ACTION_SELECT_RANGE]: SelectRangeActionContext; @@ -118,19 +118,21 @@ export class DataPublicPlugin storage: this.storage, }); + uiActions.registerTrigger(applyFilterTrigger); + uiActions.registerAction( createFilterAction(queryService.filterManager, queryService.timefilter.timefilter) ); uiActions.addTriggerAction( - SELECT_RANGE_TRIGGER, + 'SELECT_RANGE_TRIGGER' as TriggerId, createSelectRangeAction(() => ({ uiActions: startServices().plugins.uiActions, })) ); uiActions.addTriggerAction( - VALUE_CLICK_TRIGGER, + 'VALUE_CLICK_TRIGGER' as TriggerId, createValueClickAction(() => ({ uiActions: startServices().plugins.uiActions, })) diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index e5df6d860b40..3493844a71ac 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -464,14 +464,17 @@ export type AggsStart = Assign; +// Warning: (ae-missing-release-tag) "APPLY_FILTER_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const APPLY_FILTER_TRIGGER = "FILTER_TRIGGER"; + // Warning: (ae-missing-release-tag) "ApplyGlobalFilterActionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export interface ApplyGlobalFilterActionContext { - // Warning: (ae-forgotten-export) The symbol "IEmbeddable" needs to be exported by the entry point index.d.ts - // // (undocumented) - embeddable?: IEmbeddable; + embeddable?: unknown; // (undocumented) filters: Filter[]; // (undocumented) @@ -1253,6 +1256,7 @@ export class IndexPattern implements IIndexPattern { // Warning: (ae-forgotten-export) The symbol "IndexPatternDeps" needs to be exported by the entry point index.d.ts constructor({ spec, fieldFormats, shortDotsEnable, metaFields, }: IndexPatternDeps); addScriptedField(name: string, script: string, fieldType?: string): Promise; + readonly allowNoIndex: boolean; // (undocumented) readonly deleteFieldFormat: (fieldName: string) => void; // Warning: (ae-forgotten-export) The symbol "FieldAttrs" needs to be exported by the entry point index.d.ts @@ -1293,6 +1297,7 @@ export class IndexPattern implements IIndexPattern { fieldFormatMap: string | undefined; type: string | undefined; typeMeta: string | undefined; + allowNoIndex: true | undefined; }; // (undocumented) getComputedFields(): { @@ -1385,6 +1390,7 @@ export type IndexPatternAggRestrictions = Record, 'isLo // // @public (undocumented) export interface IndexPatternSpec { + // (undocumented) + allowNoIndex?: boolean; // (undocumented) fieldAttrs?: FieldAttrs; // (undocumented) @@ -2561,7 +2569,7 @@ export const UI_SETTINGS: { // src/plugins/data/common/es_query/filters/phrase_filter.ts:33:3 - (ae-forgotten-export) The symbol "PhraseFilterMeta" needs to be exported by the entry point index.d.ts // src/plugins/data/common/es_query/filters/phrases_filter.ts:31:3 - (ae-forgotten-export) The symbol "PhrasesFilterMeta" needs to be exported by the entry point index.d.ts // src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:64:5 - (ae-forgotten-export) The symbol "FormatFieldFn" needs to be exported by the entry point index.d.ts -// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:128:7 - (ae-forgotten-export) The symbol "FieldAttrSet" needs to be exported by the entry point index.d.ts +// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:133:7 - (ae-forgotten-export) The symbol "FieldAttrSet" needs to be exported by the entry point index.d.ts // src/plugins/data/common/search/aggs/types.ts:150:51 - (ae-forgotten-export) The symbol "AggTypesRegistryStart" needs to be exported by the entry point index.d.ts // src/plugins/data/common/search/search_source/search_source.ts:197:7 - (ae-forgotten-export) The symbol "SearchFieldValue" needs to be exported by the entry point index.d.ts // src/plugins/data/public/field_formats/field_formats_service.ts:67:3 - (ae-forgotten-export) The symbol "FormatFactory" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/ui_actions/public/triggers/apply_filter_trigger.ts b/src/plugins/data/public/triggers/apply_filter_trigger.ts similarity index 85% rename from src/plugins/ui_actions/public/triggers/apply_filter_trigger.ts rename to src/plugins/data/public/triggers/apply_filter_trigger.ts index aa54706476a8..816c1737608d 100644 --- a/src/plugins/ui_actions/public/triggers/apply_filter_trigger.ts +++ b/src/plugins/data/public/triggers/apply_filter_trigger.ts @@ -18,15 +18,15 @@ */ import { i18n } from '@kbn/i18n'; -import { Trigger } from '.'; +import { Trigger } from '../../../ui_actions/public'; export const APPLY_FILTER_TRIGGER = 'FILTER_TRIGGER'; export const applyFilterTrigger: Trigger<'FILTER_TRIGGER'> = { id: APPLY_FILTER_TRIGGER, - title: i18n.translate('uiActions.triggers.applyFilterTitle', { + title: i18n.translate('data.triggers.applyFilterTitle', { defaultMessage: 'Apply filter', }), - description: i18n.translate('uiActions.triggers.applyFilterDescription', { + description: i18n.translate('data.triggers.applyFilterDescription', { defaultMessage: 'When kibana filter is applied. Could be a single value or a range filter.', }), }; diff --git a/src/plugins/data/public/triggers/index.ts b/src/plugins/data/public/triggers/index.ts new file mode 100644 index 000000000000..36a38ae76bc0 --- /dev/null +++ b/src/plugins/data/public/triggers/index.ts @@ -0,0 +1,20 @@ +/* + * 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 * from './apply_filter_trigger'; diff --git a/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx b/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx index f4d1a8988da7..f842568859fc 100644 --- a/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx +++ b/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx @@ -38,7 +38,7 @@ import { DataViewRow, DataViewColumn } from '../types'; import { IUiSettingsClient } from '../../../../../../core/public'; import { Datatable, DatatableColumn } from '../../../../../expressions/public'; import { FieldFormatsStart } from '../../../field_formats'; -import { UiActionsStart } from '../../../../../ui_actions/public'; +import { TriggerId, UiActionsStart } from '../../../../../ui_actions/public'; interface DataTableFormatState { columns: DataViewColumn[]; @@ -112,7 +112,7 @@ export class DataTableFormat extends Component { const value = table.rows[rowIndex][column.id]; const eventData = { table, column: columnIndex, row: rowIndex, value }; - uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER', { + uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER' as TriggerId, { data: { data: [eventData] }, }); }} @@ -145,7 +145,7 @@ export class DataTableFormat extends Component { const value = table.rows[rowIndex][column.id]; const eventData = { table, column: columnIndex, row: rowIndex, value }; - uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER', { + uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER' as TriggerId, { data: { data: [eventData], negate: true }, }); }} diff --git a/src/plugins/data/server/index_patterns/index_patterns_api_client.ts b/src/plugins/data/server/index_patterns/index_patterns_api_client.ts index 21a3bf6e73e6..9023044184df 100644 --- a/src/plugins/data/server/index_patterns/index_patterns_api_client.ts +++ b/src/plugins/data/server/index_patterns/index_patterns_api_client.ts @@ -30,8 +30,14 @@ export class IndexPatternsApiServer implements IIndexPatternsApiClient { constructor(elasticsearchClient: ElasticsearchClient) { this.esClient = elasticsearchClient; } - async getFieldsForWildcard({ pattern, metaFields, type, rollupIndex }: GetFieldsOptions) { - const indexPatterns = new IndexPatternsFetcher(this.esClient); + async getFieldsForWildcard({ + pattern, + metaFields, + type, + rollupIndex, + allowNoIndex, + }: GetFieldsOptions) { + const indexPatterns = new IndexPatternsFetcher(this.esClient, allowNoIndex); return await indexPatterns.getFieldsForWildcard({ pattern, metaFields, diff --git a/src/plugins/data/server/index_patterns/routes.ts b/src/plugins/data/server/index_patterns/routes.ts index e9dbc2e972c6..f0b51e456337 100644 --- a/src/plugins/data/server/index_patterns/routes.ts +++ b/src/plugins/data/server/index_patterns/routes.ts @@ -75,13 +75,20 @@ export function registerRoutes( }), type: schema.maybe(schema.string()), rollup_index: schema.maybe(schema.string()), + allow_no_index: schema.maybe(schema.boolean()), }), }, }, async (context, request, response) => { const { asCurrentUser } = context.core.elasticsearch.client; const indexPatterns = new IndexPatternsFetcher(asCurrentUser); - const { pattern, meta_fields: metaFields, type, rollup_index: rollupIndex } = request.query; + const { + pattern, + meta_fields: metaFields, + type, + rollup_index: rollupIndex, + allow_no_index: allowNoIndex, + } = request.query; let parsedFields: string[] = []; try { @@ -96,6 +103,9 @@ export function registerRoutes( metaFields: parsedFields, type, rollupIndex, + fieldCapsOptions: { + allow_no_indices: allowNoIndex || false, + }, }); return response.ok({ diff --git a/src/plugins/data/server/index_patterns/routes/create_index_pattern.ts b/src/plugins/data/server/index_patterns/routes/create_index_pattern.ts index 57a745b19748..1163fd2dc995 100644 --- a/src/plugins/data/server/index_patterns/routes/create_index_pattern.ts +++ b/src/plugins/data/server/index_patterns/routes/create_index_pattern.ts @@ -50,6 +50,7 @@ const indexPatternSpecSchema = schema.object({ }) ) ), + allowNoIndex: schema.maybe(schema.boolean()), }); export const registerCreateIndexPatternRoute = ( diff --git a/src/plugins/data/server/index_patterns/routes/update_index_pattern.ts b/src/plugins/data/server/index_patterns/routes/update_index_pattern.ts index 10567544af6e..8bd59e47730f 100644 --- a/src/plugins/data/server/index_patterns/routes/update_index_pattern.ts +++ b/src/plugins/data/server/index_patterns/routes/update_index_pattern.ts @@ -38,6 +38,7 @@ const indexPatternUpdateSchema = schema.object({ ), fieldFormats: schema.maybe(schema.recordOf(schema.string(), serializedFieldFormatSchema)), fields: schema.maybe(schema.recordOf(schema.string(), fieldSpecSchema)), + allowNoIndex: schema.maybe(schema.boolean()), }); export const registerUpdateIndexPatternRoute = ( diff --git a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts index 1794df7391cb..038f340babb1 100644 --- a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts +++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts @@ -18,7 +18,7 @@ */ import { fetchProvider } from './fetch'; -import { LegacyAPICaller } from 'kibana/server'; +import { ElasticsearchClient } from 'kibana/server'; import { CollectorFetchContext } from 'src/plugins/usage_collection/server'; import { createCollectorFetchContextMock } from 'src/plugins/usage_collection/server/mocks'; @@ -30,7 +30,7 @@ jest.mock('../../../common', () => ({ })); let fetch: ReturnType; -let callCluster: LegacyAPICaller; +let esClient: ElasticsearchClient; let collectorFetchContext: CollectorFetchContext; const collectorFetchContextMock = createCollectorFetchContextMock(); @@ -38,34 +38,33 @@ function setupMockCallCluster( optCount: { optInCount?: number; optOutCount?: number } | null, language: string | undefined | null ) { - callCluster = (jest.fn((method, params) => { - if (params && 'id' in params && params.id === 'kql-telemetry:kql-telemetry') { - if (optCount === null) { - return Promise.resolve({ + function mockedEsGetMethod() { + if (optCount === null) { + return Promise.resolve({ + body: { _index: '.kibana_1', _id: 'kql-telemetry:kql-telemetry', found: false, - }); - } else { - return Promise.resolve({ + }, + }); + } else { + return Promise.resolve({ + body: { _source: { - 'kql-telemetry': { - ...optCount, - }, + 'kql-telemetry': { ...optCount }, type: 'kql-telemetry', updated_at: '2018-10-05T20:20:56.258Z', }, - }); - } - } else if (params && 'body' in params && params.body.query.term.type === 'config') { - if (language === 'missingConfigDoc') { - return Promise.resolve({ - hits: { - hits: [], - }, - }); - } else { - return Promise.resolve({ + }, + }); + } + } + function mockedEsSearchMethod() { + if (language === 'missingConfigDoc') { + return Promise.resolve({ body: { hits: { hits: [] } } }); + } else { + return Promise.resolve({ + body: { hits: { hits: [ { @@ -77,12 +76,15 @@ function setupMockCallCluster( }, ], }, - }); - } + }, + }); } - - throw new Error('invalid call'); - }) as unknown) as LegacyAPICaller; + } + const esClientMock = ({ + get: jest.fn().mockImplementation(mockedEsGetMethod), + search: jest.fn().mockImplementation(mockedEsSearchMethod), + } as unknown) as ElasticsearchClient; + esClient = esClientMock; } describe('makeKQLUsageCollector', () => { @@ -95,7 +97,7 @@ describe('makeKQLUsageCollector', () => { setupMockCallCluster({ optInCount: 1 }, 'kuery'); collectorFetchContext = { ...collectorFetchContextMock, - callCluster, + esClient, }; const fetchResponse = await fetch(collectorFetchContext); expect(fetchResponse.optInCount).toBe(1); @@ -106,7 +108,7 @@ describe('makeKQLUsageCollector', () => { setupMockCallCluster({ optInCount: 1 }, 'kuery'); collectorFetchContext = { ...collectorFetchContextMock, - callCluster, + esClient, }; const fetchResponse = await fetch(collectorFetchContext); expect(fetchResponse.defaultQueryLanguage).toBe('kuery'); @@ -117,7 +119,7 @@ describe('makeKQLUsageCollector', () => { setupMockCallCluster({ optInCount: 1 }, null); collectorFetchContext = { ...collectorFetchContextMock, - callCluster, + esClient, }; const fetchResponse = await fetch(collectorFetchContext); expect(fetchResponse.defaultQueryLanguage).toBe('lucene'); @@ -127,7 +129,7 @@ describe('makeKQLUsageCollector', () => { setupMockCallCluster({ optInCount: 1 }, undefined); collectorFetchContext = { ...collectorFetchContextMock, - callCluster, + esClient, }; const fetchResponse = await fetch(collectorFetchContext); expect(fetchResponse.defaultQueryLanguage).toBe('default-lucene'); @@ -137,7 +139,7 @@ describe('makeKQLUsageCollector', () => { setupMockCallCluster(null, 'kuery'); collectorFetchContext = { ...collectorFetchContextMock, - callCluster, + esClient, }; const fetchResponse = await fetch(collectorFetchContext); expect(fetchResponse.optInCount).toBe(0); @@ -148,7 +150,7 @@ describe('makeKQLUsageCollector', () => { setupMockCallCluster(null, 'missingConfigDoc'); collectorFetchContext = { ...collectorFetchContextMock, - callCluster, + esClient, }; const fetchResponse = await fetch(collectorFetchContext); expect(fetchResponse.defaultQueryLanguage).toBe('default-lucene'); diff --git a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts index 21a1843d1ec8..5178aa65705d 100644 --- a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts +++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts @@ -30,18 +30,22 @@ export interface Usage { } export function fetchProvider(index: string) { - return async ({ callCluster }: CollectorFetchContext): Promise => { - const [response, config] = await Promise.all([ - callCluster('get', { - index, - id: 'kql-telemetry:kql-telemetry', - ignore: [404], - }), - callCluster('search', { - index, - body: { query: { term: { type: 'config' } } }, - ignore: [404], - }), + return async ({ esClient }: CollectorFetchContext): Promise => { + const [{ body: response }, { body: config }] = await Promise.all([ + esClient.get( + { + index, + id: 'kql-telemetry:kql-telemetry', + }, + { ignore: [404] } + ), + esClient.search( + { + index, + body: { query: { term: { type: 'config' } } }, + }, + { ignore: [404] } + ), ]); const queryLanguageConfigValue: string | null | undefined = get( diff --git a/src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts b/src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts index b1410e249866..3b223e6fdb9b 100644 --- a/src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts +++ b/src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts @@ -94,4 +94,55 @@ Object { expect(migrationFn(input, savedObjectMigrationContext)).toEqual(expected); }); }); + + describe('7.11.0', () => { + const migrationFn = indexPatternSavedObjectTypeMigrations['7.11.0']; + + test('should set allowNoIndex', () => { + const input = { + type: 'index-pattern', + id: 'logs-*', + attributes: {}, + }; + const expected = { + type: 'index-pattern', + id: 'logs-*', + attributes: { + allowNoIndex: true, + }, + }; + + expect(migrationFn(input, savedObjectMigrationContext)).toEqual(expected); + + const input2 = { + type: 'index-pattern', + id: 'metrics-*', + attributes: {}, + }; + const expected2 = { + type: 'index-pattern', + id: 'metrics-*', + attributes: { + allowNoIndex: true, + }, + }; + + expect(migrationFn(input2, savedObjectMigrationContext)).toEqual(expected2); + + const input3 = { + type: 'index-pattern', + id: 'xxx', + attributes: {}, + }; + const expected3 = { + type: 'index-pattern', + id: 'xxx', + attributes: { + allowNoIndex: undefined, + }, + }; + + expect(migrationFn(input3, savedObjectMigrationContext)).toEqual(expected3); + }); + }); }); diff --git a/src/plugins/data/server/saved_objects/index_pattern_migrations.ts b/src/plugins/data/server/saved_objects/index_pattern_migrations.ts index 768041a376ad..4650aeefba05 100644 --- a/src/plugins/data/server/saved_objects/index_pattern_migrations.ts +++ b/src/plugins/data/server/saved_objects/index_pattern_migrations.ts @@ -54,7 +54,16 @@ const migrateSubTypeAndParentFieldProperties: SavedObjectMigrationFn = }; }; +const addAllowNoIndex: SavedObjectMigrationFn = (doc) => ({ + ...doc, + attributes: { + ...doc.attributes, + allowNoIndex: doc.id === 'logs-*' || doc.id === 'metrics-*' || undefined, + }, +}); + export const indexPatternSavedObjectTypeMigrations = { '6.5.0': flow(migrateAttributeTypeAndAttributeTypeMeta), '7.6.0': flow(migrateSubTypeAndParentFieldProperties), + '7.11.0': flow(addAllowNoIndex), }; diff --git a/src/plugins/data/server/search/collectors/fetch.ts b/src/plugins/data/server/search/collectors/fetch.ts index 344bc18c7b4b..9d0d431cf4ea 100644 --- a/src/plugins/data/server/search/collectors/fetch.ts +++ b/src/plugins/data/server/search/collectors/fetch.ts @@ -20,31 +20,34 @@ import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { SharedGlobalConfig } from 'kibana/server'; +import { SearchResponse } from 'elasticsearch'; import { CollectorFetchContext } from 'src/plugins/usage_collection/server'; import { Usage } from './register'; - -interface SearchTelemetrySavedObject { +interface SearchTelemetry { 'search-telemetry': Usage; } +type ESResponse = SearchResponse; export function fetchProvider(config$: Observable) { - return async ({ callCluster }: CollectorFetchContext): Promise => { + return async ({ esClient }: CollectorFetchContext): Promise => { const config = await config$.pipe(first()).toPromise(); - - const response = await callCluster('search', { - index: config.kibana.index, - body: { - query: { term: { type: { value: 'search-telemetry' } } }, + const { body: esResponse } = await esClient.search( + { + index: config.kibana.index, + body: { + query: { term: { type: { value: 'search-telemetry' } } }, + }, }, - ignore: [404], - }); - - return response.hits.hits.length - ? response.hits.hits[0]._source['search-telemetry'] - : { - successCount: 0, - errorCount: 0, - averageDuration: null, - }; + { ignore: [404] } + ); + const size = esResponse?.hits?.hits?.length ?? 0; + if (!size) { + return { + successCount: 0, + errorCount: 0, + averageDuration: null, + }; + } + return esResponse.hits.hits[0]._source['search-telemetry']; }; } diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 4d24e6d1afd4..cd3527d5ad7a 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -689,6 +689,7 @@ export class IndexPattern implements IIndexPattern { // Warning: (ae-forgotten-export) The symbol "IndexPatternDeps" needs to be exported by the entry point index.d.ts constructor({ spec, fieldFormats, shortDotsEnable, metaFields, }: IndexPatternDeps); addScriptedField(name: string, script: string, fieldType?: string): Promise; + readonly allowNoIndex: boolean; // (undocumented) readonly deleteFieldFormat: (fieldName: string) => void; // Warning: (ae-forgotten-export) The symbol "FieldAttrs" needs to be exported by the entry point index.d.ts @@ -731,6 +732,7 @@ export class IndexPattern implements IIndexPattern { fieldFormatMap: string | undefined; type: string | undefined; typeMeta: string | undefined; + allowNoIndex: true | undefined; }; // (undocumented) getComputedFields(): { @@ -819,6 +821,7 @@ export class IndexPattern implements IIndexPattern { // // @public (undocumented) export interface IndexPatternAttributes { + allowNoIndex?: boolean; // (undocumented) fieldAttrs?: string; // (undocumented) @@ -1115,7 +1118,7 @@ export class Plugin implements Plugin_2 void; search: ISearchSetup; fieldFormats: { - register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number; + register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number; }; }; // (undocumented) @@ -1124,7 +1127,7 @@ export class Plugin implements Plugin_2 Promise; }; indexPatterns: { - indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise; }; search: ISearchStart>; }; @@ -1388,7 +1391,7 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/common/es_query/filters/meta_filter.ts:54:3 - (ae-forgotten-export) The symbol "FilterMeta" needs to be exported by the entry point index.d.ts // src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:58:45 - (ae-forgotten-export) The symbol "IndexPatternFieldMap" needs to be exported by the entry point index.d.ts // src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:64:5 - (ae-forgotten-export) The symbol "FormatFieldFn" needs to be exported by the entry point index.d.ts -// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:128:7 - (ae-forgotten-export) The symbol "FieldAttrSet" needs to be exported by the entry point index.d.ts +// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:133:7 - (ae-forgotten-export) The symbol "FieldAttrSet" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:40:23 - (ae-forgotten-export) The symbol "buildCustomFilter" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:40:23 - (ae-forgotten-export) The symbol "buildFilter" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:57:23 - (ae-forgotten-export) The symbol "datatableToCSV" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/discover/common/index.ts b/src/plugins/discover/common/index.ts index 4334af63539e..321a102e8d78 100644 --- a/src/plugins/discover/common/index.ts +++ b/src/plugins/discover/common/index.ts @@ -27,4 +27,5 @@ export const FIELDS_LIMIT_SETTING = 'fields:popularLimit'; export const CONTEXT_DEFAULT_SIZE_SETTING = 'context:defaultSize'; export const CONTEXT_STEP_SETTING = 'context:step'; export const CONTEXT_TIE_BREAKER_FIELDS_SETTING = 'context:tieBreakerFields'; +export const DOC_TABLE_LEGACY = 'doc_table:legacy'; export const MODIFY_COLUMNS_ON_SWITCH = 'discover:modifyColumnsOnSwitch'; diff --git a/src/plugins/discover/public/__mocks__/index_pattern.ts b/src/plugins/discover/public/__mocks__/index_pattern.ts index 706118cb7135..f2c12315d4b9 100644 --- a/src/plugins/discover/public/__mocks__/index_pattern.ts +++ b/src/plugins/discover/public/__mocks__/index_pattern.ts @@ -22,29 +22,40 @@ import { IndexPattern } from '../../../data/common'; import { indexPatterns } from '../../../data/public'; const fields = [ + { + name: '_source', + type: '_source', + scripted: false, + filterable: false, + aggregatable: false, + }, { name: '_index', type: 'string', scripted: false, filterable: true, + aggregatable: false, }, { name: 'message', type: 'string', scripted: false, filterable: false, + aggregatable: false, }, { name: 'extension', type: 'string', scripted: false, filterable: true, + aggregatable: true, }, { name: 'bytes', type: 'number', scripted: false, filterable: true, + aggregatable: true, }, { name: 'scripted', @@ -62,16 +73,21 @@ const indexPattern = ({ id: 'the-index-pattern-id', title: 'the-index-pattern-title', metaFields: ['_index', '_score'], + formatField: jest.fn(), flattenHit: undefined, formatHit: jest.fn((hit) => hit._source), fields, - getComputedFields: () => ({}), + getComputedFields: () => ({ docvalueFields: [], scriptFields: {}, storedFields: ['*'] }), getSourceFiltering: () => ({}), getFieldByName: () => ({}), timeFieldName: '', + docvalueFields: [], } as unknown) as IndexPattern; indexPattern.flattenHit = indexPatterns.flattenHitWrapper(indexPattern, indexPattern.metaFields); indexPattern.isTimeBased = () => !!indexPattern.timeFieldName; +indexPattern.formatField = (hit: Record, fieldName: string) => { + return fieldName === '_source' ? hit._source : indexPattern.flattenHit(hit)[fieldName]; +}; export const indexPatternMock = indexPattern; diff --git a/src/plugins/discover/public/application/angular/directives/histogram.tsx b/src/plugins/discover/public/application/angular/directives/histogram.tsx index 4c39c8bb2554..5a0bd5cca610 100644 --- a/src/plugins/discover/public/application/angular/directives/histogram.tsx +++ b/src/plugins/discover/public/application/angular/directives/histogram.tsx @@ -17,25 +17,17 @@ * under the License. */ -import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer } from '@elastic/eui'; -import moment from 'moment-timezone'; -import { unitOfTime } from 'moment'; +import moment, { unitOfTime } from 'moment-timezone'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import lightEuiTheme from '@elastic/eui/dist/eui_theme_light.json'; -import darkEuiTheme from '@elastic/eui/dist/eui_theme_dark.json'; import { - AnnotationDomainTypes, Axis, Chart, HistogramBarSeries, - LineAnnotation, Position, ScaleType, Settings, - RectAnnotation, - TooltipValue, TooltipType, ElementClickListener, XYChartElementEvent, @@ -43,12 +35,17 @@ import { Theme, } from '@elastic/charts'; -import { i18n } from '@kbn/i18n'; import { IUiSettingsClient } from 'kibana/public'; import { EuiChartThemeType } from '@elastic/eui/dist/eui_charts_theme'; import { Subscription, combineLatest } from 'rxjs'; import { getServices } from '../../../kibana_services'; import { Chart as IChart } from '../helpers/point_series'; +import { + CurrentTime, + Endzones, + getAdjustedInterval, + renderEndzoneTooltip, +} from '../../../../../charts/public'; export interface DiscoverHistogramProps { chartData: IChart; @@ -60,34 +57,6 @@ interface DiscoverHistogramState { chartsBaseTheme: Theme; } -function findIntervalFromDuration( - dateValue: number, - esValue: number, - esUnit: unitOfTime.Base, - timeZone: string -) { - const date = moment.tz(dateValue, timeZone); - const startOfDate = moment.tz(date, timeZone).startOf(esUnit); - const endOfDate = moment.tz(date, timeZone).startOf(esUnit).add(esValue, esUnit); - return endOfDate.valueOf() - startOfDate.valueOf(); -} - -function getIntervalInMs( - value: number, - esValue: number, - esUnit: unitOfTime.Base, - timeZone: string -): number { - switch (esUnit) { - case 's': - return 1000 * esValue; - case 'ms': - return 1 * esValue; - default: - return findIntervalFromDuration(value, esValue, esUnit, timeZone); - } -} - function getTimezone(uiSettings: IUiSettingsClient) { if (uiSettings.isDefault('dateFormat:tz')) { const detectedTimezone = moment.tz.guess(); @@ -98,27 +67,6 @@ function getTimezone(uiSettings: IUiSettingsClient) { } } -export function findMinInterval( - xValues: number[], - esValue: number, - esUnit: string, - timeZone: string -): number { - return xValues.reduce((minInterval, currentXvalue, index) => { - let currentDiff = minInterval; - if (index > 0) { - currentDiff = Math.abs(xValues[index - 1] - currentXvalue); - } - const singleUnitInterval = getIntervalInMs( - currentXvalue, - esValue, - esUnit as unitOfTime.Base, - timeZone - ); - return Math.min(minInterval, singleUnitInterval, currentDiff); - }, Number.MAX_SAFE_INTEGER); -} - export class DiscoverHistogram extends Component { public static propTypes = { chartData: PropTypes.object, @@ -132,10 +80,10 @@ export class DiscoverHistogram extends Component + getServices().theme.chartsBaseTheme$, + ]).subscribe(([chartsTheme, chartsBaseTheme]) => this.setState({ chartsTheme, chartsBaseTheme }) ); } @@ -171,40 +119,6 @@ export class DiscoverHistogram extends Component ( - headerData: TooltipValue - ): JSX.Element | string => { - const headerDataValue = headerData.value; - const formattedValue = this.formatXValue(headerDataValue); - - const partialDataText = i18n.translate('discover.histogram.partialData.bucketTooltipText', { - defaultMessage: - 'The selected time range does not include this entire bucket, it may contain partial data.', - }); - - if (headerDataValue < domainStart || headerDataValue + xInterval > domainEnd) { - return ( - - - - - - {partialDataText} - - -

{formattedValue}

-
- ); - } - - return formattedValue; - }; - public render() { const uiSettings = getServices().uiSettings; const timeZone = getTimezone(uiSettings); @@ -216,8 +130,9 @@ export class DiscoverHistogram extends Component domainStart ? domainStart : data[0]?.x; - const domainMax = domainEnd - xInterval > lastXValue ? domainEnd - xInterval : lastXValue; + const domainMin = Math.min(data[0]?.x, domainStart); + const domainMax = Math.max(domainEnd - xInterval, lastXValue); const xDomain = { min: domainMin, max: domainMax, - minInterval: findMinInterval(xValues, intervalESValue, intervalESUnit, timeZone), - }; - - // Domain end of 'now' will be milliseconds behind current time, so we extend time by 1 minute and check if - // the annotation is within this range; if so, the line annotation uses the domainEnd as its value - const now = moment(); - const isAnnotationAtEdge = moment(domainEnd).add(60000).isAfter(now) && now.isAfter(domainEnd); - const lineAnnotationValue = isAnnotationAtEdge ? domainEnd : now; - - const lineAnnotationData = [ - { - dataValue: lineAnnotationValue, - }, - ]; - const isDarkMode = uiSettings.get('theme:darkMode'); - - const lineAnnotationStyle = { - line: { - strokeWidth: 2, - stroke: isDarkMode ? darkEuiTheme.euiColorDanger : lightEuiTheme.euiColorDanger, - opacity: 0.7, - }, + minInterval: getAdjustedInterval( + xValues, + intervalESValue, + intervalESUnit as unitOfTime.Base, + timeZone + ), }; - - const rectAnnotations = []; - if (domainStart !== domainMin) { - rectAnnotations.push({ - coordinates: { - x1: domainStart, - }, - }); - } - if (domainEnd !== domainMax) { - rectAnnotations.push({ - coordinates: { - x0: domainEnd, - }, - }); - } - - const rectAnnotationStyle = { - stroke: isDarkMode ? darkEuiTheme.euiColorLightShade : lightEuiTheme.euiColorDarkShade, - strokeWidth: 0, - opacity: isDarkMode ? 0.6 : 0.2, - fill: isDarkMode ? darkEuiTheme.euiColorLightShade : lightEuiTheme.euiColorDarkShade, - }; - const tooltipProps = { - headerFormatter: this.renderBarTooltip(xInterval, domainStart, domainEnd), + headerFormatter: renderEndzoneTooltip(xInterval, domainStart, domainEnd, this.formatXValue), type: TooltipType.VerticalCursor, }; @@ -313,19 +188,14 @@ export class DiscoverHistogram extends Component - - + { }; const discoverRoute = { ...defaults, - template: indexTemplateLegacy, + template: getServices().uiSettings.get('doc_table:legacy', true) + ? indexTemplateLegacy + : indexTemplateGrid, reloadOnSearch: false, resolve: { savedObjects: function ($route, Promise) { @@ -338,6 +342,8 @@ function discoverController($element, $route, $scope, $timeout, Promise, uiCapab $scope.minimumVisibleRows = 50; $scope.fetchStatus = fetchStatuses.UNINITIALIZED; $scope.showSaveQuery = uiCapabilities.discover.saveQuery; + $scope.showTimeCol = + !config.get('doc_table:hideTimeColumn', false) && $scope.indexPattern.timeFieldName; let abortController; $scope.$on('$destroy', () => { @@ -410,9 +416,13 @@ function discoverController($element, $route, $scope, $timeout, Promise, uiCapab function getStateDefaults() { const query = $scope.searchSource.getField('query') || data.query.queryString.getDefaultQuery(); - return { + const sort = getSortArray(savedSearch.sort, $scope.indexPattern); + + const defaultState = { query, - sort: getSortArray(savedSearch.sort, $scope.indexPattern), + sort: !sort.length + ? getDefaultSort($scope.indexPattern, config.get(SORT_DEFAULT_ORDER_SETTING, 'desc')) + : sort, columns: savedSearch.columns.length > 0 ? savedSearch.columns @@ -421,6 +431,11 @@ function discoverController($element, $route, $scope, $timeout, Promise, uiCapab interval: 'auto', filters: _.cloneDeep($scope.searchSource.getOwnField('filter')), }; + if (savedSearch.grid) { + defaultState.grid = savedSearch.grid; + } + + return defaultState; } $scope.state.index = $scope.indexPattern.id; @@ -434,6 +449,8 @@ function discoverController($element, $route, $scope, $timeout, Promise, uiCapab indexPatternList: $route.current.locals.savedObjects.ip.list, config: config, setHeaderActionMenu: getHeaderActionMenuMounter(), + filterManager, + setAppState, data, }; @@ -777,6 +794,17 @@ function discoverController($element, $route, $scope, $timeout, Promise, uiCapab const columns = columnActions.moveColumn($scope.state.columns, columnName, newIndex); setAppState({ columns }); }; + + $scope.setColumns = function setColumns(columns) { + // remove first element of columns if it's the configured timeFieldName, which is prepended automatically + const actualColumns = + $scope.indexPattern.timeFieldName && $scope.indexPattern.timeFieldName === columns[0] + ? columns.slice(1) + : columns; + $scope.state = { ...$scope.state, columns: actualColumns }; + setAppState({ columns: actualColumns }); + }; + async function setupVisualization() { // If no timefield has been specified we don't create a histogram of messages if (!getTimeField()) return; diff --git a/src/plugins/discover/public/application/angular/discover_datagrid.html b/src/plugins/discover/public/application/angular/discover_datagrid.html new file mode 100644 index 000000000000..e59ebbb0fafd --- /dev/null +++ b/src/plugins/discover/public/application/angular/discover_datagrid.html @@ -0,0 +1,31 @@ + + + + diff --git a/src/plugins/discover/public/application/angular/discover_legacy.html b/src/plugins/discover/public/application/angular/discover_legacy.html index 7cdcd6cbbca3..3596c0a2519e 100644 --- a/src/plugins/discover/public/application/angular/discover_legacy.html +++ b/src/plugins/discover/public/application/angular/discover_legacy.html @@ -1,6 +1,5 @@ { + indexPattern = FixturesStubbedLogstashIndexPatternProvider() as IndexPattern; + }); + test('should be a function', function () { + expect(typeof getDefaultSort === 'function').toBeTruthy(); + }); + + test('should return default sort for an index pattern with timeFieldName', function () { + expect(getDefaultSort(indexPattern, 'desc')).toEqual([['time', 'desc']]); + expect(getDefaultSort(indexPattern, 'asc')).toEqual([['time', 'asc']]); + }); + + test('should return default sort for an index pattern without timeFieldName', function () { + delete indexPattern.timeFieldName; + expect(getDefaultSort(indexPattern, 'desc')).toEqual([]); + expect(getDefaultSort(indexPattern, 'asc')).toEqual([]); + }); +}); diff --git a/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.ts b/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.ts index 634e3cfec3a0..c1e4da0bab54 100644 --- a/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.ts +++ b/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.ts @@ -17,7 +17,6 @@ * under the License. */ import { IndexPattern } from '../../../../kibana_services'; -// @ts-ignore import { isSortable } from './get_sort'; import { SortOrder } from '../components/table_header/helpers'; @@ -26,12 +25,12 @@ import { SortOrder } from '../components/table_header/helpers'; * the default sort is returned depending of the index pattern */ export function getDefaultSort( - indexPattern: IndexPattern, + indexPattern: IndexPattern | undefined, defaultSortOrder: string = 'desc' ): SortOrder[] { - if (indexPattern.timeFieldName && isSortable(indexPattern.timeFieldName, indexPattern)) { + if (indexPattern?.timeFieldName && isSortable(indexPattern.timeFieldName, indexPattern)) { return [[indexPattern.timeFieldName, defaultSortOrder]]; } else { - return [['_score', defaultSortOrder]]; + return []; } } diff --git a/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.test.ts b/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.test.ts new file mode 100644 index 000000000000..1dbd31897d30 --- /dev/null +++ b/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.test.ts @@ -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 { getSortForSearchSource } from './get_sort_for_search_source'; +// @ts-ignore +import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; +import { IndexPattern } from '../../../../kibana_services'; +import { SortOrder } from '../components/table_header/helpers'; + +describe('getSortForSearchSource function', function () { + let indexPattern: IndexPattern; + beforeEach(() => { + indexPattern = FixturesStubbedLogstashIndexPatternProvider() as IndexPattern; + }); + test('should be a function', function () { + expect(typeof getSortForSearchSource === 'function').toBeTruthy(); + }); + + test('should return an object to use for searchSource when columns are given', function () { + const cols = [['bytes', 'desc']] as SortOrder[]; + expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ bytes: 'desc' }]); + expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ bytes: 'desc' }]); + delete indexPattern.timeFieldName; + expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ bytes: 'desc' }]); + expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ bytes: 'desc' }]); + }); + + test('should return an object to use for searchSource when no columns are given', function () { + const cols = [] as SortOrder[]; + expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ _doc: 'desc' }]); + expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ _doc: 'asc' }]); + delete indexPattern.timeFieldName; + expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ _score: 'desc' }]); + expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ _score: 'asc' }]); + }); +}); diff --git a/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.ts b/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.ts index 6721f7a03584..1244a0e229cd 100644 --- a/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.ts +++ b/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.ts @@ -19,7 +19,6 @@ import { EsQuerySortValue, IndexPattern } from '../../../../kibana_services'; import { SortOrder } from '../components/table_header/helpers'; import { getSort } from './get_sort'; -import { getDefaultSort } from './get_default_sort'; /** * Prepares sort for search source, that's sending the request to ES @@ -33,10 +32,13 @@ export function getSortForSearchSource( indexPattern?: IndexPattern, defaultDirection: string = 'desc' ): EsQuerySortValue[] { - if (!sort || !indexPattern) { - return []; - } else if (Array.isArray(sort) && sort.length === 0) { - sort = getDefaultSort(indexPattern, defaultDirection); + if (!sort || !indexPattern || (Array.isArray(sort) && sort.length === 0)) { + if (indexPattern?.timeFieldName) { + // sorting by index order + return [{ _doc: defaultDirection } as EsQuerySortValue]; + } else { + return [{ _score: defaultDirection } as EsQuerySortValue]; + } } const { timeFieldName } = indexPattern; return getSort(sort, indexPattern).map((sortPair: Record) => { diff --git a/src/plugins/discover/public/application/components/create_discover_directive.ts b/src/plugins/discover/public/application/components/create_discover_directive.ts new file mode 100644 index 000000000000..a146f60652d8 --- /dev/null +++ b/src/plugins/discover/public/application/components/create_discover_directive.ts @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Discover } from './discover'; + +export function createDiscoverDirective(reactDirective: any) { + return reactDirective(Discover, [ + ['fetch', { watchDepth: 'reference' }], + ['fetchCounter', { watchDepth: 'reference' }], + ['fetchError', { watchDepth: 'reference' }], + ['fieldCounts', { watchDepth: 'reference' }], + ['histogramData', { watchDepth: 'reference' }], + ['hits', { watchDepth: 'reference' }], + ['indexPattern', { watchDepth: 'reference' }], + ['onAddColumn', { watchDepth: 'reference' }], + ['onAddFilter', { watchDepth: 'reference' }], + ['onChangeInterval', { watchDepth: 'reference' }], + ['onRemoveColumn', { watchDepth: 'reference' }], + ['onSetColumns', { watchDepth: 'reference' }], + ['onSort', { watchDepth: 'reference' }], + ['opts', { watchDepth: 'reference' }], + ['resetQuery', { watchDepth: 'reference' }], + ['resultState', { watchDepth: 'reference' }], + ['rows', { watchDepth: 'reference' }], + ['searchSource', { watchDepth: 'reference' }], + ['setColumns', { watchDepth: 'reference' }], + ['setIndexPattern', { watchDepth: 'reference' }], + ['showSaveQuery', { watchDepth: 'reference' }], + ['state', { watchDepth: 'reference' }], + ['timefilterUpdateHandler', { watchDepth: 'reference' }], + ['timeRange', { watchDepth: 'reference' }], + ['topNavMenu', { watchDepth: 'reference' }], + ['updateQuery', { watchDepth: 'reference' }], + ['updateSavedQueryId', { watchDepth: 'reference' }], + ]); +} diff --git a/src/plugins/discover/public/application/components/create_discover_grid_directive.tsx b/src/plugins/discover/public/application/components/create_discover_grid_directive.tsx new file mode 100644 index 000000000000..4e2a2506e282 --- /dev/null +++ b/src/plugins/discover/public/application/components/create_discover_grid_directive.tsx @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import * as React from 'react'; +import { I18nProvider } from '@kbn/i18n/react'; +import { DiscoverGrid, DiscoverGridProps } from './discover_grid/discover_grid'; +import { getServices } from '../../kibana_services'; + +export const DataGridMemoized = React.memo((props: DiscoverGridProps) => ( + +)); + +export function DiscoverGridEmbeddable(props: DiscoverGridProps) { + return ( + + + + ); +} + +/** + * this is just needed for the embeddable + */ +export function createDiscoverGridDirective(reactDirective: any) { + return reactDirective(DiscoverGridEmbeddable, [ + ['columns', { watchDepth: 'collection' }], + ['indexPattern', { watchDepth: 'reference' }], + ['onAddColumn', { watchDepth: 'reference', wrapApply: false }], + ['onFilter', { watchDepth: 'reference', wrapApply: false }], + ['onRemoveColumn', { watchDepth: 'reference', wrapApply: false }], + ['onSetColumns', { watchDepth: 'reference', wrapApply: false }], + ['onSort', { watchDepth: 'reference', wrapApply: false }], + ['rows', { watchDepth: 'collection' }], + ['sampleSize', { watchDepth: 'reference' }], + ['searchDescription', { watchDepth: 'reference' }], + ['searchTitle', { watchDepth: 'reference' }], + ['settings', { watchDepth: 'reference' }], + ['showTimeCol', { watchDepth: 'value' }], + ['sort', { watchDepth: 'value' }], + ]); +} diff --git a/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts b/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts index cb3cb06aa90a..6e5d47be987d 100644 --- a/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts +++ b/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts @@ -21,7 +21,6 @@ import { DiscoverLegacy } from './discover_legacy'; export function createDiscoverLegacyDirective(reactDirective: any) { return reactDirective(DiscoverLegacy, [ - ['addColumn', { watchDepth: 'reference' }], ['fetch', { watchDepth: 'reference' }], ['fetchCounter', { watchDepth: 'reference' }], ['fetchError', { watchDepth: 'reference' }], @@ -30,6 +29,7 @@ export function createDiscoverLegacyDirective(reactDirective: any) { ['hits', { watchDepth: 'reference' }], ['indexPattern', { watchDepth: 'reference' }], ['minimumVisibleRows', { watchDepth: 'reference' }], + ['onAddColumn', { watchDepth: 'reference' }], ['onAddFilter', { watchDepth: 'reference' }], ['onChangeInterval', { watchDepth: 'reference' }], ['onMoveColumn', { watchDepth: 'reference' }], diff --git a/src/plugins/discover/public/application/components/discover.scss b/src/plugins/discover/public/application/components/discover.scss index b17da97a4593..665bd98c232a 100644 --- a/src/plugins/discover/public/application/components/discover.scss +++ b/src/plugins/discover/public/application/components/discover.scss @@ -35,6 +35,10 @@ discover-app { } } +.dscPageContent { + border: $euiBorderThin; +} + .dscPageContent, .dscPageContent__inner { height: 100%; @@ -46,6 +50,7 @@ discover-app { .dscResultCount { padding: $euiSizeS; + min-height: $euiSize * 3; @include euiBreakpoint('xs', 's') { .dscResultCount__toggle { @@ -76,6 +81,13 @@ discover-app { padding: $euiSizeS; } +// new slimmer layout for data grid +.dscHistogramGrid { + display: flex; + height: $euiSize * 8; + padding: $euiSizeS $euiSizeS 0 $euiSizeS; +} + .dscTable { // SASSTODO: add a monospace modifier to the doc-table component .kbnDocTable__row { diff --git a/src/plugins/discover/public/application/components/discover.tsx b/src/plugins/discover/public/application/components/discover.tsx new file mode 100644 index 000000000000..aa756d960e43 --- /dev/null +++ b/src/plugins/discover/public/application/components/discover.tsx @@ -0,0 +1,321 @@ +/* + * 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 './discover.scss'; +import React, { useState, useRef } from 'react'; +import { + EuiButtonEmpty, + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiHideFor, + EuiHorizontalRule, + EuiPage, + EuiPageBody, + EuiPageContent, + EuiSpacer, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; +import classNames from 'classnames'; +import { HitsCounter } from './hits_counter'; +import { TimechartHeader } from './timechart_header'; +import { getServices } from '../../kibana_services'; +import { DiscoverUninitialized, DiscoverHistogram } from '../angular/directives'; +import { DiscoverNoResults } from './no_results'; +import { LoadingSpinner } from './loading_spinner/loading_spinner'; +import { search } from '../../../../data/public'; +import { + DiscoverSidebarResponsive, + DiscoverSidebarResponsiveProps, +} from './sidebar/discover_sidebar_responsive'; +import { DiscoverProps } from './discover_legacy'; +import { SortPairArr } from '../angular/doc_table/lib/get_sort'; +import { DiscoverGrid, DiscoverGridProps } from './discover_grid/discover_grid'; + +export const SidebarMemoized = React.memo((props: DiscoverSidebarResponsiveProps) => ( + +)); + +export const DataGridMemoized = React.memo((props: DiscoverGridProps) => ( + +)); + +export function Discover({ + fetch, + fetchCounter, + fetchError, + fieldCounts, + histogramData, + hits, + indexPattern, + onAddColumn, + onAddFilter, + onChangeInterval, + onRemoveColumn, + onSetColumns, + onSort, + opts, + resetQuery, + resultState, + rows, + searchSource, + setIndexPattern, + showSaveQuery, + state, + timefilterUpdateHandler, + timeRange, + topNavMenu, + updateQuery, + updateSavedQueryId, +}: DiscoverProps) { + const scrollableDesktop = useRef(null); + const collapseIcon = useRef(null); + const [toggleOn, toggleChart] = useState(true); + const [isSidebarClosed, setIsSidebarClosed] = useState(false); + const services = getServices(); + const { TopNavMenu } = services.navigation.ui; + const { trackUiMetric } = services; + const { savedSearch, indexPatternList, config } = opts; + const bucketAggConfig = opts.chartAggConfigs?.aggs[1]; + const bucketInterval = + bucketAggConfig && search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig) + ? bucketAggConfig.buckets?.getInterval() + : undefined; + const contentCentered = resultState === 'uninitialized'; + const showTimeCol = !config.get('doc_table:hideTimeColumn', false) && indexPattern.timeFieldName; + const columns = + state.columns && + state.columns.length > 0 && + // check if all columns where removed except the configured timeField (this can't be removed) + !(state.columns.length === 1 && state.columns[0] === indexPattern.timeFieldName) + ? state.columns + : ['_source']; + // if columns include _source this is considered as default view, so you can't remove columns + // until you add a column using Discover's sidebar + const defaultColumns = columns.includes('_source'); + + return ( + + + + +

+ {savedSearch.title} +

+ + + + + + + setIsSidebarClosed(!isSidebarClosed)} + data-test-subj="collapseSideBarButton" + aria-controls="discover-sidebar" + aria-expanded={isSidebarClosed ? 'false' : 'true'} + aria-label={i18n.translate('discover.toggleSidebarAriaLabel', { + defaultMessage: 'Toggle sidebar', + })} + buttonRef={collapseIcon} + /> + + + + + {resultState === 'none' && ( + + )} + {resultState === 'uninitialized' && } + {resultState === 'loading' && } + {resultState === 'ready' && ( + + + + + 0 ? hits : 0} + showResetButton={!!(savedSearch && savedSearch.id)} + onResetQuery={resetQuery} + /> + + {toggleOn && ( + + + + )} + + { + toggleChart(!toggleOn); + }} + > + {toggleOn + ? i18n.translate('discover.hideChart', { + defaultMessage: 'Hide chart', + }) + : i18n.translate('discover.showChart', { + defaultMessage: 'Show chart', + })} + + + + + {toggleOn && opts.timefield && ( + +
+ {opts.chartAggConfigs && histogramData && rows.length !== 0 && ( +
+ +
+ )} +
+ +
+ )} + + + + +
+

+ +

+ {rows && rows.length && ( +
+ { + const grid = { ...state.grid } || {}; + const newColumns = { ...grid.columns } || {}; + newColumns[colSettings.columnId] = { + width: colSettings.width, + }; + const newGrid = { ...grid, columns: newColumns }; + opts.setAppState({ grid: newGrid }); + }} + /> +
+ )} +
+
+
+ )} +
+
+
+
+
+
+ ); +} diff --git a/src/plugins/ui_actions/public/triggers/select_range_trigger.ts b/src/plugins/discover/public/application/components/discover_grid/constants.ts similarity index 62% rename from src/plugins/ui_actions/public/triggers/select_range_trigger.ts rename to src/plugins/discover/public/application/components/discover_grid/constants.ts index 312e75314bd9..dec483da8f8a 100644 --- a/src/plugins/ui_actions/public/triggers/select_range_trigger.ts +++ b/src/plugins/discover/public/application/components/discover_grid/constants.ts @@ -16,17 +16,23 @@ * specific language governing permissions and limitations * under the License. */ +// data types +export const kibanaJSON = 'kibana-json'; +export const geoPoint = 'geo-point'; +export const unknownType = 'unknown'; +export const gridStyle = { + border: 'all', + fontSize: 's', + cellPadding: 's', + rowHover: 'none', +}; -import { i18n } from '@kbn/i18n'; -import { Trigger } from '.'; - -export const SELECT_RANGE_TRIGGER = 'SELECT_RANGE_TRIGGER'; -export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> = { - id: SELECT_RANGE_TRIGGER, - title: i18n.translate('uiActions.triggers.selectRangeTitle', { - defaultMessage: 'Range selection', - }), - description: i18n.translate('uiActions.triggers.selectRangeDescription', { - defaultMessage: 'A range of values on the visualization', - }), +export const pageSizeArr = [25, 50, 100]; +export const defaultPageSize = 25; +export const toolbarVisibility = { + showColumnSelector: { + allowHide: false, + allowReorder: true, + }, + showStyleSelector: false, }; diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid.scss b/src/plugins/discover/public/application/components/discover_grid/discover_grid.scss new file mode 100644 index 000000000000..64a7eda96334 --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid.scss @@ -0,0 +1,68 @@ +.dscDiscoverGrid { + width: 100%; + max-width: 100%; + height: 100%; + overflow: hidden; + + .euiDataGrid__controls { + border: none; + border-bottom: $euiBorderThin; + } + + .euiDataGridRowCell:first-of-type, + .euiDataGrid--headerShade.euiDataGrid--bordersAll .euiDataGridHeaderCell:first-of-type { + border-left: none; + border-right: none; + } + + .euiDataGridRowCell:last-of-type, + .euiDataGridHeaderCell:last-of-type { + border-right: none; + } +} + +.dscDiscoverGrid__footer { + background-color: $euiColorLightShade; + padding: $euiSize / 2 $euiSize; + margin-top: $euiSize / 4; + text-align: center; +} + +.dscTable__flyoutHeader { + white-space: nowrap; +} + +// We only truncate if the cell is not a control column. +.euiDataGridHeader { + .euiDataGridHeaderCell__content { + @include euiTextTruncate; + overflow: hidden; + white-space: nowrap; + flex-grow: 1; + } + + .euiDataGridHeaderCell__popover { + flex-grow: 0; + flex-basis: auto; + width: auto; + padding-left: $euiSizeXS; + } +} + +.euiDataGridRowCell--numeric { + text-align: right; +} + +.euiDataGrid__noResults { + display: flex; + flex-direction: column; + justify-content: center; + flex: 1 0 100%; + text-align: center; + height: 100%; + width: 100%; +} + +.dscFormatSource { + @include euiTextTruncate; +} diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx new file mode 100644 index 000000000000..9588f74ed2bc --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx @@ -0,0 +1,336 @@ +/* + * 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, { useCallback, useMemo, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import './discover_grid.scss'; +import { + EuiDataGridSorting, + EuiDataGridStyle, + EuiDataGridProps, + EuiDataGrid, + EuiIcon, + EuiScreenReaderOnly, + EuiSpacer, + EuiText, + htmlIdGenerator, +} from '@elastic/eui'; +import { IndexPattern } from '../../../kibana_services'; +import { DocViewFilterFn, ElasticSearchHit } from '../../doc_views/doc_views_types'; +import { getPopoverContents, getSchemaDetectors } from './discover_grid_schema'; +import { DiscoverGridFlyout } from './discover_grid_flyout'; +import { DiscoverGridContext } from './discover_grid_context'; +import { getRenderCellValueFn } from './get_render_cell_value'; +import { DiscoverGridSettings } from './types'; +import { SortPairArr } from '../../angular/doc_table/lib/get_sort'; +import { + getEuiGridColumns, + getLeadControlColumns, + getVisibleColumns, +} from './discover_grid_columns'; +import { defaultPageSize, gridStyle, pageSizeArr, toolbarVisibility } from './constants'; +import { DiscoverServices } from '../../../build_services'; + +interface SortObj { + id: string; + direction: string; +} + +export interface DiscoverGridProps { + /** + * Determines which element labels the grid for ARIA + */ + ariaLabelledBy: string; + /** + * Determines which columns are displayed + */ + columns: string[]; + /** + * Determines whether the given columns are the default ones, so parts of the document + * are displayed (_source) with limited actions (cannor move, remove columns) + * Implemented for matching with legacy behavior + */ + defaultColumns: boolean; + /** + * The used index pattern + */ + indexPattern: IndexPattern; + /** + * Function used to add a column in the document flyout + */ + onAddColumn: (column: string) => void; + /** + * Function to add a filter in the grid cell or document flyout + */ + onFilter: DocViewFilterFn; + /** + * Function used in the grid header and flyout to remove a column + * @param column + */ + onRemoveColumn: (column: string) => void; + /** + * Function triggered when a column is resized by the user + */ + onResize?: (colSettings: { columnId: string; width: number }) => void; + /** + * Function to set all columns + */ + onSetColumns: (columns: string[]) => void; + /** + * function to change sorting of the documents + */ + onSort: (sort: string[][]) => void; + /** + * Array of documents provided by Elasticsearch + */ + rows?: ElasticSearchHit[]; + /** + * The max size of the documents returned by Elasticsearch + */ + sampleSize: number; + /** + * Grid display settings persisted in Elasticsearch (e.g. column width) + */ + settings?: DiscoverGridSettings; + /** + * Saved search description + */ + searchDescription?: string; + /** + * Saved search title + */ + searchTitle?: string; + /** + * Discover plugin services + */ + services: DiscoverServices; + /** + * Determines whether the time columns should be displayed (legacy settings) + */ + showTimeCol: boolean; + /** + * Current sort setting + */ + sort: SortPairArr[]; +} + +export const EuiDataGridMemoized = React.memo((props: EuiDataGridProps) => { + return ; +}); + +export const DiscoverGrid = ({ + ariaLabelledBy, + columns, + defaultColumns, + indexPattern, + onAddColumn, + onFilter, + onRemoveColumn, + onResize, + onSetColumns, + onSort, + rows, + sampleSize, + searchDescription, + searchTitle, + services, + settings, + showTimeCol, + sort, +}: DiscoverGridProps) => { + const [expanded, setExpanded] = useState(undefined); + + /** + * Pagination + */ + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: defaultPageSize }); + const rowCount = useMemo(() => (rows ? rows.length : 0), [rows]); + const pageCount = useMemo(() => Math.ceil(rowCount / pagination.pageSize), [ + rowCount, + pagination, + ]); + const isOnLastPage = pagination.pageIndex === pageCount - 1; + + const paginationObj = useMemo(() => { + const onChangeItemsPerPage = (pageSize: number) => + setPagination((paginationData) => ({ ...paginationData, pageSize })); + + const onChangePage = (pageIndex: number) => + setPagination((paginationData) => ({ ...paginationData, pageIndex })); + + return { + onChangeItemsPerPage, + onChangePage, + pageIndex: pagination.pageIndex > pageCount - 1 ? 0 : pagination.pageIndex, + pageSize: pagination.pageSize, + pageSizeOptions: pageSizeArr, + }; + }, [pagination, pageCount]); + + /** + * Sorting + */ + const sortingColumns = useMemo(() => sort.map(([id, direction]) => ({ id, direction })), [sort]); + + const onTableSort = useCallback( + (sortingColumnsData) => { + onSort(sortingColumnsData.map(({ id, direction }: SortObj) => [id, direction])); + }, + [onSort] + ); + + /** + * Cell rendering + */ + const renderCellValue = useMemo( + () => + getRenderCellValueFn( + indexPattern, + rows, + rows ? rows.map((hit) => indexPattern.flattenHit(hit)) : [] + ), + [rows, indexPattern] + ); + + /** + * Render variables + */ + const showDisclaimer = rowCount === sampleSize && isOnLastPage; + const randomId = useMemo(() => htmlIdGenerator()(), []); + + const euiGridColumns = useMemo( + () => getEuiGridColumns(columns, settings, indexPattern, showTimeCol, defaultColumns), + [columns, indexPattern, showTimeCol, settings, defaultColumns] + ); + const schemaDetectors = useMemo(() => getSchemaDetectors(), []); + const popoverContents = useMemo(() => getPopoverContents(), []); + const columnsVisibility = useMemo( + () => ({ + visibleColumns: getVisibleColumns(columns, indexPattern, showTimeCol) as string[], + setVisibleColumns: (newColumns: string[]) => { + onSetColumns(newColumns); + }, + }), + [columns, indexPattern, showTimeCol, onSetColumns] + ); + const sorting = useMemo(() => ({ columns: sortingColumns, onSort: onTableSort }), [ + sortingColumns, + onTableSort, + ]); + const lead = useMemo(() => getLeadControlColumns(), []); + + if (!rowCount) { + return ( +
+ + + + + +
+ ); + } + + return ( + + <> + { + if (onResize) { + onResize(col); + } + }} + pagination={paginationObj} + popoverContents={popoverContents} + renderCellValue={renderCellValue} + rowCount={rowCount} + schemaDetectors={schemaDetectors} + sorting={sorting as EuiDataGridSorting} + toolbarVisibility={ + defaultColumns + ? { + ...toolbarVisibility, + showColumnSelector: false, + } + : toolbarVisibility + } + /> + + {showDisclaimer && ( +

+ + + + +

+ )} + {searchTitle && ( + +

+ {searchDescription ? ( + + ) : ( + + )} +

+
+ )} + {expanded && ( + setExpanded(undefined)} + services={services} + /> + )} + +
+ ); +}; diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.test.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.test.tsx new file mode 100644 index 000000000000..a85583f66c6f --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.test.tsx @@ -0,0 +1,80 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { mountWithIntl } from '@kbn/test/jest'; +import { findTestSubject } from '@elastic/eui/lib/test'; +import { FilterInBtn, FilterOutBtn } from './discover_grid_cell_actions'; +import { DiscoverGridContext } from './discover_grid_context'; + +import { indexPatternMock } from '../../../__mocks__/index_pattern'; +import { esHits } from '../../../__mocks__/es_hits'; +import { EuiButton } from '@elastic/eui'; + +describe('Discover cell actions ', function () { + it('triggers filter function when FilterInBtn is clicked', async () => { + const contextMock = { + expanded: undefined, + setExpanded: jest.fn(), + rows: esHits, + onFilter: jest.fn(), + indexPattern: indexPatternMock, + isDarkMode: false, + }; + + const component = mountWithIntl( + + } + rowIndex={1} + columnId={'extension'} + isExpanded={false} + closePopover={jest.fn()} + /> + + ); + const button = findTestSubject(component, 'filterForButton'); + await button.simulate('click'); + expect(contextMock.onFilter).toHaveBeenCalledWith('extension', 'jpg', '+'); + }); + it('triggers filter function when FilterOutBtn is clicked', async () => { + const contextMock = { + expanded: undefined, + setExpanded: jest.fn(), + rows: esHits, + onFilter: jest.fn(), + indexPattern: indexPatternMock, + isDarkMode: false, + }; + + const component = mountWithIntl( + + } + rowIndex={1} + columnId={'extension'} + isExpanded={false} + closePopover={jest.fn()} + /> + + ); + const button = findTestSubject(component, 'filterOutButton'); + await button.simulate('click'); + expect(contextMock.onFilter).toHaveBeenCalledWith('extension', 'jpg', '-'); + }); +}); diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx new file mode 100644 index 000000000000..ef56166258c9 --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx @@ -0,0 +1,97 @@ +/* + * 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, { useContext } from 'react'; +import { EuiDataGridColumnCellActionProps } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { IndexPatternField } from '../../../../../data/common/index_patterns/fields'; +import { DiscoverGridContext } from './discover_grid_context'; + +export const FilterInBtn = ({ + Component, + rowIndex, + columnId, +}: EuiDataGridColumnCellActionProps) => { + const context = useContext(DiscoverGridContext); + const buttonTitle = i18n.translate('discover.grid.filterForAria', { + defaultMessage: 'Filter for this {value}', + values: { value: columnId }, + }); + + return ( + { + const row = context.rows[rowIndex]; + const flattened = context.indexPattern.flattenHit(row); + + if (flattened) { + context.onFilter(columnId, flattened[columnId], '+'); + } + }} + iconType="plusInCircle" + aria-label={buttonTitle} + title={buttonTitle} + data-test-subj="filterForButton" + > + {i18n.translate('discover.grid.filterFor', { + defaultMessage: 'Filter for', + })} + + ); +}; + +export const FilterOutBtn = ({ + Component, + rowIndex, + columnId, +}: EuiDataGridColumnCellActionProps) => { + const context = useContext(DiscoverGridContext); + const buttonTitle = i18n.translate('discover.grid.filterOutAria', { + defaultMessage: 'Filter out this {value}', + values: { value: columnId }, + }); + + return ( + { + const row = context.rows[rowIndex]; + const flattened = context.indexPattern.flattenHit(row); + + if (flattened) { + context.onFilter(columnId, flattened[columnId], '-'); + } + }} + iconType="minusInCircle" + aria-label={buttonTitle} + title={buttonTitle} + data-test-subj="filterOutButton" + > + {i18n.translate('discover.grid.filterOut', { + defaultMessage: 'Filter out', + })} + + ); +}; + +export function buildCellActions(field: IndexPatternField) { + if (!field.aggregatable && !field.searchable) { + return undefined; + } + + return [FilterInBtn, FilterOutBtn]; +} diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.test.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.test.tsx new file mode 100644 index 000000000000..dad7e1363fdd --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.test.tsx @@ -0,0 +1,154 @@ +/* + * 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 { indexPatternMock } from '../../../__mocks__/index_pattern'; +import { getEuiGridColumns } from './discover_grid_columns'; +import { indexPatternWithTimefieldMock } from '../../../__mocks__/index_pattern_with_timefield'; + +describe('Discover grid columns ', function () { + it('returns eui grid columns without time column', async () => { + const actual = getEuiGridColumns(['extension', 'message'], {}, indexPatternMock, false, false); + expect(actual).toMatchInlineSnapshot(` + Array [ + Object { + "actions": Object { + "showHide": Object { + "iconType": "cross", + "label": "Remove column", + }, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": undefined, + "display": undefined, + "id": "extension", + "isSortable": undefined, + "schema": "unknown", + }, + Object { + "actions": Object { + "showHide": Object { + "iconType": "cross", + "label": "Remove column", + }, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": undefined, + "display": undefined, + "id": "message", + "isSortable": undefined, + "schema": "unknown", + }, + ] + `); + }); + it('returns eui grid columns without time column showing default columns', async () => { + const actual = getEuiGridColumns( + ['extension', 'message'], + {}, + indexPatternWithTimefieldMock, + false, + true + ); + expect(actual).toMatchInlineSnapshot(` + Array [ + Object { + "actions": Object { + "showHide": false, + "showMoveLeft": false, + "showMoveRight": false, + }, + "cellActions": undefined, + "display": undefined, + "id": "extension", + "isSortable": undefined, + "schema": "unknown", + }, + Object { + "actions": Object { + "showHide": false, + "showMoveLeft": false, + "showMoveRight": false, + }, + "cellActions": undefined, + "display": undefined, + "id": "message", + "isSortable": undefined, + "schema": "unknown", + }, + ] + `); + }); + it('returns eui grid columns with time column', async () => { + const actual = getEuiGridColumns( + ['extension', 'message'], + {}, + indexPatternWithTimefieldMock, + true, + false + ); + expect(actual).toMatchInlineSnapshot(` + Array [ + Object { + "actions": Object { + "showHide": false, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": undefined, + "display": "Time (timestamp)", + "id": "timestamp", + "initialWidth": 180, + "isSortable": undefined, + "schema": "unknown", + }, + Object { + "actions": Object { + "showHide": Object { + "iconType": "cross", + "label": "Remove column", + }, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": undefined, + "display": undefined, + "id": "extension", + "isSortable": undefined, + "schema": "unknown", + }, + Object { + "actions": Object { + "showHide": Object { + "iconType": "cross", + "label": "Remove column", + }, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": undefined, + "display": undefined, + "id": "message", + "isSortable": undefined, + "schema": "unknown", + }, + ] + `); + }); +}); diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx new file mode 100644 index 000000000000..1cf9c84405a6 --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx @@ -0,0 +1,122 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiDataGridColumn, EuiScreenReaderOnly } from '@elastic/eui'; +import { ExpandButton } from './discover_grid_expand_button'; +import { DiscoverGridSettings } from './types'; +import { IndexPattern } from '../../../../../data/common/index_patterns/index_patterns'; +import { buildCellActions } from './discover_grid_cell_actions'; +import { getSchemaByKbnType } from './discover_grid_schema'; + +export function getLeadControlColumns() { + return [ + { + id: 'openDetails', + width: 32, + headerCellRender: () => ( + + + {i18n.translate('discover.controlColumnHeader', { + defaultMessage: 'Control column', + })} + + + ), + rowCellRender: ExpandButton, + }, + ]; +} + +export function buildEuiGridColumn( + columnName: string, + columnWidth: number | undefined = 0, + indexPattern: IndexPattern, + defaultColumns: boolean +) { + const timeString = i18n.translate('discover.timeLabel', { + defaultMessage: 'Time', + }); + const indexPatternField = indexPattern.getFieldByName(columnName); + const column: EuiDataGridColumn = { + id: columnName, + schema: getSchemaByKbnType(indexPatternField?.type), + isSortable: indexPatternField?.sortable, + display: indexPatternField?.displayName, + actions: { + showHide: + defaultColumns || columnName === indexPattern.timeFieldName + ? false + : { + label: i18n.translate('discover.removeColumnLabel', { + defaultMessage: 'Remove column', + }), + iconType: 'cross', + }, + showMoveLeft: !defaultColumns, + showMoveRight: !defaultColumns, + }, + cellActions: indexPatternField ? buildCellActions(indexPatternField) : [], + }; + + if (column.id === indexPattern.timeFieldName) { + column.display = `${timeString} (${indexPattern.timeFieldName})`; + column.initialWidth = 180; + } + if (columnWidth > 0) { + column.initialWidth = Number(columnWidth); + } + return column; +} + +export function getEuiGridColumns( + columns: string[], + settings: DiscoverGridSettings | undefined, + indexPattern: IndexPattern, + showTimeCol: boolean, + defaultColumns: boolean +) { + const timeFieldName = indexPattern.timeFieldName; + const getColWidth = (column: string) => settings?.columns?.[column]?.width ?? 0; + + if (showTimeCol && indexPattern.timeFieldName && !columns.find((col) => col === timeFieldName)) { + const usedColumns = [indexPattern.timeFieldName, ...columns]; + return usedColumns.map((column) => + buildEuiGridColumn(column, getColWidth(column), indexPattern, defaultColumns) + ); + } + + return columns.map((column) => + buildEuiGridColumn(column, getColWidth(column), indexPattern, defaultColumns) + ); +} + +export function getVisibleColumns( + columns: string[], + indexPattern: IndexPattern, + showTimeCol: boolean +) { + const timeFieldName = indexPattern.timeFieldName; + + if (showTimeCol && !columns.find((col) => col === timeFieldName)) { + return [timeFieldName, ...columns]; + } + + return columns; +} diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx new file mode 100644 index 000000000000..dcc404a0e48d --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { DocViewFilterFn, ElasticSearchHit } from '../../doc_views/doc_views_types'; +import { IndexPattern } from '../../../kibana_services'; + +export interface GridContext { + expanded: ElasticSearchHit | undefined; + setExpanded: (hit: ElasticSearchHit | undefined) => void; + rows: ElasticSearchHit[]; + onFilter: DocViewFilterFn; + indexPattern: IndexPattern; + isDarkMode: boolean; +} + +const defaultContext = ({} as unknown) as GridContext; + +export const DiscoverGridContext = React.createContext(defaultContext); diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.test.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.test.tsx new file mode 100644 index 000000000000..82fcad8c2cd6 --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.test.tsx @@ -0,0 +1,106 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { mountWithIntl } from '@kbn/test/jest'; +import { findTestSubject } from '@elastic/eui/lib/test'; +import { ExpandButton } from './discover_grid_expand_button'; +import { DiscoverGridContext } from './discover_grid_context'; +import { indexPatternMock } from '../../../__mocks__/index_pattern'; +import { esHits } from '../../../__mocks__/es_hits'; + +describe('Discover grid view button ', function () { + it('when no document is expanded, setExpanded is called with current document', async () => { + const contextMock = { + expanded: undefined, + setExpanded: jest.fn(), + rows: esHits, + onFilter: jest.fn(), + indexPattern: indexPatternMock, + isDarkMode: false, + }; + + const component = mountWithIntl( + + + + ); + const button = findTestSubject(component, 'docTableExpandToggleColumn'); + await button.simulate('click'); + expect(contextMock.setExpanded).toHaveBeenCalledWith(esHits[0]); + }); + it('when the current document is expanded, setExpanded is called with undefined', async () => { + const contextMock = { + expanded: esHits[0], + setExpanded: jest.fn(), + rows: esHits, + onFilter: jest.fn(), + indexPattern: indexPatternMock, + isDarkMode: false, + }; + + const component = mountWithIntl( + + + + ); + const button = findTestSubject(component, 'docTableExpandToggleColumn'); + await button.simulate('click'); + expect(contextMock.setExpanded).toHaveBeenCalledWith(undefined); + }); + it('when another document is expanded, setExpanded is called with the current document', async () => { + const contextMock = { + expanded: esHits[0], + setExpanded: jest.fn(), + rows: esHits, + onFilter: jest.fn(), + indexPattern: indexPatternMock, + isDarkMode: false, + }; + + const component = mountWithIntl( + + + + ); + const button = findTestSubject(component, 'docTableExpandToggleColumn'); + await button.simulate('click'); + expect(contextMock.setExpanded).toHaveBeenCalledWith(esHits[1]); + }); +}); diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.tsx new file mode 100644 index 000000000000..d4a3fe85e34e --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_expand_button.tsx @@ -0,0 +1,62 @@ +/* + * 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, { useContext, useEffect } from 'react'; +import { EuiButtonIcon, EuiDataGridCellValueElementProps, EuiToolTip } from '@elastic/eui'; +import themeDark from '@elastic/eui/dist/eui_theme_dark.json'; +import themeLight from '@elastic/eui/dist/eui_theme_light.json'; +import { i18n } from '@kbn/i18n'; +import { DiscoverGridContext } from './discover_grid_context'; +/** + * Button to expand a given row + */ +export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => { + const { expanded, setExpanded, rows, isDarkMode } = useContext(DiscoverGridContext); + const current = rows[rowIndex]; + useEffect(() => { + if (expanded && current && expanded._id === current._id) { + setCellProps({ + style: { + backgroundColor: isDarkMode ? themeDark.euiColorHighlight : themeLight.euiColorHighlight, + }, + }); + } else { + setCellProps({ style: undefined }); + } + }, [expanded, current, setCellProps, isDarkMode]); + + const isCurrentRowExpanded = current === expanded; + const buttonLabel = i18n.translate('discover.grid.viewDoc', { + defaultMessage: 'Toggle dialog with details', + }); + + return ( + + setExpanded(isCurrentRowExpanded ? undefined : current)} + color={isCurrentRowExpanded ? 'primary' : 'subdued'} + iconType={isCurrentRowExpanded ? 'minimize' : 'expand'} + isSelected={isCurrentRowExpanded} + /> + + ); +}; diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx new file mode 100644 index 000000000000..79ad98ae2bab --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx @@ -0,0 +1,143 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutHeader, + EuiTitle, + EuiButtonEmpty, + EuiText, + EuiSpacer, + EuiPortal, +} from '@elastic/eui'; +import { DocViewer } from '../doc_viewer/doc_viewer'; +import { IndexPattern } from '../../../kibana_services'; +import { DocViewFilterFn, ElasticSearchHit } from '../../doc_views/doc_views_types'; +import { DiscoverServices } from '../../../build_services'; +import { getContextUrl } from '../../helpers/get_context_url'; + +interface Props { + columns: string[]; + hit: ElasticSearchHit; + indexPattern: IndexPattern; + onAddColumn: (column: string) => void; + onClose: () => void; + onFilter: DocViewFilterFn; + onRemoveColumn: (column: string) => void; + services: DiscoverServices; +} + +/** + * Flyout displaying an expanded Elasticsearch document + */ +export function DiscoverGridFlyout({ + hit, + indexPattern, + columns, + onFilter, + onClose, + onRemoveColumn, + onAddColumn, + services, +}: Props) { + return ( + + + + +

+ {i18n.translate('discover.grid.tableRow.detailHeading', { + defaultMessage: 'Expanded document', + })} +

+
+ + + + + + + {i18n.translate('discover.grid.tableRow.viewText', { + defaultMessage: 'View:', + })} + + + + + + {i18n.translate('discover.grid.tableRow.viewSingleDocumentLinkTextSimple', { + defaultMessage: 'Single document', + })} + + + {indexPattern.isTimeBased() && indexPattern.id && ( + + + {i18n.translate('discover.grid.tableRow.viewSurroundingDocumentsLinkTextSimple', { + defaultMessage: 'Surrounding documents', + })} + + + )} + +
+ + { + onFilter(mapping, value, mode); + onClose(); + }} + onRemoveColumn={(columnName: string) => { + onRemoveColumn(columnName); + onClose(); + }} + onAddColumn={(columnName: string) => { + onAddColumn(columnName); + onClose(); + }} + /> + +
+
+ ); +} diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_schema.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_schema.tsx new file mode 100644 index 000000000000..aa87d3982fa0 --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_schema.tsx @@ -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 React, { ReactNode } from 'react'; +import { EuiCodeBlock } from '@elastic/eui'; +import { geoPoint, kibanaJSON, unknownType } from './constants'; +import { KBN_FIELD_TYPES } from '../../../../../data/common'; + +export function getSchemaByKbnType(kbnType: string | undefined) { + // Default DataGrid schemas: boolean, numeric, datetime, json, currency, string + switch (kbnType) { + case KBN_FIELD_TYPES.IP: + case KBN_FIELD_TYPES.GEO_SHAPE: + case KBN_FIELD_TYPES.NUMBER: + return 'numeric'; + case KBN_FIELD_TYPES.BOOLEAN: + return 'boolean'; + case KBN_FIELD_TYPES.STRING: + return 'string'; + case KBN_FIELD_TYPES.DATE: + return 'datetime'; + case KBN_FIELD_TYPES._SOURCE: + return kibanaJSON; + case KBN_FIELD_TYPES.GEO_POINT: + return geoPoint; + default: + return unknownType; + } +} + +export function getSchemaDetectors() { + return [ + { + type: kibanaJSON, + detector() { + return 0; // this schema is always explicitly defined + }, + sortTextAsc: '', + sortTextDesc: '', + icon: '', + color: '', + }, + { + type: unknownType, + detector() { + return 0; // this schema is always explicitly defined + }, + sortTextAsc: '', + sortTextDesc: '', + icon: '', + color: '', + }, + { + type: geoPoint, + detector() { + return 0; // this schema is always explicitly defined + }, + sortTextAsc: '', + sortTextDesc: '', + icon: 'tokenGeo', + }, + ]; +} + +/** + * Returns custom popover content for certain schemas + */ +export function getPopoverContents() { + return { + [geoPoint]: ({ children }: { children: ReactNode }) => { + return {children}; + }, + [unknownType]: ({ children }: { children: ReactNode }) => { + return ( + + {children} + + ); + }, + [kibanaJSON]: ({ children }: { children: ReactNode }) => { + return ( + + {children} + + ); + }, + }; +} diff --git a/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx new file mode 100644 index 000000000000..d9896f4c5390 --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx @@ -0,0 +1,132 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { shallow } from 'enzyme'; +import { getRenderCellValueFn } from './get_render_cell_value'; +import { indexPatternMock } from '../../../__mocks__/index_pattern'; +const rows = [ + { + _id: '1', + _index: 'test', + _type: 'test', + _score: 1, + _source: { bytes: 100 }, + }, +]; + +describe('Discover grid cell rendering', function () { + it('renders bytes column correctly', () => { + const DiscoverGridCellValue = getRenderCellValueFn( + indexPatternMock, + rows, + rows.map((row) => indexPatternMock.flattenHit(row)) + ); + const component = shallow( + + ); + expect(component.html()).toMatchInlineSnapshot(`"100"`); + }); + it('renders _source column correctly', () => { + const DiscoverGridCellValue = getRenderCellValueFn( + indexPatternMock, + rows, + rows.map((row) => indexPatternMock.flattenHit(row)) + ); + const component = shallow( + + ); + expect(component.html()).toMatchInlineSnapshot( + `"
bytes
100
"` + ); + }); + + it('renders _source column correctly when isDetails is set to true', () => { + const DiscoverGridCellValue = getRenderCellValueFn( + indexPatternMock, + rows, + rows.map((row) => indexPatternMock.flattenHit(row)) + ); + const component = shallow( + + ); + expect(component.html()).toMatchInlineSnapshot(` + "{ + "bytes": 100 + }" + `); + }); + + it('renders correctly when invalid row is given', () => { + const DiscoverGridCellValue = getRenderCellValueFn( + indexPatternMock, + rows, + rows.map((row) => indexPatternMock.flattenHit(row)) + ); + const component = shallow( + + ); + expect(component.html()).toMatchInlineSnapshot(`"-"`); + }); + it('renders correctly when invalid column is given', () => { + const DiscoverGridCellValue = getRenderCellValueFn( + indexPatternMock, + rows, + rows.map((row) => indexPatternMock.flattenHit(row)) + ); + const component = shallow( + + ); + expect(component.html()).toMatchInlineSnapshot(`"-"`); + }); +}); diff --git a/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx new file mode 100644 index 000000000000..2157e778f84d --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx @@ -0,0 +1,116 @@ +/* + * 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, { Fragment, useContext, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import themeLight from '@elastic/eui/dist/eui_theme_light.json'; +import themeDark from '@elastic/eui/dist/eui_theme_dark.json'; + +import { + EuiDataGridCellValueElementProps, + EuiDescriptionList, + EuiDescriptionListTitle, + EuiDescriptionListDescription, +} from '@elastic/eui'; +import { IndexPattern } from '../../../kibana_services'; +import { ElasticSearchHit } from '../../doc_views/doc_views_types'; +import { DiscoverGridContext } from './discover_grid_context'; + +export const getRenderCellValueFn = ( + indexPattern: IndexPattern, + rows: ElasticSearchHit[] | undefined, + rowsFlattened: Array> +) => ({ rowIndex, columnId, isDetails, setCellProps }: EuiDataGridCellValueElementProps) => { + const row = rows ? (rows[rowIndex] as Record) : undefined; + const rowFlattened = rowsFlattened + ? (rowsFlattened[rowIndex] as Record) + : undefined; + + const field = indexPattern.fields.getByName(columnId); + const ctx = useContext(DiscoverGridContext); + + useEffect(() => { + if (ctx.expanded && row && ctx.expanded._id === row._id) { + setCellProps({ + style: { + backgroundColor: ctx.isDarkMode + ? themeDark.euiColorHighlight + : themeLight.euiColorHighlight, + }, + }); + } else { + setCellProps({ style: undefined }); + } + }, [ctx, row, setCellProps]); + + if (typeof row === 'undefined' || typeof rowFlattened === 'undefined') { + return -; + } + + if (field && field.type === '_source') { + if (isDetails) { + // nicely formatted JSON for the expanded view + return {JSON.stringify(row[columnId], null, 2)}; + } + const formatted = indexPattern.formatHit(row); + + return ( + + {Object.keys(formatted).map((key) => ( + + {key} + + + ))} + + ); + } + + if (!field?.type && rowFlattened && typeof rowFlattened[columnId] === 'object') { + if (isDetails) { + // nicely formatted JSON for the expanded view + return {JSON.stringify(rowFlattened[columnId], null, 2)}; + } + + return {JSON.stringify(rowFlattened[columnId])}; + } + + if (field?.type === 'geo_point' && rowFlattened && rowFlattened[columnId]) { + const valueFormatted = rowFlattened[columnId] as { lat: number; lon: number }; + return ( +
+ {i18n.translate('discover.latitudeAndLongitude', { + defaultMessage: 'Lat: {lat} Lon: {lon}', + values: { + lat: valueFormatted?.lat, + lon: valueFormatted?.lon, + }, + })} +
+ ); + } + + const valueFormatted = indexPattern.formatField(row, columnId); + if (typeof valueFormatted === 'undefined') { + return -; + } + return ( + // eslint-disable-next-line react/no-danger + + ); +}; diff --git a/src/plugins/discover/public/application/components/discover_grid/types.ts b/src/plugins/discover/public/application/components/discover_grid/types.ts new file mode 100644 index 000000000000..3d57dbffe924 --- /dev/null +++ b/src/plugins/discover/public/application/components/discover_grid/types.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * User configurable state of data grid, persisted in saved search + */ +export interface DiscoverGridSettings { + columns?: Record; +} + +export interface DiscoverGridSettingsColumn { + width?: number; +} diff --git a/src/plugins/discover/public/application/components/discover_legacy.test.tsx b/src/plugins/discover/public/application/components/discover_legacy.test.tsx index e2f4ba7ab6e2..bad5c1d2e532 100644 --- a/src/plugins/discover/public/application/components/discover_legacy.test.tsx +++ b/src/plugins/discover/public/application/components/discover_legacy.test.tsx @@ -67,7 +67,6 @@ function getProps(indexPattern: IndexPattern) { } as unknown) as DiscoverServices; return { - addColumn: jest.fn(), fetch: jest.fn(), fetchCounter: 0, fetchError: undefined, @@ -75,6 +74,7 @@ function getProps(indexPattern: IndexPattern) { hits: esHits.length, indexPattern, minimumVisibleRows: 10, + onAddColumn: jest.fn(), onAddFilter: jest.fn(), onChangeInterval: jest.fn(), onMoveColumn: jest.fn(), diff --git a/src/plugins/discover/public/application/components/discover_legacy.tsx b/src/plugins/discover/public/application/components/discover_legacy.tsx index d228be66990b..436a14502443 100644 --- a/src/plugins/discover/public/application/components/discover_legacy.tsx +++ b/src/plugins/discover/public/application/components/discover_legacy.tsx @@ -63,46 +63,161 @@ import { import { DocViewFilterFn, ElasticSearchHit } from '../doc_views/doc_views_types'; export interface DiscoverProps { - addColumn: (column: string) => void; + /** + * Function to fetch documents from Elasticsearch + */ fetch: () => void; + /** + * Counter how often data was fetched (used for testing) + */ fetchCounter: number; + /** + * Error in case of a failing document fetch + */ fetchError?: Error; + /** + * Statistics by fields calculated using the fetched documents + */ fieldCounts: Record; + /** + * Histogram aggregation data + */ histogramData?: Chart; + /** + * Number of documents found by recent fetch + */ hits: number; + /** + * Current IndexPattern + */ indexPattern: IndexPattern; + /** + * Value needed for legacy "infinite" loading functionality + * Determins how much records are rendered using the legacy table + * Increased when scrolling down + */ minimumVisibleRows: number; + /** + * Function to add a column to state + */ + onAddColumn: (column: string) => void; + /** + * Function to add a filter to state + */ onAddFilter: DocViewFilterFn; + /** + * Function to change the used time interval of the date histogram + */ onChangeInterval: (interval: string) => void; + /** + * Function to move a given column to a given index, used in legacy table + */ onMoveColumn: (columns: string, newIdx: number) => void; + /** + * Function to remove a given column from state + */ onRemoveColumn: (column: string) => void; + /** + * Function to replace columns in state + */ onSetColumns: (columns: string[]) => void; + /** + * Function to scroll down the legacy table to the bottom + */ onSkipBottomButtonClick: () => void; + /** + * Function to change sorting of the table, triggers a fetch + */ onSort: (sort: string[][]) => void; opts: { + /** + * Date histogram aggregation config + */ chartAggConfigs?: AggConfigs; + /** + * Client of uiSettings + */ config: IUiSettingsClient; + /** + * Data plugin + */ data: DataPublicPluginStart; - fixedScroll: (el: HTMLElement) => void; + /** + * Data plugin filter manager + */ filterManager: FilterManager; + /** + * List of available index patterns + */ indexPatternList: Array>; + /** + * The number of documents that can be displayed in the table/grid + */ sampleSize: number; + /** + * Current instance of SavedSearch + */ savedSearch: SavedSearch; + /** + * Function to set the header menu + */ setHeaderActionMenu: (menuMount: MountPoint | undefined) => void; + /** + * Timefield of the currently used index pattern + */ timefield: string; + /** + * Function to set the current state + */ setAppState: (state: Partial) => void; }; + /** + * Function to reset the current query + */ resetQuery: () => void; + /** + * Current state of the actual query, one of 'uninitialized', 'loading' ,'ready', 'none' + */ resultState: string; + /** + * Array of document of the recent successful search request + */ rows: ElasticSearchHit[]; + /** + * Instance of SearchSource, the high level search API + */ searchSource: ISearchSource; + /** + * Function to change the current index pattern + */ setIndexPattern: (id: string) => void; + /** + * Determines whether the user should be able to use the save query feature + */ showSaveQuery: boolean; + /** + * Current app state of URL + */ state: AppState; + /** + * Function to update the time filter + */ timefilterUpdateHandler: (ranges: { from: number; to: number }) => void; + /** + * Currently selected time range + */ timeRange?: { from: string; to: string }; + /** + * Menu data of top navigation (New, save ...) + */ topNavMenu: TopNavMenuData[]; + /** + * Function to update the actual query + */ updateQuery: (payload: { dateRange: TimeRange; query?: Query }, isUpdate?: boolean) => void; + /** + * Function to update the actual savedQuery id + */ updateSavedQueryId: (savedQueryId?: string) => void; } @@ -114,7 +229,6 @@ export const SidebarMemoized = React.memo((props: DiscoverSidebarResponsiveProps )); export function DiscoverLegacy({ - addColumn, fetch, fetchCounter, fieldCounts, @@ -123,6 +237,7 @@ export function DiscoverLegacy({ hits, indexPattern, minimumVisibleRows, + onAddColumn, onAddFilter, onChangeInterval, onMoveColumn, @@ -192,7 +307,7 @@ export function DiscoverLegacy({ fieldCounts={fieldCounts} hits={rows} indexPatternList={indexPatternList} - onAddField={addColumn} + onAddField={onAddColumn} onAddFilter={onAddFilter} onRemoveField={onRemoveColumn} selectedIndexPattern={searchSource && searchSource.getField('index')} @@ -206,6 +321,8 @@ export function DiscoverLegacy({ setIsSidebarClosed(!isSidebarClosed)} data-test-subj="collapseSideBarButton" aria-controls="discover-sidebar" @@ -335,7 +452,7 @@ export function DiscoverLegacy({ sort={state.sort || []} searchDescription={opts.savedSearch.description} searchTitle={opts.savedSearch.lastSavedTitle} - onAddColumn={addColumn} + onAddColumn={onAddColumn} onFilter={onAddFilter} onMoveColumn={onMoveColumn} onRemoveColumn={onRemoveColumn} diff --git a/src/plugins/discover/public/application/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap b/src/plugins/discover/public/application/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap index b5bd961037e2..d02b484a06a4 100644 --- a/src/plugins/discover/public/application/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap +++ b/src/plugins/discover/public/application/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap @@ -6,6 +6,7 @@ exports[`Render with 3 different tabs 1`] = ` > - +
); } diff --git a/src/plugins/discover/public/application/components/field_name/__snapshots__/field_name.test.tsx.snap b/src/plugins/discover/public/application/components/field_name/__snapshots__/field_name.test.tsx.snap index 2fa96f937238..6b5e45f8a044 100644 --- a/src/plugins/discover/public/application/components/field_name/__snapshots__/field_name.test.tsx.snap +++ b/src/plugins/discover/public/application/components/field_name/__snapshots__/field_name.test.tsx.snap @@ -31,7 +31,7 @@ exports[`FieldName renders a geo field 1`] = `
`; -exports[`FieldName renders a number field by providing a field record, useShortDots is set to false 1`] = ` +exports[`FieldName renders a number field by providing a field record 1`] = `
diff --git a/src/plugins/discover/public/application/components/field_name/field_name.test.tsx b/src/plugins/discover/public/application/components/field_name/field_name.test.tsx index 0deddce1c40a..248191acf9ab 100644 --- a/src/plugins/discover/public/application/components/field_name/field_name.test.tsx +++ b/src/plugins/discover/public/application/components/field_name/field_name.test.tsx @@ -27,7 +27,7 @@ test('FieldName renders a string field by providing fieldType and fieldName', () expect(component).toMatchSnapshot(); }); -test('FieldName renders a number field by providing a field record, useShortDots is set to false', () => { +test('FieldName renders a number field by providing a field record', () => { const component = render(); expect(component).toMatchSnapshot(); }); diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx index 391e15485f07..0957ee101bd2 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx @@ -56,7 +56,6 @@ function getComponent({ }: { selected?: boolean; showDetails?: boolean; - useShortDots?: boolean; field?: IndexPatternField; }) { const indexPattern = getStubIndexPattern( diff --git a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.test.ts b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.test.ts index d4670a1e7601..22cacae4c3b4 100644 --- a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.test.ts +++ b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.test.ts @@ -19,51 +19,58 @@ import { groupFields } from './group_fields'; import { getDefaultFieldFilter } from './field_filter'; +import { IndexPatternField } from '../../../../../../data/common/index_patterns/fields'; -describe('group_fields', function () { - it('should group fields in selected, popular, unpopular group', function () { - const fields = [ - { - name: 'category', - type: 'string', - esTypes: ['text'], - count: 1, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'currency', - type: 'string', - esTypes: ['keyword'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'customer_birth_date', - type: 'date', - esTypes: ['date'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - ]; +const fields = [ + { + name: 'category', + type: 'string', + esTypes: ['text'], + count: 1, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'currency', + type: 'string', + esTypes: ['keyword'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + name: 'customer_birth_date', + type: 'date', + esTypes: ['date'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, +]; - const fieldCounts = { - category: 1, - currency: 1, - customer_birth_date: 1, - }; +const fieldCounts = { + category: 1, + currency: 1, + customer_birth_date: 1, +}; +describe('group_fields', function () { + it('should group fields in selected, popular, unpopular group', function () { const fieldFilterState = getDefaultFieldFilter(); - const actual = groupFields(fields as any, ['currency'], 5, fieldCounts, fieldFilterState); + const actual = groupFields( + fields as IndexPatternField[], + ['currency'], + 5, + fieldCounts, + fieldFilterState + ); expect(actual).toMatchInlineSnapshot(` Object { "popular": Array [ @@ -111,4 +118,34 @@ describe('group_fields', function () { } `); }); + + it('should sort selected fields by columns order ', function () { + const fieldFilterState = getDefaultFieldFilter(); + + const actual1 = groupFields( + fields as IndexPatternField[], + ['customer_birth_date', 'currency', 'unknown'], + 5, + fieldCounts, + fieldFilterState + ); + expect(actual1.selected.map((field) => field.name)).toEqual([ + 'customer_birth_date', + 'currency', + 'unknown', + ]); + + const actual2 = groupFields( + fields as IndexPatternField[], + ['currency', 'customer_birth_date', 'unknown'], + 5, + fieldCounts, + fieldFilterState + ); + expect(actual2.selected.map((field) => field.name)).toEqual([ + 'currency', + 'customer_birth_date', + 'unknown', + ]); + }); }); diff --git a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx index c6a06618900f..c34becc97cb9 100644 --- a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx +++ b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx @@ -70,6 +70,15 @@ export function groupFields( result.unpopular.push(field); } } + // add columns, that are not part of the index pattern, to be removeable + for (const column of columns) { + if (!result.selected.find((field) => field.name === column)) { + result.selected.push({ name: column, displayName: column } as IndexPatternField); + } + } + result.selected.sort((a, b) => { + return columns.indexOf(a.name) - columns.indexOf(b.name); + }); return result; } diff --git a/src/plugins/discover/public/application/embeddable/search_embeddable.ts b/src/plugins/discover/public/application/embeddable/search_embeddable.ts index b143afd1988e..e4a8ab7bc67f 100644 --- a/src/plugins/discover/public/application/embeddable/search_embeddable.ts +++ b/src/plugins/discover/public/application/embeddable/search_embeddable.ts @@ -21,9 +21,10 @@ import angular from 'angular'; import _ from 'lodash'; import { Subscription } from 'rxjs'; import { i18n } from '@kbn/i18n'; -import { UiActionsStart, APPLY_FILTER_TRIGGER } from '../../../../ui_actions/public'; +import { UiActionsStart } from '../../../../ui_actions/public'; import { RequestAdapter, Adapters } from '../../../../inspector/public'; import { + APPLY_FILTER_TRIGGER, esFilters, Filter, TimeRange, @@ -35,6 +36,7 @@ import { import { Container, Embeddable } from '../../../../embeddable/public'; import * as columnActions from '../angular/doc_table/actions/columns'; import searchTemplate from './search_template.html'; +import searchTemplateGrid from './search_template_datagrid.html'; import { ISearchEmbeddable, SearchInput, SearchOutput } from './types'; import { SortOrder } from '../angular/doc_table/components/table_header/helpers'; import { getSortForSearchSource } from '../angular/doc_table'; @@ -48,22 +50,29 @@ import { import { SEARCH_EMBEDDABLE_TYPE } from './constants'; import { SavedSearch } from '../..'; import { SAMPLE_SIZE_SETTING, SORT_DEFAULT_ORDER_SETTING } from '../../../common'; +import { DiscoverGridSettings } from '../components/discover_grid/types'; +import { DiscoverServices } from '../../build_services'; +import { ElasticSearchHit } from '../doc_views/doc_views_types'; +import { getDefaultSort } from '../angular/doc_table/lib/get_default_sort'; interface SearchScope extends ng.IScope { columns?: string[]; + settings?: DiscoverGridSettings; description?: string; sort?: SortOrder[]; sharedItemTitle?: string; inspectorAdapters?: Adapters; setSortOrder?: (sortPair: SortOrder[]) => void; + setColumns?: (columns: string[]) => void; removeColumn?: (column: string) => void; addColumn?: (column: string) => void; moveColumn?: (column: string, index: number) => void; filter?: (field: IFieldType, value: string[], operator: string) => void; - hits?: any[]; + hits?: ElasticSearchHit[]; indexPattern?: IndexPattern; totalHitCount?: number; isLoading?: boolean; + showTimeCol?: boolean; } interface SearchEmbeddableConfig { @@ -75,6 +84,7 @@ interface SearchEmbeddableConfig { indexPatterns?: IndexPattern[]; editable: boolean; filterManager: FilterManager; + services: DiscoverServices; } export class SearchEmbeddable @@ -93,6 +103,7 @@ export class SearchEmbeddable public readonly type = SEARCH_EMBEDDABLE_TYPE; private filterManager: FilterManager; private abortController?: AbortController; + private services: DiscoverServices; private prevTimeRange?: TimeRange; private prevFilters?: Filter[]; @@ -109,6 +120,7 @@ export class SearchEmbeddable indexPatterns, editable, filterManager, + services, }: SearchEmbeddableConfig, initialInput: SearchInput, private readonly executeTriggerActions: UiActionsStart['executeTriggerActions'], @@ -126,7 +138,7 @@ export class SearchEmbeddable }, parent ); - + this.services = services; this.filterManager = filterManager; this.savedSearch = savedSearch; this.$rootScope = $rootScope; @@ -136,8 +148,8 @@ export class SearchEmbeddable }; this.initializeSearchScope(); - this.autoRefreshFetchSubscription = getServices() - .timefilter.getAutoRefreshFetch$() + this.autoRefreshFetchSubscription = this.services.timefilter + .getAutoRefreshFetch$() .subscribe(this.fetch); this.subscription = this.getUpdated$().subscribe(() => { @@ -165,7 +177,9 @@ export class SearchEmbeddable if (!this.searchScope) { throw new Error('Search scope not defined'); } - this.searchInstance = this.$compile(searchTemplate)(this.searchScope); + this.searchInstance = this.$compile( + this.services.uiSettings.get('doc_table:legacy', true) ? searchTemplate : searchTemplateGrid + )(this.searchScope); const rootNode = angular.element(domNode); rootNode.append(this.searchInstance); @@ -200,6 +214,13 @@ export class SearchEmbeddable const { searchSource } = this.savedSearch; const indexPattern = (searchScope.indexPattern = searchSource.getField('index'))!; + if (!this.savedSearch.sort || !this.savedSearch.sort.length) { + this.savedSearch.sort = getDefaultSort( + indexPattern, + getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING, 'desc') + ); + } + const timeRangeSearchSource = searchSource.create(); timeRangeSearchSource.setField('filter', () => { if (!this.searchScope || !this.input.timeRange) return; @@ -241,6 +262,15 @@ export class SearchEmbeddable this.updateInput({ columns }); }; + searchScope.setColumns = (columns: string[]) => { + this.updateInput({ columns }); + }; + + if (this.savedSearch.grid) { + searchScope.settings = this.savedSearch.grid; + } + searchScope.showTimeCol = !this.services.uiSettings.get('doc_table:hideTimeColumn', false); + searchScope.filter = async (field, value, operator) => { let filters = esFilters.generateFilters( this.filterManager, @@ -277,13 +307,13 @@ export class SearchEmbeddable if (this.abortController) this.abortController.abort(); this.abortController = new AbortController(); - searchSource.setField('size', getServices().uiSettings.get(SAMPLE_SIZE_SETTING)); + searchSource.setField('size', this.services.uiSettings.get(SAMPLE_SIZE_SETTING)); searchSource.setField( 'sort', getSortForSearchSource( this.searchScope.sort, this.searchScope.indexPattern, - getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING) + this.services.uiSettings.get(SORT_DEFAULT_ORDER_SETTING) ) ); @@ -341,7 +371,14 @@ export class SearchEmbeddable // If there is column or sort data on the panel, that means the original columns or sort settings have // been overridden in a dashboard. searchScope.columns = this.input.columns || this.savedSearch.columns; - searchScope.sort = this.input.sort || this.savedSearch.sort; + const savedSearchSort = + this.savedSearch.sort && this.savedSearch.sort.length + ? this.savedSearch.sort + : getDefaultSort( + this.searchScope?.indexPattern, + getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING, 'desc') + ); + searchScope.sort = this.input.sort || savedSearchSort; searchScope.sharedItemTitle = this.panelTitle; if (forceFetch || isFetchRequired) { diff --git a/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts b/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts index f61fa361f0c0..d85476568201 100644 --- a/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts +++ b/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts @@ -103,6 +103,7 @@ export class SearchEmbeddableFactory filterManager, editable: getServices().capabilities.discover.save as boolean, indexPatterns: indexPattern ? [indexPattern] : [], + services: getServices(), }, input, executeTriggerActions, diff --git a/src/plugins/discover/public/application/embeddable/search_template.html b/src/plugins/discover/public/application/embeddable/search_template.html index e188d230ea30..be2f5cceac08 100644 --- a/src/plugins/discover/public/application/embeddable/search_template.html +++ b/src/plugins/discover/public/application/embeddable/search_template.html @@ -1,20 +1,20 @@ diff --git a/src/plugins/discover/public/application/embeddable/search_template_datagrid.html b/src/plugins/discover/public/application/embeddable/search_template_datagrid.html new file mode 100644 index 000000000000..6524783897f8 --- /dev/null +++ b/src/plugins/discover/public/application/embeddable/search_template_datagrid.html @@ -0,0 +1,19 @@ + diff --git a/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts b/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts index b2aa3a05d7eb..2ab1b93d6c37 100644 --- a/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts +++ b/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts @@ -21,6 +21,7 @@ import { getSharingData } from './get_sharing_data'; import { IUiSettingsClient } from 'kibana/public'; import { createSearchSourceMock } from '../../../../data/common/search/search_source/mocks'; import { indexPatternMock } from '../../__mocks__/index_pattern'; +import { SORT_DEFAULT_ORDER_SETTING } from '../../../common'; describe('getSharingData', () => { test('returns valid data for sharing', async () => { @@ -29,7 +30,10 @@ describe('getSharingData', () => { searchSourceMock, { columns: [] }, ({ - get: () => { + get: (key: string) => { + if (key === SORT_DEFAULT_ORDER_SETTING) { + return 'desc'; + } return false; }, } as unknown) as IUiSettingsClient, @@ -47,7 +51,7 @@ describe('getSharingData', () => { "searchRequest": Object { "body": Object { "_source": Object {}, - "fields": undefined, + "fields": Array [], "query": Object { "bool": Object { "filter": Array [], @@ -57,8 +61,16 @@ describe('getSharingData', () => { }, }, "script_fields": Object {}, - "sort": Array [], - "stored_fields": undefined, + "sort": Array [ + Object { + "_score": Object { + "order": "desc", + }, + }, + ], + "stored_fields": Array [ + "*", + ], }, "index": "the-index-pattern-title", }, diff --git a/src/plugins/discover/public/application/helpers/persist_saved_search.ts b/src/plugins/discover/public/application/helpers/persist_saved_search.ts index 8e956eff598f..8ec2012b5843 100644 --- a/src/plugins/discover/public/application/helpers/persist_saved_search.ts +++ b/src/plugins/discover/public/application/helpers/persist_saved_search.ts @@ -53,6 +53,9 @@ export async function persistSavedSearch( savedSearch.columns = state.columns || []; savedSearch.sort = (state.sort as SortOrder[]) || []; + if (state.grid) { + savedSearch.grid = state.grid; + } try { const id = await savedSearch.save(saveOptions); diff --git a/src/plugins/discover/public/get_inner_angular.ts b/src/plugins/discover/public/get_inner_angular.ts index 651a26cad755..2ace65c31cc0 100644 --- a/src/plugins/discover/public/get_inner_angular.ts +++ b/src/plugins/discover/public/get_inner_angular.ts @@ -41,6 +41,7 @@ import { createTableRowDirective } from './application/angular/doc_table/compone import { createPagerFactory } from './application/angular/doc_table/lib/pager/pager_factory'; import { createInfiniteScrollDirective } from './application/angular/doc_table/infinite_scroll'; import { createDocViewerDirective } from './application/angular/doc_viewer'; +import { createDiscoverGridDirective } from './application/components/create_discover_grid_directive'; import { createRenderCompleteDirective } from './application/angular/directives/render_complete'; import { initAngularBootstrap, @@ -55,6 +56,8 @@ import { import { DiscoverStartPlugins } from './plugin'; import { getScopedHistory } from './kibana_services'; import { createDiscoverLegacyDirective } from './application/components/create_discover_legacy_directive'; +import { createDiscoverDirective } from './application/components/create_discover_directive'; + /** * returns the main inner angular module, it contains all the parts of Angular Discover * needs to render, so in the end the current 'kibana' angular module is no longer necessary @@ -136,7 +139,8 @@ export function initializeInnerAngularModule( .config(watchMultiDecorator) .run(registerListenEventListener) .directive('renderComplete', createRenderCompleteDirective) - .directive('discoverLegacy', createDiscoverLegacyDirective); + .directive('discoverLegacy', createDiscoverLegacyDirective) + .directive('discover', createDiscoverDirective); } function createLocalPromiseModule() { @@ -188,6 +192,7 @@ function createDocTableModule() { .directive('kbnTableRow', createTableRowDirective) .directive('toolBarPagerButtons', createToolBarPagerButtonsDirective) .directive('kbnInfiniteScroll', createInfiniteScrollDirective) + .directive('discoverGrid', createDiscoverGridDirective) .directive('docViewer', createDocViewerDirective) .directive('contextAppLegacy', createContextAppLegacy); } diff --git a/src/plugins/discover/public/saved_searches/_saved_search.ts b/src/plugins/discover/public/saved_searches/_saved_search.ts index 1ec4549f05d4..8a0ec128b4eb 100644 --- a/src/plugins/discover/public/saved_searches/_saved_search.ts +++ b/src/plugins/discover/public/saved_searches/_saved_search.ts @@ -26,6 +26,7 @@ export function createSavedSearchClass(savedObjects: SavedObjectsStart) { description: 'text', hits: 'integer', columns: 'keyword', + grid: 'object', sort: 'keyword', version: 'integer', }; @@ -45,6 +46,7 @@ export function createSavedSearchClass(savedObjects: SavedObjectsStart) { description: 'text', hits: 'integer', columns: 'keyword', + grid: 'object', sort: 'keyword', version: 'integer', }, diff --git a/src/plugins/discover/public/saved_searches/types.ts b/src/plugins/discover/public/saved_searches/types.ts index d5e5dd765a36..7f6f1a2553d5 100644 --- a/src/plugins/discover/public/saved_searches/types.ts +++ b/src/plugins/discover/public/saved_searches/types.ts @@ -19,6 +19,7 @@ import { SearchSource } from '../../../data/public'; import { SavedObjectSaveOpts } from '../../../saved_objects/public'; +import { DiscoverGridSettings } from '../application/components/discover_grid/types'; export type SortOrder = [string, string]; export interface SavedSearch { @@ -28,6 +29,7 @@ export interface SavedSearch { description?: string; columns: string[]; sort: SortOrder[]; + grid: DiscoverGridSettings; destroy: () => void; save: (saveOptions: SavedObjectSaveOpts) => Promise; lastSavedTitle?: string; diff --git a/src/plugins/discover/server/saved_objects/search.ts b/src/plugins/discover/server/saved_objects/search.ts index a6e42f956a02..d124a24b120f 100644 --- a/src/plugins/discover/server/saved_objects/search.ts +++ b/src/plugins/discover/server/saved_objects/search.ts @@ -53,6 +53,7 @@ export const searchSavedObjectType: SavedObjectsType = { }, sort: { type: 'keyword', index: false, doc_values: false }, title: { type: 'text' }, + grid: { type: 'object', enabled: false }, version: { type: 'integer' }, }, }, diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index f45281ee6220..425928385e64 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -33,6 +33,7 @@ import { CONTEXT_DEFAULT_SIZE_SETTING, CONTEXT_STEP_SETTING, CONTEXT_TIE_BREAKER_FIELDS_SETTING, + DOC_TABLE_LEGACY, MODIFY_COLUMNS_ON_SWITCH, } from '../common'; @@ -165,6 +166,23 @@ export const uiSettings: Record = { category: ['discover'], schema: schema.arrayOf(schema.string()), }, + [DOC_TABLE_LEGACY]: { + name: i18n.translate('discover.advancedSettings.docTableVersionName', { + defaultMessage: 'Use legacy table', + }), + value: true, + description: i18n.translate('discover.advancedSettings.docTableVersionDescription', { + defaultMessage: + 'Discover uses a new table layout that includes better data sorting, drag-and-drop columns, and a full screen ' + + 'view. Enable this option if you prefer to fall back to the legacy table.', + }), + category: ['discover'], + schema: schema.boolean(), + metric: { + type: METRIC_TYPE.CLICK, + name: 'discover:useLegacyDataGrid', + }, + }, [MODIFY_COLUMNS_ON_SWITCH]: { name: i18n.translate('discover.advancedSettings.discover.modifyColumnsOnSwitchTitle', { defaultMessage: 'Modify columns when changing index patterns', diff --git a/src/plugins/embeddable/common/types.ts b/src/plugins/embeddable/common/types.ts index 8965446cc85f..8366d81a6575 100644 --- a/src/plugins/embeddable/common/types.ts +++ b/src/plugins/embeddable/common/types.ts @@ -18,8 +18,6 @@ */ import { PersistableStateService, SerializableState } from '../../kibana_utils/common'; -import { Query, TimeRange } from '../../data/common/query'; -import { Filter } from '../../data/common/es_query/filters'; export enum ViewMode { EDIT = 'edit', @@ -54,24 +52,14 @@ export type EmbeddableInput = { disableTriggers?: boolean; /** - * Time range of the chart. - */ - timeRange?: TimeRange; - - /** - * Visualization query string used to narrow down results. - */ - query?: Query; - - /** - * Visualization filters used to narrow down results. + * Search session id to group searches */ - filters?: Filter[]; + searchSessionId?: string; /** - * Search session id to group searches + * Flag whether colors should be synced with other panels */ - searchSessionId?: string; + syncColors?: boolean; }; export interface PanelState { diff --git a/src/plugins/embeddable/public/bootstrap.ts b/src/plugins/embeddable/public/bootstrap.ts index 5c95214ef591..efaff42c19e2 100644 --- a/src/plugins/embeddable/public/bootstrap.ts +++ b/src/plugins/embeddable/public/bootstrap.ts @@ -18,18 +18,24 @@ */ import { UiActionsSetup } from '../../ui_actions/public'; import { - contextMenuTrigger, - panelBadgeTrigger, - EmbeddableContext, - CONTEXT_MENU_TRIGGER, - PANEL_BADGE_TRIGGER, ACTION_ADD_PANEL, ACTION_CUSTOMIZE_PANEL, - ACTION_INSPECT_PANEL, - REMOVE_PANEL_ACTION, ACTION_EDIT_PANEL, - panelNotificationTrigger, + ACTION_INSPECT_PANEL, + CONTEXT_MENU_TRIGGER, + contextMenuTrigger, + EmbeddableContext, + PANEL_BADGE_TRIGGER, PANEL_NOTIFICATION_TRIGGER, + panelBadgeTrigger, + panelNotificationTrigger, + RangeSelectContext, + REMOVE_PANEL_ACTION, + SELECT_RANGE_TRIGGER, + selectRangeTrigger, + ValueClickContext, + VALUE_CLICK_TRIGGER, + valueClickTrigger, } from './lib'; declare module '../../ui_actions/public' { @@ -37,6 +43,8 @@ declare module '../../ui_actions/public' { [CONTEXT_MENU_TRIGGER]: EmbeddableContext; [PANEL_BADGE_TRIGGER]: EmbeddableContext; [PANEL_NOTIFICATION_TRIGGER]: EmbeddableContext; + [SELECT_RANGE_TRIGGER]: RangeSelectContext; + [VALUE_CLICK_TRIGGER]: ValueClickContext; } export interface ActionContextMapping { @@ -56,4 +64,6 @@ export const bootstrap = (uiActions: UiActionsSetup) => { uiActions.registerTrigger(contextMenuTrigger); uiActions.registerTrigger(panelBadgeTrigger); uiActions.registerTrigger(panelNotificationTrigger); + uiActions.registerTrigger(selectRangeTrigger); + uiActions.registerTrigger(valueClickTrigger); }; diff --git a/src/plugins/embeddable/public/index.ts b/src/plugins/embeddable/public/index.ts index 0fc7c7965010..d537ef2bd0c5 100644 --- a/src/plugins/embeddable/public/index.ts +++ b/src/plugins/embeddable/public/index.ts @@ -65,6 +65,8 @@ export { PanelNotFoundError, PanelState, PropertySpec, + SELECT_RANGE_TRIGGER, + VALUE_CLICK_TRIGGER, ViewMode, withEmbeddableSubscription, SavedObjectEmbeddableInput, diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable.test.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable.test.tsx index c7c71656bceb..c0e13a84066c 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable.test.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable.test.tsx @@ -24,8 +24,10 @@ import { Embeddable } from './embeddable'; import { EmbeddableOutput, EmbeddableInput } from './i_embeddable'; import { ViewMode } from '../types'; import { ContactCardEmbeddable } from '../test_samples/embeddables/contact_card/contact_card_embeddable'; -import { FilterableEmbeddable } from '../test_samples/embeddables/filterable_embeddable'; -import type { Filter } from '../../../../data/public'; +import { + MockFilter, + FilterableEmbeddable, +} from '../test_samples/embeddables/filterable_embeddable'; class TestClass { constructor() {} @@ -83,7 +85,7 @@ test('Embeddable reload is called if lastReloadRequest input time changes', asyn test('Embeddable reload is called if lastReloadRequest input time changed and new input is used', async () => { const hello = new FilterableEmbeddable({ id: '123', filters: [], lastReloadRequestTime: 0 }); - const aFilter = ({} as unknown) as Filter; + const aFilter = ({} as unknown) as MockFilter; hello.reload = jest.fn(() => { // when reload is called embeddable already has new input expect(hello.getInput().filters).toEqual([aFilter]); diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx index 0361939fd07e..cb78fac5471a 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx @@ -20,6 +20,7 @@ import { ViewMode, EmbeddableOutput, isErrorEmbeddable } from '../../../../'; import { AddPanelAction } from './add_panel_action'; import { + MockFilter, FILTERABLE_EMBEDDABLE, FilterableEmbeddable, FilterableEmbeddableInput, @@ -28,7 +29,6 @@ import { FilterableEmbeddableFactory } from '../../../../test_samples/embeddable import { FilterableContainer } from '../../../../test_samples/embeddables/filterable_container'; import { coreMock } from '../../../../../../../../core/public/mocks'; import { ContactCardEmbeddable } from '../../../../test_samples'; -import { esFilters, Filter } from '../../../../../../../../plugins/data/public'; import { EmbeddableStart } from '../../../../../plugin'; import { embeddablePluginMock } from '../../../../../mocks'; import { defaultTrigger } from '../../../../../../../ui_actions/public/triggers'; @@ -51,8 +51,8 @@ beforeEach(async () => { () => null ); - const derivedFilter: Filter = { - $state: { store: esFilters.FilterStateStore.APP_STATE }, + const derivedFilter: MockFilter = { + $state: { store: 'appState' }, meta: { disabled: false, alias: 'name', negate: false }, query: { match: {} }, }; diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/open_add_panel_flyout.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/open_add_panel_flyout.tsx index 867092b78ef7..3363f556b418 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/open_add_panel_flyout.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/open_add_panel_flyout.tsx @@ -17,20 +17,20 @@ * under the License. */ import React from 'react'; -import { NotificationsStart, OverlayStart } from 'src/core/public'; +import { NotificationsStart, OverlayRef, OverlayStart } from 'src/core/public'; import { EmbeddableStart } from '../../../../../plugin'; import { toMountPoint } from '../../../../../../../kibana_react/public'; import { IContainer } from '../../../../containers'; import { AddPanelFlyout } from './add_panel_flyout'; -export async function openAddPanelFlyout(options: { +export function openAddPanelFlyout(options: { embeddable: IContainer; getFactory: EmbeddableStart['getEmbeddableFactory']; getAllFactories: EmbeddableStart['getEmbeddableFactories']; overlays: OverlayStart; notifications: NotificationsStart; SavedObjectFinder: React.ComponentType; -}) { +}): OverlayRef { const { embeddable, getFactory, @@ -59,4 +59,5 @@ export async function openAddPanelFlyout(options: { ownFocus: true, } ); + return flyoutSession; } diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx index eb8364144898..b784a4612730 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx @@ -29,7 +29,6 @@ import { import { inspectorPluginMock } from '../../../../../../../plugins/inspector/public/mocks'; import { EmbeddableOutput, isErrorEmbeddable, ErrorEmbeddable } from '../../../embeddables'; import { of } from '../../../../tests/helpers'; -import { esFilters } from '../../../../../../../plugins/data/public'; import { embeddablePluginMock } from '../../../../mocks'; import { EmbeddableStart } from '../../../../plugin'; @@ -43,7 +42,7 @@ const setupTests = async () => { panels: {}, filters: [ { - $state: { store: esFilters.FilterStateStore.APP_STATE }, + $state: { store: 'appState' }, meta: { disabled: false, alias: 'name', negate: false }, query: { match: {} }, }, diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx index dea4a88bda08..ce6a1cc20fc4 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx @@ -21,6 +21,7 @@ import { EmbeddableOutput, isErrorEmbeddable } from '../../../'; import { RemovePanelAction } from './remove_panel_action'; import { EmbeddableStart } from '../../../../plugin'; import { + MockFilter, FILTERABLE_EMBEDDABLE, FilterableEmbeddable, FilterableEmbeddableInput, @@ -29,7 +30,6 @@ import { FilterableEmbeddableFactory } from '../../../test_samples/embeddables/f import { FilterableContainer } from '../../../test_samples/embeddables/filterable_container'; import { ViewMode } from '../../../types'; import { ContactCardEmbeddable } from '../../../test_samples/embeddables/contact_card/contact_card_embeddable'; -import { esFilters, Filter } from '../../../../../../../plugins/data/public'; import { embeddablePluginMock } from '../../../../mocks'; const { setup, doStart } = embeddablePluginMock.createInstance(); @@ -39,8 +39,8 @@ let container: FilterableContainer; let embeddable: FilterableEmbeddable; beforeEach(async () => { - const derivedFilter: Filter = { - $state: { store: esFilters.FilterStateStore.APP_STATE }, + const derivedFilter: MockFilter = { + $state: { store: 'appState' }, meta: { disabled: false, alias: 'name', negate: false }, query: { match: {} }, }; diff --git a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts index cbaeddf472d5..be034d125dce 100644 --- a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts +++ b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts @@ -23,6 +23,7 @@ import { EmbeddableStateTransfer } from '.'; import { ApplicationStart, PublicAppInfo } from '../../../../../core/public'; import { EMBEDDABLE_EDITOR_STATE_KEY, EMBEDDABLE_PACKAGE_STATE_KEY } from './types'; import { EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY } from './embeddable_state_transfer'; +import { Subject } from 'rxjs'; const createStorage = (): Storage => { const createMockStore = () => { @@ -46,16 +47,24 @@ const createStorage = (): Storage => { describe('embeddable state transfer', () => { let application: jest.Mocked; let stateTransfer: EmbeddableStateTransfer; + let currentAppId$: Subject; let store: Storage; const destinationApp = 'superUltraVisualize'; const originatingApp = 'superUltraTestDashboard'; beforeEach(() => { + currentAppId$ = new Subject(); + currentAppId$.next(originatingApp); const core = coreMock.createStart(); application = core.application; store = createStorage(); - stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, undefined, store); + stateTransfer = new EmbeddableStateTransfer( + application.navigateToApp, + currentAppId$, + undefined, + store + ); }); it('cannot fetch app name when given no app list', async () => { @@ -67,7 +76,7 @@ describe('embeddable state transfer', () => { ['testId', { title: 'State Transfer Test App Hello' } as PublicAppInfo], ['testId2', { title: 'State Transfer Test App Goodbye' } as PublicAppInfo], ]); - stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, appsList); + stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, currentAppId$, appsList); expect(stateTransfer.getAppNameFromId('kibanana')).toBeUndefined(); }); @@ -76,7 +85,7 @@ describe('embeddable state transfer', () => { ['testId', { title: 'State Transfer Test App Hello' } as PublicAppInfo], ['testId2', { title: 'State Transfer Test App Goodbye' } as PublicAppInfo], ]); - stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, appsList); + stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, currentAppId$, appsList); expect(stateTransfer.getAppNameFromId('testId')).toBe('State Transfer Test App Hello'); expect(stateTransfer.getAppNameFromId('testId2')).toBe('State Transfer Test App Goodbye'); }); @@ -107,6 +116,13 @@ describe('embeddable state transfer', () => { }); }); + it('sets isTransferInProgress to true when sending an outgoing editor state', async () => { + await stateTransfer.navigateToEditor(destinationApp, { state: { originatingApp } }); + expect(stateTransfer.isTransferInProgress).toEqual(true); + currentAppId$.next(destinationApp); + expect(stateTransfer.isTransferInProgress).toEqual(false); + }); + it('can send an outgoing embeddable package state', async () => { await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, { state: { type: 'coolestType', input: { savedObjectId: '150' } }, @@ -135,6 +151,15 @@ describe('embeddable state transfer', () => { }); }); + it('sets isTransferInProgress to true when sending an outgoing embeddable package state', async () => { + await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, { + state: { type: 'coolestType', input: { savedObjectId: '150' } }, + }); + expect(stateTransfer.isTransferInProgress).toEqual(true); + currentAppId$.next(destinationApp); + expect(stateTransfer.isTransferInProgress).toEqual(false); + }); + it('can fetch an incoming editor state', async () => { store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, { [EMBEDDABLE_EDITOR_STATE_KEY]: { originatingApp: 'superUltraTestDashboard' }, diff --git a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts index 0b34bea81052..92900059668d 100644 --- a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts +++ b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts @@ -38,14 +38,20 @@ export const EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY = 'EMBEDDABLE_STATE_TRANSFER' * @public */ export class EmbeddableStateTransfer { + public isTransferInProgress: boolean; private storage: Storage; constructor( private navigateToApp: ApplicationStart['navigateToApp'], + currentAppId$: ApplicationStart['currentAppId$'], private appList?: ReadonlyMap | undefined, customStorage?: Storage ) { this.storage = customStorage ? customStorage : new Storage(sessionStorage); + this.isTransferInProgress = false; + currentAppId$.subscribe(() => { + this.isTransferInProgress = false; + }); } /** @@ -105,6 +111,7 @@ export class EmbeddableStateTransfer { state: EmbeddableEditorState; } ): Promise { + this.isTransferInProgress = true; await this.navigateToWithState(appId, EMBEDDABLE_EDITOR_STATE_KEY, { ...options, appendToExistingState: true, @@ -119,6 +126,7 @@ export class EmbeddableStateTransfer { appId: string, options?: { path?: string; state: EmbeddablePackageState } ): Promise { + this.isTransferInProgress = true; await this.navigateToWithState(appId, EMBEDDABLE_PACKAGE_STATE_KEY, { ...options, appendToExistingState: true, diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx index db71b94ac855..23696612fd82 100644 --- a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx +++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx @@ -18,13 +18,13 @@ */ import { Container, ContainerInput } from '../../containers'; -import { Filter } from '../../../../../data/public'; import { EmbeddableStart } from '../../../plugin'; +import { MockFilter } from './filterable_embeddable'; export const FILTERABLE_CONTAINER = 'FILTERABLE_CONTAINER'; export interface FilterableContainerInput extends ContainerInput { - filters: Filter[]; + filters: MockFilter[]; } /** @@ -33,7 +33,7 @@ export interface FilterableContainerInput extends ContainerInput { * here instead */ export type InheritedChildrenInput = { - filters: Filter[]; + filters: MockFilter[]; id?: string; }; diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx index fd6ea3b9aa2b..99d21198dd15 100644 --- a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx +++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx @@ -19,12 +19,18 @@ import { IContainer } from '../../containers'; import { EmbeddableOutput, EmbeddableInput, Embeddable } from '../../embeddables'; -import { Filter } from '../../../../../data/public'; + +/** @internal */ +export interface MockFilter { + $state?: any; + meta: any; + query?: any; +} export const FILTERABLE_EMBEDDABLE = 'FILTERABLE_EMBEDDABLE'; export interface FilterableEmbeddableInput extends EmbeddableInput { - filters: Filter[]; + filters: MockFilter[]; } export class FilterableEmbeddable extends Embeddable { diff --git a/src/plugins/embeddable/public/lib/triggers/triggers.ts b/src/plugins/embeddable/public/lib/triggers/triggers.ts index c3b1496b8eca..d9fb063a5bb5 100644 --- a/src/plugins/embeddable/public/lib/triggers/triggers.ts +++ b/src/plugins/embeddable/public/lib/triggers/triggers.ts @@ -22,8 +22,8 @@ import { Datatable } from '../../../../expressions'; import { Trigger, RowClickContext } from '../../../../ui_actions/public'; import { IEmbeddable } from '..'; -export interface EmbeddableContext { - embeddable: IEmbeddable; +export interface EmbeddableContext { + embeddable: T; } export interface ValueClickContext { @@ -88,6 +88,28 @@ export const panelNotificationTrigger: Trigger<'PANEL_NOTIFICATION_TRIGGER'> = { }), }; +export const SELECT_RANGE_TRIGGER = 'SELECT_RANGE_TRIGGER'; +export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> = { + id: SELECT_RANGE_TRIGGER, + title: i18n.translate('embeddableApi.selectRangeTrigger.title', { + defaultMessage: 'Range selection', + }), + description: i18n.translate('embeddableApi.selectRangeTrigger.description', { + defaultMessage: 'A range of values on the visualization', + }), +}; + +export const VALUE_CLICK_TRIGGER = 'VALUE_CLICK_TRIGGER'; +export const valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'> = { + id: VALUE_CLICK_TRIGGER, + title: i18n.translate('embeddableApi.valueClickTrigger.title', { + defaultMessage: 'Single click', + }), + description: i18n.translate('embeddableApi.valueClickTrigger.description', { + defaultMessage: 'A data point click on the visualization', + }), +}; + export const isValueClickTriggerContext = ( context: ChartActionContext ): context is ValueClickContext => context.data && 'data' in context.data; diff --git a/src/plugins/embeddable/public/mocks.tsx b/src/plugins/embeddable/public/mocks.tsx index df24d9c0393f..c41ecaabe847 100644 --- a/src/plugins/embeddable/public/mocks.tsx +++ b/src/plugins/embeddable/public/mocks.tsx @@ -34,7 +34,6 @@ import { coreMock } from '../../../core/public/mocks'; import { UiActionsService } from './lib/ui_actions'; import { CoreStart } from '../../../core/public'; import { Start as InspectorStart } from '../../inspector/public'; -import { dataPluginMock } from '../../data/public/mocks'; import { inspectorPluginMock } from '../../inspector/public/mocks'; import { uiActionsPluginMock } from '../../ui_actions/public/mocks'; @@ -136,13 +135,11 @@ const createInstance = (setupPlugins: Partial = {}) const plugin = new EmbeddablePublicPlugin({} as any); const setup = plugin.setup(coreMock.createSetup(), { uiActions: setupPlugins.uiActions || uiActionsPluginMock.createSetupContract(), - data: dataPluginMock.createSetupContract(), }); const doStart = (startPlugins: Partial = {}) => plugin.start(coreMock.createStart(), { uiActions: startPlugins.uiActions || uiActionsPluginMock.createStartContract(), inspector: inspectorPluginMock.createStartContract(), - data: dataPluginMock.createStartContract(), }); return { plugin, diff --git a/src/plugins/embeddable/public/plugin.tsx b/src/plugins/embeddable/public/plugin.tsx index 5118a1a8818c..a417fb3938b8 100644 --- a/src/plugins/embeddable/public/plugin.tsx +++ b/src/plugins/embeddable/public/plugin.tsx @@ -19,7 +19,6 @@ import React from 'react'; import { Subscription } from 'rxjs'; import { identity } from 'lodash'; -import { DataPublicPluginSetup, DataPublicPluginStart } from '../../data/public'; import { getSavedObjectFinder, showSaveModal } from '../../saved_objects/public'; import { UiActionsSetup, UiActionsStart } from '../../ui_actions/public'; import { Start as InspectorStart } from '../../inspector/public'; @@ -62,12 +61,10 @@ import { } from '../common/lib'; export interface EmbeddableSetupDependencies { - data: DataPublicPluginSetup; uiActions: UiActionsSetup; } export interface EmbeddableStartDependencies { - data: DataPublicPluginStart; uiActions: UiActionsStart; inspector: InspectorStart; } @@ -144,7 +141,7 @@ export class EmbeddablePublicPlugin implements Plugin { this.embeddableFactories.set( @@ -161,6 +158,7 @@ export class EmbeddablePublicPlugin implements Plugin storage - ? new EmbeddableStateTransfer(core.application.navigateToApp, this.appList, storage) + ? new EmbeddableStateTransfer( + core.application.navigateToApp, + core.application.currentAppId$, + this.appList, + storage + ) : this.stateTransferService, EmbeddablePanel: getEmbeddablePanelHoc(), telemetry: getTelemetryFunction(commonContract), diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md index 03818fccda0b..b20d5866298d 100644 --- a/src/plugins/embeddable/public/public.api.md +++ b/src/plugins/embeddable/public/public.api.md @@ -8,88 +8,54 @@ import { Action } from 'history'; import { Action as Action_3 } from 'src/plugins/ui_actions/public'; import { ActionExecutionContext as ActionExecutionContext_2 } from 'src/plugins/ui_actions/public'; import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; -import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch'; import { ApplicationStart as ApplicationStart_2 } from 'kibana/public'; -import { Assign } from '@kbn/utility-types'; -import { BehaviorSubject } from 'rxjs'; -import { BfetchPublicSetup } from 'src/plugins/bfetch/public'; import Boom from '@hapi/boom'; import { ConfigDeprecationProvider } from '@kbn/config'; -import { CoreSetup as CoreSetup_2 } from 'src/core/public'; -import { CoreSetup as CoreSetup_3 } from 'kibana/public'; -import { CoreStart as CoreStart_2 } from 'kibana/public'; import * as CSS from 'csstype'; -import { DatatableColumn as DatatableColumn_2 } from 'src/plugins/expressions'; import { EmbeddableStart as EmbeddableStart_2 } from 'src/plugins/embeddable/public/plugin'; -import { Ensure } from '@kbn/utility-types'; import { EnvironmentMode } from '@kbn/config'; -import { ErrorToastOptions as ErrorToastOptions_2 } from 'src/core/public/notifications'; import { EuiBreadcrumb } from '@elastic/eui'; import { EuiButtonEmptyProps } from '@elastic/eui'; -import { EuiComboBoxProps } from '@elastic/eui'; import { EuiConfirmModalProps } from '@elastic/eui'; import { EuiContextMenuPanelDescriptor } from '@elastic/eui'; import { EuiFlyoutSize } from '@elastic/eui'; import { EuiGlobalToastListToast } from '@elastic/eui'; import { EventEmitter } from 'events'; -import { ExpressionAstExpression } from 'src/plugins/expressions/common'; import { History } from 'history'; import { Href } from 'history'; -import { HttpSetup as HttpSetup_2 } from 'kibana/public'; import { I18nStart as I18nStart_2 } from 'src/core/public'; import { IconType } from '@elastic/eui'; -import { ISearchOptions } from 'src/plugins/data/public'; -import { ISearchSource } from 'src/plugins/data/public'; -import { IStorageWrapper as IStorageWrapper_2 } from 'src/plugins/kibana_utils/public'; -import { IUiSettingsClient as IUiSettingsClient_2 } from 'src/core/public'; import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; import { Logger } from '@kbn/logging'; import { LogMeta } from '@kbn/logging'; import { MaybePromise } from '@kbn/utility-types'; -import { Moment } from 'moment'; -import { NameList } from 'elasticsearch'; import { NotificationsStart as NotificationsStart_2 } from 'src/core/public'; import { Observable } from 'rxjs'; import { Optional } from '@kbn/utility-types'; +import { OverlayRef as OverlayRef_2 } from 'src/core/public'; import { OverlayStart as OverlayStart_2 } from 'src/core/public'; import { PackageInfo } from '@kbn/config'; import { Path } from 'history'; import { PluginInitializerContext } from 'src/core/public'; -import { PluginInitializerContext as PluginInitializerContext_3 } from 'kibana/public'; import * as PropTypes from 'prop-types'; -import { PublicContract } from '@kbn/utility-types'; import { PublicMethodsOf } from '@kbn/utility-types'; import { PublicUiSettingsParams } from 'src/core/server/types'; import React from 'react'; import { RecursiveReadonly } from '@kbn/utility-types'; -import { RequestAdapter as RequestAdapter_2 } from 'src/plugins/inspector/common'; -import { Required } from '@kbn/utility-types'; import * as Rx from 'rxjs'; -import { SavedObject as SavedObject_2 } from 'kibana/server'; -import { SavedObject as SavedObject_3 } from 'src/core/server'; import { SavedObjectAttributes } from 'kibana/server'; import { SavedObjectAttributes as SavedObjectAttributes_2 } from 'src/core/public'; import { SavedObjectAttributes as SavedObjectAttributes_3 } from 'kibana/public'; -import { SavedObjectsClientContract as SavedObjectsClientContract_3 } from 'src/core/public'; -import { SavedObjectsFindOptions as SavedObjectsFindOptions_3 } from 'kibana/public'; -import { SavedObjectsFindResponse as SavedObjectsFindResponse_2 } from 'kibana/server'; -import { Search } from '@elastic/elasticsearch/api/requestParams'; -import { SearchResponse } from 'elasticsearch'; -import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; import { ShallowPromise } from '@kbn/utility-types'; import { SimpleSavedObject as SimpleSavedObject_2 } from 'src/core/public'; import { Start as Start_2 } from 'src/plugins/inspector/public'; -import { StartServicesAccessor as StartServicesAccessor_2 } from 'kibana/public'; -import { ToastInputFields as ToastInputFields_2 } from 'src/core/public/notifications'; -import { ToastsSetup as ToastsSetup_2 } from 'kibana/public'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; import { TypeOf } from '@kbn/config-schema'; import { UiComponent } from 'src/plugins/kibana_utils/public'; -import { UiCounterMetricType } from '@kbn/analytics'; import { UnregisterCallback } from 'history'; import { UserProvidedValues } from 'src/core/server/types'; @@ -348,7 +314,7 @@ export abstract class Embeddable { +export class EmbeddableChildPanel extends React.Component { constructor(props: EmbeddableChildPanelProps); // (undocumented) [panel: string]: any; @@ -381,9 +347,9 @@ export interface EmbeddableChildPanelProps { // Warning: (ae-missing-release-tag) "EmbeddableContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface EmbeddableContext { +export interface EmbeddableContext { // (undocumented) - embeddable: IEmbeddable; + embeddable: T; } // @public @@ -444,10 +410,8 @@ export type EmbeddableInput = { enhancements?: SerializableState; disabledActions?: string[]; disableTriggers?: boolean; - timeRange?: TimeRange; - query?: Query; - filters?: Filter[]; searchSessionId?: string; + syncColors?: boolean; }; // Warning: (ae-missing-release-tag) "EmbeddableInstanceConfiguration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -501,7 +465,7 @@ export interface EmbeddablePackageState { // Warning: (ae-missing-release-tag) "EmbeddablePanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export class EmbeddablePanel extends React.Component { +export class EmbeddablePanel extends React.Component { constructor(props: Props); // (undocumented) closeMyContextMenuPanel: () => void; @@ -571,10 +535,6 @@ export interface EmbeddableSetup { // // @public (undocumented) export interface EmbeddableSetupDependencies { - // Warning: (ae-forgotten-export) The symbol "DataPublicPluginSetup" needs to be exported by the entry point index.d.ts - // - // (undocumented) - data: DataPublicPluginSetup; // Warning: (ae-forgotten-export) The symbol "UiActionsSetup" needs to be exported by the entry point index.d.ts // // (undocumented) @@ -610,10 +570,6 @@ export interface EmbeddableStart extends PersistableStateService | undefined, customStorage?: Storage); + constructor(navigateToApp: ApplicationStart['navigateToApp'], currentAppId$: ApplicationStart['currentAppId$'], appList?: ReadonlyMap | undefined, customStorage?: Storage); // (undocumented) clearEditorState(): void; getAppNameFromId: (appId: string) => string | undefined; getIncomingEditorState(removeAfterFetch?: boolean): EmbeddableEditorState | undefined; getIncomingEmbeddablePackage(removeAfterFetch?: boolean): EmbeddablePackageState | undefined; + // (undocumented) + isTransferInProgress: boolean; // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ApplicationStart" navigateToEditor(appId: string, options?: { path?: string; @@ -713,7 +671,7 @@ export interface IEmbeddable context is EmbeddableContext; +export const isContextMenuTriggerContext: (context: unknown) => context is EmbeddableContext>; // Warning: (ae-missing-release-tag) "isEmbeddable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -760,7 +718,7 @@ export function openAddPanelFlyout(options: { overlays: OverlayStart_2; notifications: NotificationsStart_2; SavedObjectFinder: React.ComponentType; -}): Promise; +}): OverlayRef_2; // Warning: (ae-missing-release-tag) "OutputSpec" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -867,6 +825,16 @@ export interface SavedObjectEmbeddableInput extends EmbeddableInput { savedObjectId: string; } +// Warning: (ae-missing-release-tag) "SELECT_RANGE_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const SELECT_RANGE_TRIGGER = "SELECT_RANGE_TRIGGER"; + +// Warning: (ae-missing-release-tag) "VALUE_CLICK_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const VALUE_CLICK_TRIGGER = "VALUE_CLICK_TRIGGER"; + // Warning: (ae-missing-release-tag) "ValueClickContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -910,10 +878,7 @@ export const withEmbeddableSubscription: { test('Explicit embeddable input mapped to undefined will default to inherited', async () => { const { start } = await creatHelloWorldContainerAndEmbeddable(); - const derivedFilter: Filter = { - $state: { store: esFilters.FilterStateStore.APP_STATE }, + const derivedFilter: MockFilter = { + $state: { store: 'appState' }, meta: { disabled: false, alias: 'name', negate: false }, query: { match: {} }, }; diff --git a/src/plugins/embeddable/public/tests/explicit_input.test.ts b/src/plugins/embeddable/public/tests/explicit_input.test.ts index 24785dd50a03..531fbcee94db 100644 --- a/src/plugins/embeddable/public/tests/explicit_input.test.ts +++ b/src/plugins/embeddable/public/tests/explicit_input.test.ts @@ -20,6 +20,7 @@ import { skip } from 'rxjs/operators'; import { testPlugin } from './test_plugin'; import { + MockFilter, FILTERABLE_EMBEDDABLE, FilterableEmbeddableInput, } from '../lib/test_samples/embeddables/filterable_embeddable'; @@ -34,7 +35,6 @@ import { FilterableContainer } from '../lib/test_samples/embeddables/filterable_ import { isErrorEmbeddable } from '../lib'; import { HelloWorldContainer } from '../lib/test_samples/embeddables/hello_world_container'; import { coreMock } from '../../../../core/public/mocks'; -import { esFilters, Filter } from '../../../../plugins/data/public'; import { createEmbeddablePanelMock } from '../mocks'; const { setup, doStart, coreStart, uiActions } = testPlugin( @@ -56,8 +56,8 @@ setup.registerEmbeddableFactory( const start = doStart(); test('Explicit embeddable input mapped to undefined will default to inherited', async () => { - const derivedFilter: Filter = { - $state: { store: esFilters.FilterStateStore.APP_STATE }, + const derivedFilter: MockFilter = { + $state: { store: 'appState' }, meta: { disabled: false, alias: 'name', negate: false }, query: { match: {} }, }; diff --git a/src/plugins/embeddable/public/tests/test_plugin.ts b/src/plugins/embeddable/public/tests/test_plugin.ts index 2c298b437a11..74bb70e913bc 100644 --- a/src/plugins/embeddable/public/tests/test_plugin.ts +++ b/src/plugins/embeddable/public/tests/test_plugin.ts @@ -21,7 +21,6 @@ import { CoreSetup, CoreStart } from 'src/core/public'; import { UiActionsStart } from '../../../ui_actions/public'; import { uiActionsPluginMock } from '../../../ui_actions/public/mocks'; import { inspectorPluginMock } from '../../../inspector/public/mocks'; -import { dataPluginMock } from '../../../data/public/mocks'; import { coreMock } from '../../../../core/public/mocks'; import { EmbeddablePublicPlugin, EmbeddableSetup, EmbeddableStart } from '../plugin'; @@ -42,7 +41,6 @@ export const testPlugin = ( const initializerContext = {} as any; const plugin = new EmbeddablePublicPlugin(initializerContext); const setup = plugin.setup(coreSetup, { - data: dataPluginMock.createSetupContract(), uiActions: uiActions.setup, }); @@ -53,7 +51,6 @@ export const testPlugin = ( setup, doStart: (anotherCoreStart: CoreStart = coreStart) => { const start = plugin.start(anotherCoreStart, { - data: dataPluginMock.createStartContract(), inspector: inspectorPluginMock.createStartContract(), uiActions: uiActionsPluginMock.createStartContract(), }); diff --git a/src/plugins/es_ui_shared/public/components/cron_editor/cron_editor.tsx b/src/plugins/es_ui_shared/public/components/cron_editor/cron_editor.tsx index 72e2f51c37e4..19af93b67aca 100644 --- a/src/plugins/es_ui_shared/public/components/cron_editor/cron_editor.tsx +++ b/src/plugins/es_ui_shared/public/components/cron_editor/cron_editor.tsx @@ -67,6 +67,7 @@ interface Props { fieldToPreferredValueMap: FieldToValueMap; frequency: Frequency; }) => void; + autoFocus?: boolean; } type State = FieldToValueMap; @@ -234,6 +235,7 @@ export class CronEditor extends Component { fullWidth > ) => diff --git a/src/plugins/expressions/common/expression_renderers/types.ts b/src/plugins/expressions/common/expression_renderers/types.ts index 88aca4c07ee3..3f3cfb9ed2dd 100644 --- a/src/plugins/expressions/common/expression_renderers/types.ts +++ b/src/plugins/expressions/common/expression_renderers/types.ts @@ -17,8 +17,6 @@ * under the License. */ -import { PersistedState } from 'src/plugins/visualizations/public'; - export interface ExpressionRenderDefinition { /** * Technical name of the renderer, used as ID to identify renderer in @@ -84,5 +82,11 @@ export interface IInterpreterRenderHandlers { event: (event: any) => void; hasCompatibleActions?: (event: any) => Promise; getRenderMode: () => RenderMode; - uiState?: PersistedState; + isSyncColorsEnabled: () => boolean; + /** + * This uiState interface is actually `PersistedState` from the visualizations plugin, + * but expressions cannot know about vis or it creates a mess of circular dependencies. + * Downstream consumers of the uiState handler will need to cast for now. + */ + uiState?: unknown; } diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts index e9e0fa18af6c..1cf499ce2635 100644 --- a/src/plugins/expressions/public/loader.ts +++ b/src/plugins/expressions/public/loader.ts @@ -64,6 +64,7 @@ export class ExpressionLoader { this.renderHandler = new ExpressionRenderHandler(element, { onRenderError: params && params.onRenderError, renderMode: params?.renderMode, + syncColors: params?.syncColors, hasCompatibleActions: params?.hasCompatibleActions, }); this.render$ = this.renderHandler.render$; diff --git a/src/plugins/expressions/public/public.api.md b/src/plugins/expressions/public/public.api.md index bb1f5dd9270d..5c018adc0131 100644 --- a/src/plugins/expressions/public/public.api.md +++ b/src/plugins/expressions/public/public.api.md @@ -12,7 +12,6 @@ import { EventEmitter } from 'events'; import { KibanaRequest } from 'src/core/server'; import { Observable } from 'rxjs'; import { PackageInfo } from '@kbn/config'; -import { PersistedState } from 'src/plugins/visualizations/public'; import { Plugin as Plugin_2 } from 'src/core/public'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public'; import React from 'react'; @@ -532,7 +531,7 @@ export interface ExpressionRenderError extends Error { // @public (undocumented) export class ExpressionRenderHandler { // Warning: (ae-forgotten-export) The symbol "ExpressionRenderHandlerParams" needs to be exported by the entry point index.d.ts - constructor(element: HTMLElement, { onRenderError, renderMode, hasCompatibleActions, }?: ExpressionRenderHandlerParams); + constructor(element: HTMLElement, { onRenderError, renderMode, syncColors, hasCompatibleActions, }?: ExpressionRenderHandlerParams); // (undocumented) destroy: () => void; // (undocumented) @@ -904,6 +903,8 @@ export interface IExpressionLoaderParams { // (undocumented) searchSessionId?: string; // (undocumented) + syncColors?: boolean; + // (undocumented) uiState?: unknown; // (undocumented) variables?: Record; @@ -921,11 +922,12 @@ export interface IInterpreterRenderHandlers { // (undocumented) hasCompatibleActions?: (event: any) => Promise; // (undocumented) + isSyncColorsEnabled: () => boolean; + // (undocumented) onDestroy: (fn: () => void) => void; // (undocumented) reload: () => void; - // (undocumented) - uiState?: PersistedState; + uiState?: unknown; // (undocumented) update: (params: any) => void; } diff --git a/src/plugins/expressions/public/react_expression_renderer.test.tsx b/src/plugins/expressions/public/react_expression_renderer.test.tsx index e52d4d153882..ac6fcab33acb 100644 --- a/src/plugins/expressions/public/react_expression_renderer.test.tsx +++ b/src/plugins/expressions/public/react_expression_renderer.test.tsx @@ -146,6 +146,44 @@ describe('ExpressionRenderer', () => { instance.unmount(); }); + it('waits for debounce period on other loader option change if specified', () => { + jest.useFakeTimers(); + + const refreshSubject = new Subject(); + const loaderUpdate = jest.fn(); + + (ExpressionLoader as jest.Mock).mockImplementation(() => { + return { + render$: new Subject(), + data$: new Subject(), + loading$: new Subject(), + update: loaderUpdate, + destroy: jest.fn(), + }; + }); + + const instance = mount( + + ); + + instance.setProps({ searchContext: { from: 'now-30m', to: 'now' } }); + + expect(loaderUpdate).toHaveBeenCalledTimes(1); + + act(() => { + jest.runAllTimers(); + }); + + expect(loaderUpdate).toHaveBeenCalledTimes(2); + + instance.unmount(); + }); + it('should display a custom error message if the user provides one and then remove it after successful render', () => { const dataSubject = new Subject(); const data$ = dataSubject.asObservable().pipe(share()); @@ -266,4 +304,22 @@ describe('ExpressionRenderer', () => { expect(onEvent).toHaveBeenCalledTimes(1); expect(onEvent.mock.calls[0][0]).toBe(event); }); + + it('should correctly assign classes to the wrapper node', () => { + (ExpressionLoader as jest.Mock).mockImplementation(() => { + return { + render$: new Subject(), + data$: new Subject(), + loading$: new Subject(), + update: jest.fn(), + destroy: jest.fn(), + }; + }); + + const instance = mount(); + // Counte is 2 because the class is applied to ReactExpressionRenderer + internal component + expect(instance.find('.myClassName').length).toBe(2); + + instance.unmount(); + }); }); diff --git a/src/plugins/expressions/public/react_expression_renderer.tsx b/src/plugins/expressions/public/react_expression_renderer.tsx index 894325c8b65f..3227b34dcc1f 100644 --- a/src/plugins/expressions/public/react_expression_renderer.tsx +++ b/src/plugins/expressions/public/react_expression_renderer.tsx @@ -90,21 +90,23 @@ export const ReactExpressionRenderer = ({ null ); const [debouncedExpression, setDebouncedExpression] = useState(expression); - useEffect(() => { + const [waitingForDebounceToComplete, setDebouncePending] = useState(false); + useShallowCompareEffect(() => { if (debounce === undefined) { return; } + setDebouncePending(true); const handler = setTimeout(() => { setDebouncedExpression(expression); + setDebouncePending(false); }, debounce); return () => { clearTimeout(handler); }; - }, [expression, debounce]); + }, [expression, expressionLoaderOptions, debounce]); const activeExpression = debounce !== undefined ? debouncedExpression : expression; - const waitingForDebounceToComplete = debounce !== undefined && expression !== debouncedExpression; /* eslint-disable react-hooks/exhaustive-deps */ // OK to ignore react-hooks/exhaustive-deps because options update is handled by calling .update() @@ -168,7 +170,12 @@ export const ReactExpressionRenderer = ({ errorRenderHandlerRef.current = null; }; - }, [hasCustomRenderErrorHandler, onEvent]); + }, [ + hasCustomRenderErrorHandler, + onEvent, + expressionLoaderOptions.renderMode, + expressionLoaderOptions.syncColors, + ]); useEffect(() => { const subscription = reload$?.subscribe(() => { @@ -182,12 +189,16 @@ export const ReactExpressionRenderer = ({ // Re-fetch data automatically when the inputs change useShallowCompareEffect( () => { - if (expressionLoaderRef.current) { + // only update the loader if the debounce period is over + if (expressionLoaderRef.current && !waitingForDebounceToComplete) { expressionLoaderRef.current.update(activeExpression, expressionLoaderOptions); } }, - // when expression is changed by reference and when any other loaderOption is changed by reference - [{ activeExpression, ...expressionLoaderOptions }] + // when debounced, wait for debounce status to change to update loader. + // Otherwise, update when expression is changed by reference and when any other loaderOption is changed by reference + debounce === undefined + ? [{ activeExpression, ...expressionLoaderOptions }] + : [{ waitingForDebounceToComplete }] ); /* eslint-enable react-hooks/exhaustive-deps */ @@ -200,10 +211,9 @@ export const ReactExpressionRenderer = ({ } }, [state.error]); - const classes = classNames('expExpressionRenderer', { + const classes = classNames('expExpressionRenderer', className, { 'expExpressionRenderer-isEmpty': state.isEmpty, 'expExpressionRenderer-hasError': !!state.error, - className, }); const expressionStyles: React.CSSProperties = {}; diff --git a/src/plugins/expressions/public/render.ts b/src/plugins/expressions/public/render.ts index 717776a2861b..e3091b908dec 100644 --- a/src/plugins/expressions/public/render.ts +++ b/src/plugins/expressions/public/render.ts @@ -31,6 +31,7 @@ export type IExpressionRendererExtraHandlers = Record; export interface ExpressionRenderHandlerParams { onRenderError?: RenderErrorHandlerFnType; renderMode?: RenderMode; + syncColors?: boolean; hasCompatibleActions?: (event: ExpressionRendererEvent) => Promise; } @@ -63,6 +64,7 @@ export class ExpressionRenderHandler { { onRenderError, renderMode, + syncColors, hasCompatibleActions = async () => false, }: ExpressionRenderHandlerParams = {} ) { @@ -101,6 +103,9 @@ export class ExpressionRenderHandler { getRenderMode: () => { return renderMode || 'display'; }, + isSyncColorsEnabled: () => { + return syncColors || false; + }, hasCompatibleActions, }; } diff --git a/src/plugins/expressions/public/types/index.ts b/src/plugins/expressions/public/types/index.ts index f37107abbb71..d709d8ca96bb 100644 --- a/src/plugins/expressions/public/types/index.ts +++ b/src/plugins/expressions/public/types/index.ts @@ -57,6 +57,7 @@ export interface IExpressionLoaderParams { onRenderError?: RenderErrorHandlerFnType; searchSessionId?: string; renderMode?: RenderMode; + syncColors?: boolean; hasCompatibleActions?: ExpressionRenderHandlerParams['hasCompatibleActions']; } diff --git a/src/plugins/expressions/server/server.api.md b/src/plugins/expressions/server/server.api.md index 7c1ab11f7502..71199560ee0c 100644 --- a/src/plugins/expressions/server/server.api.md +++ b/src/plugins/expressions/server/server.api.md @@ -10,7 +10,6 @@ import { Ensure } from '@kbn/utility-types'; import { EventEmitter } from 'events'; import { KibanaRequest } from 'src/core/server'; import { Observable } from 'rxjs'; -import { PersistedState } from 'src/plugins/visualizations/public'; import { Plugin as Plugin_2 } from 'src/core/server'; import { PluginInitializerContext } from 'src/core/server'; import { UnwrapPromiseOrReturn } from '@kbn/utility-types'; @@ -738,11 +737,12 @@ export interface IInterpreterRenderHandlers { // (undocumented) hasCompatibleActions?: (event: any) => Promise; // (undocumented) + isSyncColorsEnabled: () => boolean; + // (undocumented) onDestroy: (fn: () => void) => void; // (undocumented) reload: () => void; - // (undocumented) - uiState?: PersistedState; + uiState?: unknown; // (undocumented) update: (params: any) => void; } diff --git a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts index 60d05890028d..5cb837f816ff 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts @@ -34,7 +34,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[eCommerce] Sales by Category', }), visState: - '{"title":"[eCommerce] Sales by Category","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"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},"aggs":[{"id":"1","enabled":true,"type":"sum","schema":"metric","params":{"field":"total_quantity"}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"order_date","interval":"auto","time_zone":"America/New_York","drop_partials":false,"customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"category.keyword","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}', + '{"title":"[eCommerce] Sales by Category","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Sum of total_quantity"}}],"seriesParams":[{"show":"true","type":"area","mode":"stacked","data":{"label":"Sum of total_quantity","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"top","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"sum","schema":"metric","params":{"field":"total_quantity"}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"order_date","interval":"auto","drop_partials":false,"min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"category.keyword","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}', uiStateJSON: '{}', description: '', version: 1, diff --git a/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts index e65b6ad40651..6b06a526a123 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts @@ -56,7 +56,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[Flights] Flight Count and Average Ticket Price', }), visState: - '{"title":"[Flights] Flight Count and Average Ticket Price","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Average Ticket Price"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Flight Count"}}],"seriesParams":[{"show":true,"mode":"stacked","type":"area","drawLinesBetweenPoints":true,"showCircles":false,"interpolate":"linear","lineWidth":2,"data":{"id":"5","label":"Flight Count"},"valueAxis":"ValueAxis-2"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"4","label":"Average Ticket Price"},"valueAxis":"ValueAxis-1","lineWidth":2}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":13},"aggs":[{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"5","enabled":true,"type":"count","schema":"metric","params":{"customLabel":"Flight Count"}},{"id":"4","enabled":true,"type":"avg","schema":"metric","params":{"field":"AvgTicketPrice","customLabel":"Average Ticket Price"}},{"id":"2","enabled":true,"type":"avg","schema":"radius","params":{"field":"AvgTicketPrice"}}]}', + '{"title":"[Flights] Flight Count and Average Ticket Price","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Average Ticket Price"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Flight Count"}}],"seriesParams":[{"show":true,"mode":"stacked","type":"area","drawLinesBetweenPoints":true,"showCircles":false,"interpolate":"linear","lineWidth":2,"data":{"id":"5","label":"Flight Count"},"valueAxis":"ValueAxis-2"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"4","label":"Average Ticket Price"},"valueAxis":"ValueAxis-1","lineWidth":2}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":13,"detailedTooltip":true},"aggs":[{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"5","enabled":true,"type":"count","schema":"metric","params":{"customLabel":"Flight Count"}},{"id":"4","enabled":true,"type":"avg","schema":"metric","params":{"field":"AvgTicketPrice","customLabel":"Average Ticket Price"}},{"id":"2","enabled":true,"type":"avg","schema":"radius","params":{"field":"AvgTicketPrice"}}]}', uiStateJSON: '{"vis":{"legendOpen":true,"colors":{"Average Ticket Price":"#629E51","Flight Count":"#AEA2E0"}}}', description: '', @@ -133,7 +133,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[Flights] Delay Type', }), visState: - '{"title":"[Flights] Delay Type","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"cardinal","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"FlightDelayType","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}', + '{"title":"[Flights] Delay Type","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"cardinal","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"FlightDelayType","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}', uiStateJSON: '{}', description: '', version: 1, @@ -176,7 +176,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[Flights] Delay Buckets', }), visState: - '{"title":"[Flights] Delay Buckets","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"histogram","schema":"segment","params":{"field":"FlightDelayMin","interval":30,"extended_bounds":{},"customLabel":"Flight Delay Minutes"}}]}', + '{"title":"[Flights] Delay Buckets","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"histogram","schema":"segment","params":{"field":"FlightDelayMin","interval":30,"extended_bounds":{},"customLabel":"Flight Delay Minutes"}}]}', uiStateJSON: '{"vis":{"legendOpen":false}}', description: '', version: 1, @@ -198,7 +198,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[Flights] Flight Delays', }), visState: - '{"title":"[Flights] Flight Delays","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"FlightDelay","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Delays"}}]}', + '{"title":"[Flights] Flight Delays","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"FlightDelay","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Delays"}}]}', uiStateJSON: '{}', description: '', version: 1, @@ -220,7 +220,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[Flights] Flight Cancellations', }), visState: - '{"title":"[Flights] Flight Cancellations","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"Cancelled","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Cancellations"}}]}', + '{"title":"[Flights] Flight Cancellations","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"Cancelled","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Cancellations"}}]}', uiStateJSON: '{}', description: '', version: 1, diff --git a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts index 068ba66c4b0d..7b891107cdfb 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts @@ -33,7 +33,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[Logs] Unique Visitors vs. Average Bytes', }), visState: - '{"title":"[Logs] Unique Visitors vs. Average Bytes","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Avg. Bytes"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Unique Visitors"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Avg. Bytes","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"2","label":"Unique Visitors"},"valueAxis":"ValueAxis-2"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":17},"aggs":[{"id":"1","enabled":true,"type":"avg","schema":"metric","params":{"field":"bytes","customLabel":"Avg. Bytes"}},{"id":"2","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"clientip","customLabel":"Unique Visitors"}},{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","time_zone":"America/Los_Angeles","customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"4","enabled":true,"type":"count","schema":"radius","params":{}}]}', + '{"title":"[Logs] Unique Visitors vs. Average Bytes","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Avg. Bytes"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Unique Visitors"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Avg. Bytes","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"2","label":"Unique Visitors"},"valueAxis":"ValueAxis-2"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":17,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"avg","schema":"metric","params":{"field":"bytes","customLabel":"Avg. Bytes"}},{"id":"2","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"clientip","customLabel":"Unique Visitors"}},{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"4","enabled":true,"type":"count","schema":"radius","params":{}}]}', uiStateJSON: '{"vis":{"colors":{"Avg. Bytes":"#70DBED","Unique Visitors":"#0A437C"}}}', description: '', version: 1, diff --git a/src/plugins/home/server/services/sample_data/usage/collector_fetch.test.ts b/src/plugins/home/server/services/sample_data/usage/collector_fetch.test.ts index 54fed3db1de4..58bb037f8d61 100644 --- a/src/plugins/home/server/services/sample_data/usage/collector_fetch.test.ts +++ b/src/plugins/home/server/services/sample_data/usage/collector_fetch.test.ts @@ -23,7 +23,7 @@ import { fetchProvider } from './collector_fetch'; const getMockFetchClients = (hits?: unknown[]) => { const fetchParamsMock = createCollectorFetchContextMock(); - fetchParamsMock.callCluster.mockResolvedValue({ hits: { hits } }); + fetchParamsMock.esClient.search = jest.fn().mockResolvedValue({ body: { hits: { hits } } }); return fetchParamsMock; }; diff --git a/src/plugins/home/server/services/sample_data/usage/collector_fetch.ts b/src/plugins/home/server/services/sample_data/usage/collector_fetch.ts index 7df9b14d2efb..ef958873d966 100644 --- a/src/plugins/home/server/services/sample_data/usage/collector_fetch.ts +++ b/src/plugins/home/server/services/sample_data/usage/collector_fetch.ts @@ -19,6 +19,7 @@ import { get } from 'lodash'; import moment from 'moment'; +import { SearchResponse } from 'src/core/server'; import { CollectorFetchContext } from '../../../../../usage_collection/server'; interface SearchHit { @@ -41,17 +42,23 @@ export interface TelemetryResponse { last_uninstall_set: string | null; } +type ESResponse = SearchResponse; + export function fetchProvider(index: string) { - return async ({ callCluster }: CollectorFetchContext) => { - const response = await callCluster('search', { - index, - body: { - query: { term: { type: { value: 'sample-data-telemetry' } } }, - _source: { includes: ['sample-data-telemetry', 'type', 'updated_at'] }, + return async ({ esClient }: CollectorFetchContext) => { + const { body: response } = await esClient.search( + { + index, + body: { + query: { term: { type: { value: 'sample-data-telemetry' } } }, + _source: { includes: ['sample-data-telemetry', 'type', 'updated_at'] }, + }, + filter_path: 'hits.hits._id,hits.hits._source', }, - filter_path: 'hits.hits._id,hits.hits._source', - ignore: [404], - }); + { + ignore: [404], + } + ); const getLast = ( dataSet: string, diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.test.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.test.ts index a7681e176642..64f1088dc339 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.test.ts @@ -16,14 +16,25 @@ * specific language governing permissions and limitations * under the License. */ - +import { elasticsearchServiceMock } from '../../../../../../src/core/server/mocks'; import { getSavedObjectsCounts } from './get_saved_object_counts'; +export function mockGetSavedObjectsCounts(params: any) { + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + esClient.search.mockResolvedValue( + // @ts-ignore we only care about the response body + { + body: { ...params }, + } + ); + return esClient; +} + describe('getSavedObjectsCounts', () => { test('Get all the saved objects equal to 0 because no results were found', async () => { - const callCluster = jest.fn(() => ({})); + const esClient = mockGetSavedObjectsCounts({}); - const results = await getSavedObjectsCounts(callCluster as any, '.kibana'); + const results = await getSavedObjectsCounts(esClient, '.kibana'); expect(results).toStrictEqual({ dashboard: { total: 0 }, visualization: { total: 0 }, @@ -35,7 +46,7 @@ describe('getSavedObjectsCounts', () => { }); test('Merge the zeros with the results', async () => { - const callCluster = jest.fn(() => ({ + const esClient = mockGetSavedObjectsCounts({ aggregations: { types: { buckets: [ @@ -46,9 +57,9 @@ describe('getSavedObjectsCounts', () => { ], }, }, - })); + }); - const results = await getSavedObjectsCounts(callCluster as any, '.kibana'); + const results = await getSavedObjectsCounts(esClient, '.kibana'); expect(results).toStrictEqual({ dashboard: { total: 1 }, visualization: { total: 0 }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts index e88d90fe5b24..65cc3643a88c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts @@ -27,7 +27,7 @@ */ import { snakeCase } from 'lodash'; -import { LegacyAPICaller } from 'kibana/server'; +import { ElasticsearchClient } from 'src/core/server'; const TYPES = [ 'dashboard', @@ -48,7 +48,7 @@ export interface KibanaSavedObjectCounts { } export async function getSavedObjectsCounts( - callCluster: LegacyAPICaller, + esClient: ElasticsearchClient, kibanaIndex: string // Typically '.kibana'. We might need a way to obtain it from the SavedObjects client (or the SavedObjects client to provide a way to run aggregations?) ): Promise { const savedObjectCountSearchParams = { @@ -67,9 +67,9 @@ export async function getSavedObjectsCounts( }, }, }; - const resp = await callCluster('search', savedObjectCountSearchParams); + const { body } = await esClient.search(savedObjectCountSearchParams); const buckets: Array<{ key: string; doc_count: number }> = - resp.aggregations?.types?.buckets || []; + body.aggregations?.types?.buckets || []; // Initialise the object with all zeros for all the types const allZeros: KibanaSavedObjectCounts = TYPES.reduce( diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/index.test.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/index.test.ts index 83cac1d456a3..dee9ca4d32c5 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/kibana/index.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/index.test.ts @@ -20,12 +20,13 @@ import { loggingSystemMock, pluginInitializerContextConfigMock, + elasticsearchServiceMock, } from '../../../../../core/server/mocks'; import { Collector, + createCollectorFetchContextMock, createUsageCollectionSetupMock, } from '../../../../usage_collection/server/usage_collection.mock'; -import { createCollectorFetchContextMock } from '../../../../usage_collection/server/mocks'; import { registerKibanaUsageCollector } from './'; const logger = loggingSystemMock.createLogger(); @@ -43,7 +44,9 @@ describe('telemetry_kibana', () => { const getMockFetchClients = (hits?: unknown[]) => { const fetchParamsMock = createCollectorFetchContextMock(); - fetchParamsMock.callCluster.mockResolvedValue({ hits: { hits } }); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + esClient.search.mockResolvedValue({ body: { hits: { hits } } } as any); + fetchParamsMock.esClient = esClient; return fetchParamsMock; }; diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts index 6c2e0a2c926a..5dd39d172e1c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts @@ -43,13 +43,13 @@ export function getKibanaUsageCollector( graph_workspace: { total: { type: 'long' } }, timelion_sheet: { total: { type: 'long' } }, }, - async fetch({ callCluster }) { + async fetch({ esClient }) { const { kibana: { index }, } = await legacyConfig$.pipe(take(1)).toPromise(); return { index, - ...(await getSavedObjectsCounts(callCluster, index)), + ...(await getSavedObjectsCounts(esClient, index)), }; }, }); diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts index bf03c649fa6b..81026927380e 100644 --- a/src/plugins/management/public/plugin.ts +++ b/src/plugins/management/public/plugin.ts @@ -58,11 +58,12 @@ export class ManagementPlugin implements Plugin ({ diff --git a/src/plugins/telemetry/common/constants.ts b/src/plugins/telemetry/common/constants.ts index fc77332c18fc..2fa8b32f6829 100644 --- a/src/plugins/telemetry/common/constants.ts +++ b/src/plugins/telemetry/common/constants.ts @@ -49,7 +49,7 @@ export const LOCALSTORAGE_KEY = 'telemetry.data'; /** * Link to Advanced Settings. */ -export const PATH_TO_ADVANCED_SETTINGS = 'management/kibana/settings'; +export const PATH_TO_ADVANCED_SETTINGS = '/app/management/kibana/settings'; /** * Link to the Elastic Telemetry privacy statement. diff --git a/src/plugins/telemetry/public/components/__snapshots__/opted_in_notice_banner.test.tsx.snap b/src/plugins/telemetry/public/components/__snapshots__/opted_in_notice_banner.test.tsx.snap index 62998da73d6f..897e3b2761c7 100644 --- a/src/plugins/telemetry/public/components/__snapshots__/opted_in_notice_banner.test.tsx.snap +++ b/src/plugins/telemetry/public/components/__snapshots__/opted_in_notice_banner.test.tsx.snap @@ -10,7 +10,7 @@ exports[`OptInDetailsComponent renders as expected 1`] = ` values={ Object { "disableLink": { it('renders as expected', () => { - expect(shallowWithIntl( {}} />)).toMatchSnapshot(); + expect( + shallowWithIntl( {}} http={mockHttp} />) + ).toMatchSnapshot(); }); it('fires the "onSeenBanner" prop when a link is clicked', () => { const onLinkClick = jest.fn(); - const component = shallowWithIntl(); + const component = shallowWithIntl( + + ); const button = component.findWhere((n) => n.type() === EuiButton); diff --git a/src/plugins/telemetry/public/components/opted_in_notice_banner.tsx b/src/plugins/telemetry/public/components/opted_in_notice_banner.tsx index 090893964c88..46ae17171203 100644 --- a/src/plugins/telemetry/public/components/opted_in_notice_banner.tsx +++ b/src/plugins/telemetry/public/components/opted_in_notice_banner.tsx @@ -24,14 +24,18 @@ import { EuiButton, EuiLink, EuiCallOut, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { PATH_TO_ADVANCED_SETTINGS, PRIVACY_STATEMENT_URL } from '../../common/constants'; +import { HttpSetup } from '../../../../core/public'; interface Props { + http: HttpSetup; onSeenBanner: () => any; } export class OptedInNoticeBanner extends React.PureComponent { render() { - const { onSeenBanner } = this.props; + const { onSeenBanner, http } = this.props; + const basePath = http.basePath.get(); + const bannerTitle = i18n.translate('telemetry.telemetryOptedInNoticeTitle', { defaultMessage: 'Help us improve the Elastic Stack', }); @@ -56,7 +60,7 @@ export class OptedInNoticeBanner extends React.PureComponent { ), disableLink: ( - + { it('adds a banner to banners with priority of 10000', () => { const bannerID = 'brucer-wayne'; const overlays = overlayServiceMock.createStartContract(); + const mockHttp = httpServiceMock.createStartContract(); overlays.banners.add.mockReturnValue(bannerID); const returnedBannerId = renderOptedInNoticeBanner({ + http: mockHttp, onSeen: jest.fn(), overlays, }); diff --git a/src/plugins/telemetry/public/services/telemetry_notifications/render_opted_in_notice_banner.tsx b/src/plugins/telemetry/public/services/telemetry_notifications/render_opted_in_notice_banner.tsx index e63e46af6e8c..e1feea4b6cbe 100644 --- a/src/plugins/telemetry/public/services/telemetry_notifications/render_opted_in_notice_banner.tsx +++ b/src/plugins/telemetry/public/services/telemetry_notifications/render_opted_in_notice_banner.tsx @@ -23,11 +23,12 @@ import { OptedInNoticeBanner } from '../../components/opted_in_notice_banner'; import { toMountPoint } from '../../../../kibana_react/public'; interface RenderBannerConfig { + http: CoreStart['http']; overlays: CoreStart['overlays']; onSeen: () => void; } -export function renderOptedInNoticeBanner({ onSeen, overlays }: RenderBannerConfig) { - const mount = toMountPoint(); +export function renderOptedInNoticeBanner({ onSeen, overlays, http }: RenderBannerConfig) { + const mount = toMountPoint(); const bannerId = overlays.banners.add(mount, 10000); return bannerId; diff --git a/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts b/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts index fc44a4db7cf5..6ebbfcfb9133 100644 --- a/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts +++ b/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts @@ -23,18 +23,21 @@ import { renderOptInBanner } from './render_opt_in_banner'; import { TelemetryService } from '../telemetry_service'; interface TelemetryNotificationsConstructor { + http: CoreStart['http']; overlays: CoreStart['overlays']; telemetryService: TelemetryService; } export class TelemetryNotifications { + private readonly http: CoreStart['http']; private readonly overlays: CoreStart['overlays']; private readonly telemetryService: TelemetryService; private optedInNoticeBannerId?: string; private optInBannerId?: string; - constructor({ overlays, telemetryService }: TelemetryNotificationsConstructor) { + constructor({ http, overlays, telemetryService }: TelemetryNotificationsConstructor) { this.telemetryService = telemetryService; + this.http = http; this.overlays = overlays; } @@ -46,6 +49,7 @@ export class TelemetryNotifications { public renderOptedInNoticeBanner = (): void => { const bannerId = renderOptedInNoticeBanner({ + http: this.http, onSeen: this.setOptedInNoticeSeen, overlays: this.overlays, }); diff --git a/src/plugins/tile_map/public/components/tile_map_options.tsx b/src/plugins/tile_map/public/components/tile_map_options.tsx index 1a7b11ccf6e2..a6c0bb8a50dd 100644 --- a/src/plugins/tile_map/public/components/tile_map_options.tsx +++ b/src/plugins/tile_map/public/components/tile_map_options.tsx @@ -21,8 +21,13 @@ import React, { useEffect } from 'react'; import { EuiPanel, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { BasicOptions, RangeOption, SelectOption, SwitchOption } from '../../../charts/public'; +import { + VisOptionsProps, + BasicOptions, + SelectOption, + SwitchOption, + RangeOption, +} from '../../../vis_default_editor/public'; import { WmsOptions, TileMapVisParams, MapTypes } from '../../../maps_legacy/public'; export type TileMapOptionsProps = VisOptionsProps; diff --git a/src/plugins/ui_actions/public/index.ts b/src/plugins/ui_actions/public/index.ts index d223c0abcccb..7890e4bab44a 100644 --- a/src/plugins/ui_actions/public/index.ts +++ b/src/plugins/ui_actions/public/index.ts @@ -40,12 +40,6 @@ export { export { Trigger, TriggerContext, - SELECT_RANGE_TRIGGER, - selectRangeTrigger, - VALUE_CLICK_TRIGGER, - valueClickTrigger, - APPLY_FILTER_TRIGGER, - applyFilterTrigger, VISUALIZE_FIELD_TRIGGER, visualizeFieldTrigger, VISUALIZE_GEO_FIELD_TRIGGER, diff --git a/src/plugins/ui_actions/public/plugin.ts b/src/plugins/ui_actions/public/plugin.ts index fdb75e9a426e..84a7ae45fc7b 100644 --- a/src/plugins/ui_actions/public/plugin.ts +++ b/src/plugins/ui_actions/public/plugin.ts @@ -20,14 +20,7 @@ import { CoreStart, CoreSetup, Plugin, PluginInitializerContext } from 'src/core/public'; import { PublicMethodsOf } from '@kbn/utility-types'; import { UiActionsService } from './service'; -import { - selectRangeTrigger, - valueClickTrigger, - rowClickTrigger, - applyFilterTrigger, - visualizeFieldTrigger, - visualizeGeoFieldTrigger, -} from './triggers'; +import { rowClickTrigger, visualizeFieldTrigger, visualizeGeoFieldTrigger } from './triggers'; export type UiActionsSetup = Pick< UiActionsService, @@ -47,10 +40,7 @@ export class UiActionsPlugin implements Plugin { constructor(initializerContext: PluginInitializerContext) {} public setup(core: CoreSetup): UiActionsSetup { - this.service.registerTrigger(selectRangeTrigger); - this.service.registerTrigger(valueClickTrigger); this.service.registerTrigger(rowClickTrigger); - this.service.registerTrigger(applyFilterTrigger); this.service.registerTrigger(visualizeFieldTrigger); this.service.registerTrigger(visualizeGeoFieldTrigger); return this.service; diff --git a/src/plugins/ui_actions/public/public.api.md b/src/plugins/ui_actions/public/public.api.md index 2384dfab13c8..808cb1f3fbca 100644 --- a/src/plugins/ui_actions/public/public.api.md +++ b/src/plugins/ui_actions/public/public.api.md @@ -8,14 +8,11 @@ import { CoreSetup } from 'src/core/public'; import { CoreStart } from 'src/core/public'; import { EnvironmentMode } from '@kbn/config'; import { EuiContextMenuPanelDescriptor } from '@elastic/eui'; -import { EventEmitter } from 'events'; -import { Observable } from 'rxjs'; import { PackageInfo } from '@kbn/config'; import { Plugin } from 'src/core/public'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public'; import { PublicMethodsOf } from '@kbn/utility-types'; import React from 'react'; -import * as Rx from 'rxjs'; import { UiComponent } from 'src/plugins/kibana_utils/public'; // Warning: (ae-forgotten-export) The symbol "BaseContext" needs to be exported by the entry point index.d.ts @@ -95,16 +92,6 @@ export interface ActionExecutionMeta { // @public (undocumented) export type ActionType = keyof ActionContextMapping; -// Warning: (ae-missing-release-tag) "APPLY_FILTER_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const APPLY_FILTER_TRIGGER = "FILTER_TRIGGER"; - -// Warning: (ae-missing-release-tag) "applyFilterTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const applyFilterTrigger: Trigger<'FILTER_TRIGGER'>; - // Warning: (ae-forgotten-export) The symbol "BuildContextMenuParams" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "buildContextMenuForActions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -148,10 +135,8 @@ export interface RowClickContext { table: Datatable; columns?: string[]; }; - // Warning: (ae-forgotten-export) The symbol "IEmbeddable" needs to be exported by the entry point index.d.ts - // // (undocumented) - embeddable?: IEmbeddable; + embeddable?: unknown; } // Warning: (ae-missing-release-tag) "rowClickTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -159,16 +144,6 @@ export interface RowClickContext { // @public (undocumented) export const rowClickTrigger: Trigger<'ROW_CLICK_TRIGGER'>; -// Warning: (ae-missing-release-tag) "SELECT_RANGE_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const SELECT_RANGE_TRIGGER = "SELECT_RANGE_TRIGGER"; - -// Warning: (ae-missing-release-tag) "selectRangeTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'>; - // Warning: (ae-missing-release-tag) "Trigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public @@ -192,20 +167,8 @@ export interface TriggerContextMapping { // // (undocumented) [DEFAULT_TRIGGER]: TriggerContext_2; - // Warning: (ae-forgotten-export) The symbol "ApplyGlobalFilterActionContext" needs to be exported by the entry point index.d.ts - // - // (undocumented) - [APPLY_FILTER_TRIGGER]: ApplyGlobalFilterActionContext; // (undocumented) [ROW_CLICK_TRIGGER]: RowClickContext; - // Warning: (ae-forgotten-export) The symbol "RangeSelectContext" needs to be exported by the entry point index.d.ts - // - // (undocumented) - [SELECT_RANGE_TRIGGER]: RangeSelectContext; - // Warning: (ae-forgotten-export) The symbol "ValueClickContext" needs to be exported by the entry point index.d.ts - // - // (undocumented) - [VALUE_CLICK_TRIGGER]: ValueClickContext; // (undocumented) [VISUALIZE_FIELD_TRIGGER]: VisualizeFieldContext; // (undocumented) @@ -262,35 +225,35 @@ export class UiActionsService { // // (undocumented) protected readonly actions: ActionRegistry; - readonly addTriggerAction: (triggerId: T, action: UiActionsActionDefinition | Action) => void; + readonly addTriggerAction: (triggerId: T, action: UiActionsActionDefinition | Action) => void; // (undocumented) - readonly attachAction: (triggerId: T, actionId: string) => void; + readonly attachAction: (triggerId: T, actionId: string) => void; readonly clear: () => void; // (undocumented) readonly detachAction: (triggerId: TriggerId, actionId: string) => void; // @deprecated (undocumented) - readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise; + readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise; // Warning: (ae-forgotten-export) The symbol "UiActionsExecutionService" needs to be exported by the entry point index.d.ts // // (undocumented) readonly executionService: UiActionsExecutionService; readonly fork: () => UiActionsService; // (undocumented) - readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">; + readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">; // Warning: (ae-forgotten-export) The symbol "TriggerContract" needs to be exported by the entry point index.d.ts // // (undocumented) - readonly getTrigger: (triggerId: T) => TriggerContract; + readonly getTrigger: (triggerId: T) => TriggerContract; // (undocumented) - readonly getTriggerActions: (triggerId: T) => Action[]; + readonly getTriggerActions: (triggerId: T) => Action[]; // (undocumented) - readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; + readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; // (undocumented) readonly hasAction: (actionId: string) => boolean; // Warning: (ae-forgotten-export) The symbol "ActionContext" needs to be exported by the entry point index.d.ts // // (undocumented) - readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">; + readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">; // (undocumented) readonly registerTrigger: (trigger: Trigger) => void; // Warning: (ae-forgotten-export) The symbol "TriggerRegistry" needs to be exported by the entry point index.d.ts @@ -326,16 +289,6 @@ export type UiActionsSetup = Pick; -// Warning: (ae-missing-release-tag) "VALUE_CLICK_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const VALUE_CLICK_TRIGGER = "VALUE_CLICK_TRIGGER"; - -// Warning: (ae-missing-release-tag) "valueClickTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'>; - // Warning: (ae-missing-release-tag) "VISUALIZE_FIELD_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -371,7 +324,7 @@ export const visualizeGeoFieldTrigger: Trigger<'VISUALIZE_GEO_FIELD_TRIGGER'>; // Warnings were encountered during analysis: // -// src/plugins/ui_actions/public/triggers/row_click_trigger.ts:45:5 - (ae-forgotten-export) The symbol "Datatable" needs to be exported by the entry point index.d.ts +// src/plugins/ui_actions/public/triggers/row_click_trigger.ts:46:5 - (ae-forgotten-export) The symbol "Datatable" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/src/plugins/ui_actions/public/triggers/index.ts b/src/plugins/ui_actions/public/triggers/index.ts index ecbf4d1f7b98..6bba87e85eb9 100644 --- a/src/plugins/ui_actions/public/triggers/index.ts +++ b/src/plugins/ui_actions/public/triggers/index.ts @@ -20,10 +20,7 @@ export * from './trigger'; export * from './trigger_contract'; export * from './trigger_internal'; -export * from './select_range_trigger'; -export * from './value_click_trigger'; export * from './row_click_trigger'; -export * from './apply_filter_trigger'; export * from './visualize_field_trigger'; export * from './visualize_geo_field_trigger'; export * from './default_trigger'; diff --git a/src/plugins/ui_actions/public/triggers/row_click_trigger.ts b/src/plugins/ui_actions/public/triggers/row_click_trigger.ts index 87bca03f8c3b..0fc261b3e1fb 100644 --- a/src/plugins/ui_actions/public/triggers/row_click_trigger.ts +++ b/src/plugins/ui_actions/public/triggers/row_click_trigger.ts @@ -18,7 +18,6 @@ */ import { i18n } from '@kbn/i18n'; -import { IEmbeddable } from '../../../embeddable/public'; import { Trigger } from '.'; import { Datatable } from '../../../expressions'; @@ -35,7 +34,9 @@ export const rowClickTrigger: Trigger<'ROW_CLICK_TRIGGER'> = { }; export interface RowClickContext { - embeddable?: IEmbeddable; + // Need to make this unknown to prevent circular dependencies. + // Apps using this property will need to cast to `IEmbeddable`. + embeddable?: unknown; data: { /** * Row index, starting from 0, where user clicked. diff --git a/src/plugins/ui_actions/public/triggers/trigger.ts b/src/plugins/ui_actions/public/triggers/trigger.ts index 2c019b09881d..1b1231c132dd 100644 --- a/src/plugins/ui_actions/public/triggers/trigger.ts +++ b/src/plugins/ui_actions/public/triggers/trigger.ts @@ -32,8 +32,7 @@ import { TriggerContextMapping, TriggerId } from '../types'; */ export interface Trigger { /** - * Unique name of the trigger as identified in `ui_actions` plugin trigger - * registry, such as "SELECT_RANGE_TRIGGER" or "VALUE_CLICK_TRIGGER". + * Unique name of the trigger as identified in `ui_actions` plugin trigger registry. */ id: ID; diff --git a/src/plugins/ui_actions/public/triggers/trigger_contract.ts b/src/plugins/ui_actions/public/triggers/trigger_contract.ts index 04a75cb3a53d..7e7fba0ba80d 100644 --- a/src/plugins/ui_actions/public/triggers/trigger_contract.ts +++ b/src/plugins/ui_actions/public/triggers/trigger_contract.ts @@ -25,8 +25,7 @@ import { TriggerId, TriggerContextMapping } from '../types'; */ export class TriggerContract { /** - * Unique name of the trigger as identified in `ui_actions` plugin trigger - * registry, such as "SELECT_RANGE_TRIGGER" or "VALUE_CLICK_TRIGGER". + * Unique name of the trigger as identified in `ui_actions` plugin trigger registry. */ public readonly id: T; diff --git a/src/plugins/ui_actions/public/types.ts b/src/plugins/ui_actions/public/types.ts index 0266a755be92..62fac245514c 100644 --- a/src/plugins/ui_actions/public/types.ts +++ b/src/plugins/ui_actions/public/types.ts @@ -20,17 +20,12 @@ import { ActionInternal } from './actions/action_internal'; import { TriggerInternal } from './triggers/trigger_internal'; import { - SELECT_RANGE_TRIGGER, - VALUE_CLICK_TRIGGER, ROW_CLICK_TRIGGER, - APPLY_FILTER_TRIGGER, VISUALIZE_FIELD_TRIGGER, VISUALIZE_GEO_FIELD_TRIGGER, DEFAULT_TRIGGER, RowClickContext, } from './triggers'; -import type { RangeSelectContext, ValueClickContext } from '../../embeddable/public'; -import type { ApplyGlobalFilterActionContext } from '../../data/public'; export type TriggerRegistry = Map>; export type ActionRegistry = Map; @@ -49,10 +44,7 @@ export type TriggerContext = BaseContext; export interface TriggerContextMapping { [DEFAULT_TRIGGER]: TriggerContext; - [SELECT_RANGE_TRIGGER]: RangeSelectContext; - [VALUE_CLICK_TRIGGER]: ValueClickContext; [ROW_CLICK_TRIGGER]: RowClickContext; - [APPLY_FILTER_TRIGGER]: ApplyGlobalFilterActionContext; [VISUALIZE_FIELD_TRIGGER]: VisualizeFieldContext; [VISUALIZE_GEO_FIELD_TRIGGER]: VisualizeFieldContext; } diff --git a/src/plugins/vis_default_editor/kibana.json b/src/plugins/vis_default_editor/kibana.json index 35ad0a3a8be9..9664b14821c0 100644 --- a/src/plugins/vis_default_editor/kibana.json +++ b/src/plugins/vis_default_editor/kibana.json @@ -2,5 +2,6 @@ "id": "visDefaultEditor", "version": "kibana", "ui": true, + "optionalPlugins": ["visualize"], "requiredBundles": ["kibanaUtils", "kibanaReact", "data"] } diff --git a/src/plugins/vis_default_editor/public/components/agg_add.tsx b/src/plugins/vis_default_editor/public/components/agg_add.tsx index e78f2fcc4453..2da7b33139a8 100644 --- a/src/plugins/vis_default_editor/public/components/agg_add.tsx +++ b/src/plugins/vis_default_editor/public/components/agg_add.tsx @@ -76,10 +76,17 @@ function DefaultEditorAggAdd({ ); - const isSchemaDisabled = (schema: Schema): boolean => { + const isMaxedCount = (schema: Schema): boolean => { const count = group.filter((agg) => agg.schema === schema.name).length; return count >= schema.max; }; + const isSchemaDisabled = (schema: Schema, maxedCount: boolean): boolean => { + return schema.disabled ?? maxedCount; + }; + const maxTooltipText = i18n.translate('visDefaultEditor.aggAdd.maxBuckets', { + defaultMessage: 'Max {groupNameLabel} count reached', + values: { groupNameLabel }, + }); return ( @@ -109,16 +116,21 @@ function DefaultEditorAggAdd({ )} ( - onSelectSchema(schema)} - > - {schema.title} - - ))} + items={schemas.map((schema) => { + const maxedCount = isMaxedCount(schema); + + return ( + onSelectSchema(schema)} + toolTipContent={schema.tooltip ?? (maxedCount ? maxTooltipText : undefined)} + > + {schema.title} + + ); + })} /> diff --git a/src/plugins/charts/public/static/components/basic_options.tsx b/src/plugins/vis_default_editor/public/components/options/basic_options.tsx similarity index 86% rename from src/plugins/charts/public/static/components/basic_options.tsx rename to src/plugins/vis_default_editor/public/components/options/basic_options.tsx index cac4c8d70d79..f67a9997cb5e 100644 --- a/src/plugins/charts/public/static/components/basic_options.tsx +++ b/src/plugins/vis_default_editor/public/components/options/basic_options.tsx @@ -18,9 +18,10 @@ */ import React from 'react'; + import { i18n } from '@kbn/i18n'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisOptionsProps } from '../../vis_options_props'; import { SwitchOption } from './switch'; import { SelectOption } from './select'; @@ -37,7 +38,7 @@ function BasicOptions({ return ( <> ({ setValue={setValue} /> void; @@ -71,7 +71,7 @@ function ColorRanges({ return ( ( paramName: T, @@ -67,7 +66,7 @@ function ColorSchemaOptions({ }} > @@ -80,11 +79,11 @@ function ColorSchemaOptions({ disabled={disabled} helpText={ showHelpText && - i18n.translate('charts.controls.colorSchema.howToChangeColorsDescription', { + i18n.translate('visDefaultEditor.options.colorSchema.howToChangeColorsDescription', { defaultMessage: 'Individual colors can be changed in the legend.', }) } - label={i18n.translate('charts.controls.colorSchema.colorSchemaLabel', { + label={i18n.translate('visDefaultEditor.options.colorSchema.colorSchemaLabel', { defaultMessage: 'Color schema', })} labelAppend={isCustomColors && resetColorsButton} @@ -96,7 +95,7 @@ function ColorSchemaOptions({ ({ const [stateValue, setStateValue] = useState(value); const [isValidState, setIsValidState] = useState(true); - const error = i18n.translate('charts.controls.rangeErrorMessage', { + const error = i18n.translate('visDefaultEditor.options.rangeErrorMessage', { defaultMessage: 'Values must be on or between {min} and {max}', values: { min, max }, }); diff --git a/src/plugins/charts/public/static/components/required_number_input.tsx b/src/plugins/vis_default_editor/public/components/options/required_number_input.tsx similarity index 100% rename from src/plugins/charts/public/static/components/required_number_input.tsx rename to src/plugins/vis_default_editor/public/components/options/required_number_input.tsx diff --git a/src/plugins/charts/public/static/components/select.tsx b/src/plugins/vis_default_editor/public/components/options/select.tsx similarity index 100% rename from src/plugins/charts/public/static/components/select.tsx rename to src/plugins/vis_default_editor/public/components/options/select.tsx diff --git a/src/plugins/charts/public/static/components/switch.tsx b/src/plugins/vis_default_editor/public/components/options/switch.tsx similarity index 100% rename from src/plugins/charts/public/static/components/switch.tsx rename to src/plugins/vis_default_editor/public/components/options/switch.tsx diff --git a/src/plugins/charts/public/static/components/text_input.tsx b/src/plugins/vis_default_editor/public/components/options/text_input.tsx similarity index 100% rename from src/plugins/charts/public/static/components/text_input.tsx rename to src/plugins/vis_default_editor/public/components/options/text_input.tsx diff --git a/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts b/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts index 337533df50fa..90e2d792d359 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts +++ b/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts @@ -20,9 +20,10 @@ import { useCallback, useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { Vis } from 'src/plugins/visualizations/public'; -import { DefaultEditorDataTab, DefaultEditorDataTabProps } from './data_tab'; +import { Vis } from '../../../../visualizations/public'; + import { VisOptionsProps } from '../../vis_options_props'; +import { DefaultEditorDataTab, DefaultEditorDataTabProps } from './data_tab'; export interface OptionTab { editor: React.ComponentType; diff --git a/src/plugins/vis_default_editor/public/default_editor_controller.tsx b/src/plugins/vis_default_editor/public/default_editor_controller.tsx index 707b14c23ea7..f44ea3e203b0 100644 --- a/src/plugins/vis_default_editor/public/default_editor_controller.tsx +++ b/src/plugins/vis_default_editor/public/default_editor_controller.tsx @@ -25,6 +25,7 @@ import { EuiErrorBoundary, EuiLoadingChart } from '@elastic/eui'; import { EditorRenderProps, IEditorController } from 'src/plugins/visualize/public'; import { Vis, VisualizeEmbeddableContract } from 'src/plugins/visualizations/public'; +// @ts-ignore const DefaultEditor = lazy(() => import('./default_editor')); class DefaultEditorController implements IEditorController { diff --git a/src/plugins/vis_default_editor/public/index.ts b/src/plugins/vis_default_editor/public/index.ts index d7eb5eda7bdf..fd1bdf8b2e65 100644 --- a/src/plugins/vis_default_editor/public/index.ts +++ b/src/plugins/vis_default_editor/public/index.ts @@ -17,18 +17,19 @@ * under the License. */ -export { DefaultEditorController } from './default_editor_controller'; +import { PluginInitializerContext } from 'kibana/public'; +import { DefaultEditorController } from './default_editor_controller'; +import { VisDefaultEditorPlugin } from './plugin'; + +export { DefaultEditorController }; export { useValidation } from './components/controls/utils'; +export * from './components/options'; export { RangesParamEditor, RangeValues } from './components/controls/ranges'; export * from './editor_size'; export * from './vis_options_props'; export * from './utils'; export { ISchemas, Schemas, Schema } from './schemas'; -/** dummy plugin, we just want visDefaultEditor to have its own bundle */ -export function plugin() { - return new (class VisDefaultEditor { - setup() {} - start() {} - })(); -} +export const plugin = (context: PluginInitializerContext) => { + return new VisDefaultEditorPlugin(); +}; diff --git a/src/plugins/vis_default_editor/public/plugin.ts b/src/plugins/vis_default_editor/public/plugin.ts new file mode 100644 index 000000000000..a7a5c6146a6e --- /dev/null +++ b/src/plugins/vis_default_editor/public/plugin.ts @@ -0,0 +1,40 @@ +/* + * 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 { CoreSetup, Plugin } from 'kibana/public'; + +import { VisualizePluginSetup } from '../../visualize/public'; +import { DefaultEditorController } from './default_editor_controller'; + +export interface VisDefaultEditorSetupDependencies { + visualize: VisualizePluginSetup; +} + +export class VisDefaultEditorPlugin + implements Plugin { + public setup(core: CoreSetup, { visualize }: VisDefaultEditorSetupDependencies) { + if (visualize) { + visualize.setDefaultEditor(DefaultEditorController); + } + } + + public start() {} + + stop() {} +} diff --git a/src/plugins/vis_default_editor/public/schemas.ts b/src/plugins/vis_default_editor/public/schemas.ts index d95a6252331b..7ecb4e54726b 100644 --- a/src/plugins/vis_default_editor/public/schemas.ts +++ b/src/plugins/vis_default_editor/public/schemas.ts @@ -17,6 +17,7 @@ * under the License. */ +import { ReactNode } from 'react'; import _, { defaults } from 'lodash'; import { Optional } from '@kbn/utility-types'; @@ -42,6 +43,8 @@ export interface Schema { hideCustomLabel?: boolean; mustBeFirst?: boolean; aggSettings?: any; + disabled?: boolean; + tooltip?: ReactNode; } export class Schemas implements ISchemas { diff --git a/src/plugins/vis_type_markdown/kibana.json b/src/plugins/vis_type_markdown/kibana.json index c0afcb0e99d1..6cfedf60687e 100644 --- a/src/plugins/vis_type_markdown/kibana.json +++ b/src/plugins/vis_type_markdown/kibana.json @@ -4,5 +4,5 @@ "ui": true, "server": true, "requiredPlugins": ["expressions", "visualizations"], - "requiredBundles": ["kibanaReact", "charts", "visualizations", "expressions", "visDefaultEditor"] + "requiredBundles": ["kibanaReact", "visualizations", "expressions", "visDefaultEditor"] } diff --git a/src/plugins/vis_type_markdown/public/settings_options.tsx b/src/plugins/vis_type_markdown/public/settings_options.tsx index bf4570db5d4a..1b793ca573f8 100644 --- a/src/plugins/vis_type_markdown/public/settings_options.tsx +++ b/src/plugins/vis_type_markdown/public/settings_options.tsx @@ -21,8 +21,7 @@ import React from 'react'; import { EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { RangeOption, SwitchOption } from '../../charts/public'; +import { VisOptionsProps, SwitchOption, RangeOption } from '../../vis_default_editor/public'; import { MarkdownVisParams } from './types'; function SettingsOptions({ stateParams, setValue }: VisOptionsProps) { diff --git a/src/plugins/vis_type_markdown/public/to_ast.test.ts b/src/plugins/vis_type_markdown/public/to_ast.test.ts index 1ad1fa0ee251..4c7b570aef05 100644 --- a/src/plugins/vis_type_markdown/public/to_ast.test.ts +++ b/src/plugins/vis_type_markdown/public/to_ast.test.ts @@ -42,12 +42,14 @@ describe('markdown vis toExpressionAst function', () => { it('without params', () => { vis.params = {}; + // @ts-expect-error const actual = toExpressionAst(vis); expect(actual).toMatchSnapshot(); }); it('with params', () => { vis.params = { markdown: '### my markdown', fontSize: 15, openLinksInNewTab: true }; + // @ts-expect-error const actual = toExpressionAst(vis); expect(actual).toMatchSnapshot(); }); diff --git a/src/plugins/vis_type_markdown/public/to_ast.ts b/src/plugins/vis_type_markdown/public/to_ast.ts index 9b481218b42e..dc61acf722ad 100644 --- a/src/plugins/vis_type_markdown/public/to_ast.ts +++ b/src/plugins/vis_type_markdown/public/to_ast.ts @@ -17,11 +17,11 @@ * under the License. */ -import { Vis } from '../../visualizations/public'; +import { VisToExpressionAst } from '../../visualizations/public'; import { buildExpression, buildExpressionFunction } from '../../expressions/public'; import { MarkdownVisExpressionFunctionDefinition } from './markdown_fn'; -export const toExpressionAst = (vis: Vis) => { +export const toExpressionAst: VisToExpressionAst = (vis) => { const { markdown, fontSize, openLinksInNewTab } = vis.params; const markdownVis = buildExpressionFunction( diff --git a/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx b/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx index d0a741223887..58c486dfa90a 100644 --- a/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx +++ b/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx @@ -29,16 +29,16 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; import { - ColorModes, ColorRanges, - ColorSchemaOptions, + SetColorRangeValue, + VisOptionsProps, SwitchOption, - RangeOption, SetColorSchemaOptionsValue, - SetColorRangeValue, -} from '../../../charts/public'; + ColorSchemaOptions, + RangeOption, +} from '../../../vis_default_editor/public'; +import { ColorMode } from '../../../charts/public'; import { MetricVisParam, VisParams } from '../types'; function MetricVisOptions({ @@ -86,7 +86,7 @@ function MetricVisOptions({ ); const setColorMode: EuiButtonGroupProps['onChange'] = useCallback( - (id: string) => setMetricValue('metricColorMode', id as ColorModes), + (id: string) => setMetricValue('metricColorMode', id as ColorMode), [setMetricValue] ); @@ -158,7 +158,7 @@ function MetricVisOptions({ colorSchemas={vis.type.editorConfig.collections.colorSchemas} disabled={ stateParams.metric.colorsRange.length === 1 || - stateParams.metric.metricColorMode === ColorModes.NONE + stateParams.metric.metricColorMode === ColorMode.None } invertColors={stateParams.metric.invertColors} setValue={setMetricValue as SetColorSchemaOptionsValue} diff --git a/src/plugins/vis_type_metric/public/metric_vis_fn.ts b/src/plugins/vis_type_metric/public/metric_vis_fn.ts index ae6dc6683852..783ca3d3906e 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_fn.ts +++ b/src/plugins/vis_type_metric/public/metric_vis_fn.ts @@ -27,14 +27,14 @@ import { Style, } from '../../expressions/public'; import { visType, DimensionsVisParam, VisParams } from './types'; -import { ColorSchemas, vislibColorMaps, ColorModes } from '../../charts/public'; +import { ColorSchemas, vislibColorMaps, ColorMode } from '../../charts/public'; export type Input = Datatable; interface Arguments { percentageMode: boolean; colorSchema: ColorSchemas; - colorMode: ColorModes; + colorMode: ColorMode; useRanges: boolean; invertColors: boolean; showLabels: boolean; @@ -86,7 +86,7 @@ export const createMetricVisFn = (): MetricVisExpressionFunctionDefinition => ({ colorMode: { types: ['string'], default: '"None"', - options: [ColorModes.NONE, ColorModes.LABELS, ColorModes.BACKGROUND], + options: [ColorMode.None, ColorMode.Labels, ColorMode.Background], help: i18n.translate('visTypeMetric.function.colorMode.help', { defaultMessage: 'Which part of metric to color', }), @@ -197,8 +197,8 @@ export const createMetricVisFn = (): MetricVisExpressionFunctionDefinition => ({ invertColors: args.invertColors, style: { bgFill: args.bgFill, - bgColor: args.colorMode === ColorModes.BACKGROUND, - labelColor: args.colorMode === ColorModes.LABELS, + bgColor: args.colorMode === ColorMode.Background, + labelColor: args.colorMode === ColorMode.Labels, subText: args.subText, fontSize, }, diff --git a/src/plugins/vis_type_metric/public/metric_vis_type.ts b/src/plugins/vis_type_metric/public/metric_vis_type.ts index f7c74e324053..ba8f27b9412a 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_type.ts +++ b/src/plugins/vis_type_metric/public/metric_vis_type.ts @@ -20,7 +20,7 @@ import { i18n } from '@kbn/i18n'; import { BaseVisTypeOptions } from 'src/plugins/visualizations/public'; import { MetricVisOptions } from './components/metric_vis_options'; -import { ColorSchemas, colorSchemas, ColorModes } from '../../charts/public'; +import { ColorSchemas, colorSchemas, ColorMode } from '../../charts/public'; import { AggGroupNames } from '../../data/public'; import { Schemas } from '../../vis_default_editor/public'; import { toExpressionAst } from './to_ast'; @@ -42,7 +42,7 @@ export const createMetricVisTypeDefinition = (): BaseVisTypeOptions => ({ percentageMode: false, useRanges: false, colorSchema: ColorSchemas.GreenToRed, - metricColorMode: ColorModes.NONE, + metricColorMode: ColorMode.None, colorsRange: [{ from: 0, to: 10000 }], labels: { show: true, @@ -62,19 +62,19 @@ export const createMetricVisTypeDefinition = (): BaseVisTypeOptions => ({ collections: { metricColorMode: [ { - id: ColorModes.NONE, + id: ColorMode.None, label: i18n.translate('visTypeMetric.colorModes.noneOptionLabel', { defaultMessage: 'None', }), }, { - id: ColorModes.LABELS, + id: ColorMode.Labels, label: i18n.translate('visTypeMetric.colorModes.labelsOptionLabel', { defaultMessage: 'Labels', }), }, { - id: ColorModes.BACKGROUND, + id: ColorMode.Background, label: i18n.translate('visTypeMetric.colorModes.backgroundOptionLabel', { defaultMessage: 'Background', }), diff --git a/src/plugins/vis_type_metric/public/types.ts b/src/plugins/vis_type_metric/public/types.ts index e1f2c7721a42..e0ebfb36fa37 100644 --- a/src/plugins/vis_type_metric/public/types.ts +++ b/src/plugins/vis_type_metric/public/types.ts @@ -19,7 +19,7 @@ import { Range } from '../../expressions/public'; import { SchemaConfig } from '../../visualizations/public'; -import { ColorModes, Labels, Style, ColorSchemas } from '../../charts/public'; +import { ColorMode, Labels, Style, ColorSchemas } from '../../charts/public'; export const visType = 'metric'; @@ -32,7 +32,7 @@ export interface MetricVisParam { percentageMode: boolean; useRanges: boolean; colorSchema: ColorSchemas; - metricColorMode: ColorModes; + metricColorMode: ColorMode; colorsRange: Range[]; labels: Labels; invertColors: boolean; diff --git a/src/plugins/vis_type_table/kibana.json b/src/plugins/vis_type_table/kibana.json index dce9bce0e888..1fb8516851eb 100644 --- a/src/plugins/vis_type_table/kibana.json +++ b/src/plugins/vis_type_table/kibana.json @@ -13,7 +13,6 @@ "kibanaUtils", "kibanaReact", "share", - "charts", "visDefaultEditor" ], "optionalPlugins": ["usageCollection"] diff --git a/src/plugins/vis_type_table/public/components/table_vis_options.tsx b/src/plugins/vis_type_table/public/components/table_vis_options.tsx index b81f0425011d..3932db1262ac 100644 --- a/src/plugins/vis_type_table/public/components/table_vis_options.tsx +++ b/src/plugins/vis_type_table/public/components/table_vis_options.tsx @@ -23,9 +23,13 @@ import { EuiIconTip, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; import { search } from '../../../data/public'; -import { SwitchOption, SelectOption, NumberInputOption } from '../../../charts/public'; +import { + SwitchOption, + SelectOption, + NumberInputOption, + VisOptionsProps, +} from '../../../vis_default_editor/public'; import { TableVisParams } from '../types'; import { totalAggregations } from './utils'; diff --git a/src/plugins/vis_type_table/public/components/table_visualization.tsx b/src/plugins/vis_type_table/public/components/table_visualization.tsx index 2d38acc57519..a1e4fad719dc 100644 --- a/src/plugins/vis_type_table/public/components/table_visualization.tsx +++ b/src/plugins/vis_type_table/public/components/table_visualization.tsx @@ -23,6 +23,7 @@ import classNames from 'classnames'; import { CoreStart } from 'kibana/public'; import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; +import type { PersistedState } from 'src/plugins/visualizations/public'; import { KibanaContextProvider } from '../../../kibana_react/public'; import { TableVisConfig } from '../types'; import { TableContext } from '../table_vis_response_handler'; @@ -47,7 +48,7 @@ const TableVisualizationComponent = ({ handlers.done(); }, [handlers]); - const uiStateProps = useUiState(handlers.uiState); + const uiStateProps = useUiState(handlers.uiState as PersistedState); const className = classNames('tbvChart', { // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/src/plugins/vis_type_table/public/utils/use/use_ui_state.ts b/src/plugins/vis_type_table/public/utils/use/use_ui_state.ts index 68bad16972ec..cc43fc6bcb58 100644 --- a/src/plugins/vis_type_table/public/utils/use/use_ui_state.ts +++ b/src/plugins/vis_type_table/public/utils/use/use_ui_state.ts @@ -19,7 +19,7 @@ import { debounce, isEqual } from 'lodash'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; +import type { PersistedState } from 'src/plugins/visualizations/public'; import { ColumnWidthData, TableVisUiState, TableVisUseUiStateProps } from '../../types'; @@ -28,9 +28,7 @@ const defaultSort = { direction: null, }; -export const useUiState = ( - uiState: IInterpreterRenderHandlers['uiState'] -): TableVisUseUiStateProps => { +export const useUiState = (uiState: PersistedState): TableVisUseUiStateProps => { const [sort, setSortState] = useState( uiState?.get('vis.params.sort') || defaultSort ); diff --git a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx index d33576e4e552..5d5f499d650b 100644 --- a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx +++ b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx @@ -20,9 +20,8 @@ import React from 'react'; import { EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps } from '../../../vis_default_editor/public'; +import { VisOptionsProps, SelectOption, SwitchOption } from '../../../vis_default_editor/public'; import { ValidatedDualRange } from '../../../kibana_react/public'; -import { SelectOption, SwitchOption } from '../../../charts/public'; import { TagCloudVisParams } from '../types'; function TagCloudOptions({ stateParams, setValue, vis }: VisOptionsProps) { diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/decorators/__snapshots__/area_decorator.test.js.snap b/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/decorators/__snapshots__/area_decorator.test.js.snap index 7ded8e2254aa..fceb9c3fdb81 100644 --- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/decorators/__snapshots__/area_decorator.test.js.snap +++ b/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/decorators/__snapshots__/area_decorator.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`src/legacy/core_plugins/metrics/public/visualizations/views/timeseries/decorators/area_decorator.js should render and match a snapshot 1`] = ` - should render and match a snapshot 1`] = ` - , domNode diff --git a/src/plugins/vis_type_timeseries/server/routes/fields.ts b/src/plugins/vis_type_timeseries/server/routes/fields.ts index a9a890845d15..e787fd8d08a2 100644 --- a/src/plugins/vis_type_timeseries/server/routes/fields.ts +++ b/src/plugins/vis_type_timeseries/server/routes/fields.ts @@ -39,7 +39,7 @@ export const fieldsRoutes = (framework: Framework) => { return res.customError({ body: err.output.payload, statusCode: err.output.statusCode, - headers: err.output.headers, + headers: err.output.headers as { [key: string]: string }, }); } diff --git a/src/plugins/vis_type_vislib/kibana.json b/src/plugins/vis_type_vislib/kibana.json index 720abff16b7c..175c21f47c18 100644 --- a/src/plugins/vis_type_vislib/kibana.json +++ b/src/plugins/vis_type_vislib/kibana.json @@ -4,6 +4,5 @@ "server": true, "ui": true, "requiredPlugins": ["charts", "data", "expressions", "visualizations", "kibanaLegacy"], - "optionalPlugins": ["visTypeXy"], - "requiredBundles": ["kibanaUtils", "visDefaultEditor"] + "requiredBundles": ["kibanaUtils", "visDefaultEditor", "visTypeXy"] } diff --git a/src/plugins/vis_type_vislib/public/area.ts b/src/plugins/vis_type_vislib/public/area.ts index ec7bce254f58..389daca6d177 100644 --- a/src/plugins/vis_type_vislib/public/area.ts +++ b/src/plugins/vis_type_vislib/public/area.ts @@ -17,172 +17,14 @@ * under the License. */ -import { i18n } from '@kbn/i18n'; -// @ts-ignore -import { palettes } from '@elastic/eui/lib/services'; -// @ts-ignore -import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; +import { xyVisTypes } from '../../vis_type_xy/public'; +import { BaseVisTypeOptions } from '../../visualizations/public'; -import { AggGroupNames } from '../../data/public'; -import { Schemas } from '../../vis_default_editor/public'; -import { - Positions, - ChartTypes, - ChartModes, - InterpolationModes, - AxisTypes, - ScaleTypes, - AxisModes, - ThresholdLineStyles, - getConfigCollections, -} from './utils/collections'; -import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { Rotates } from '../../charts/public'; -import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; import { toExpressionAst } from './to_ast'; import { BasicVislibParams } from './types'; 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 data between an axis and a line.', - }), - getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], + ...(xyVisTypes.area() as BaseVisTypeOptions), toExpressionAst, - visConfig: { - defaults: { - type: 'area', - grid: { - categoryLines: false, - }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: AxisTypes.CATEGORY, - position: Positions.BOTTOM, - show: true, - style: {}, - scale: { - type: ScaleTypes.LINEAR, - }, - labels: { - show: true, - filter: true, - truncate: 100, - }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: AxisTypes.VALUE, - position: Positions.LEFT, - show: true, - style: {}, - scale: { - type: ScaleTypes.LINEAR, - mode: AxisModes.NORMAL, - }, - labels: { - show: true, - rotate: Rotates.HORIZONTAL, - filter: false, - truncate: 100, - }, - title: { - text: countLabel, - }, - }, - ], - seriesParams: [ - { - show: true, - type: ChartTypes.AREA, - mode: ChartModes.STACKED, - data: { - label: countLabel, - id: '1', - }, - drawLinesBetweenPoints: true, - lineWidth: 2, - showCircles: true, - interpolate: InterpolationModes.LINEAR, - valueAxis: 'ValueAxis-1', - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: Positions.RIGHT, - times: [], - addTimeMarker: false, - thresholdLine: { - show: false, - value: 10, - width: 1, - style: ThresholdLineStyles.FULL, - color: euiPaletteColorBlind()[9], - }, - labels: {}, - }, - }, - editorConfig: { - collections: getConfigCollections(), - optionTabs: getAreaOptionTabs(), - schemas: new Schemas([ - { - group: AggGroupNames.Metrics, - name: 'metric', - title: i18n.translate('visTypeVislib.area.metricsTitle', { - defaultMessage: 'Y-axis', - }), - aggFilter: ['!geo_centroid', '!geo_bounds'], - min: 1, - defaults: [{ schema: 'metric', type: 'count' }], - }, - { - group: AggGroupNames.Metrics, - name: 'radius', - title: i18n.translate('visTypeVislib.area.radiusTitle', { - defaultMessage: 'Dot size', - }), - min: 0, - max: 1, - aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality'], - }, - { - group: AggGroupNames.Buckets, - name: 'segment', - title: i18n.translate('visTypeVislib.area.segmentTitle', { - defaultMessage: 'X-axis', - }), - min: 0, - max: 1, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'group', - title: i18n.translate('visTypeVislib.area.groupTitle', { - defaultMessage: 'Split series', - }), - min: 0, - max: 3, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'split', - title: i18n.translate('visTypeVislib.area.splitTitle', { - defaultMessage: 'Split chart', - }), - min: 0, - max: 1, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - ]), - }, + visualization: undefined, }; 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 deleted file mode 100644 index 63881fea1ad8..000000000000 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { mount, shallow } from 'enzyme'; - -import { IAggConfig, IAggType } from 'src/plugins/data/public'; -import MetricsAxisOptions from './index'; -import { BasicVislibParams, SeriesParam, ValueAxis } from '../../../types'; -import { ValidationVisOptionsProps } from '../../common'; -import { Positions } from '../../../utils/collections'; -import { ValueAxesPanel } from './value_axes_panel'; -import { CategoryAxisPanel } from './category_axis_panel'; -import { ChartTypes } from '../../../utils/collections'; -import { defaultValueAxisId, valueAxis, seriesParam, categoryAxis } from './mocks'; - -jest.mock('./series_panel', () => ({ - SeriesPanel: () => 'SeriesPanel', -})); -jest.mock('./category_axis_panel', () => ({ - CategoryAxisPanel: () => 'CategoryAxisPanel', -})); -jest.mock('./value_axes_panel', () => ({ - ValueAxesPanel: () => 'ValueAxesPanel', -})); - -const SERIES_PARAMS = 'seriesParams'; -const VALUE_AXES = 'valueAxes'; - -const aggCount: IAggConfig = { - id: '1', - type: { name: 'count' }, - makeLabel: () => 'Count', -} as IAggConfig; - -const aggAverage: IAggConfig = { - id: '2', - type: { name: 'average' } as IAggType, - makeLabel: () => 'Average', -} as IAggConfig; - -const createAggs = (aggs: any[]) => ({ - aggs, - bySchemaName: () => aggs, -}); - -describe('MetricsAxisOptions component', () => { - let setValue: jest.Mock; - let defaultProps: ValidationVisOptionsProps; - let axis: ValueAxis; - let axisRight: ValueAxis; - let chart: SeriesParam; - - beforeEach(() => { - setValue = jest.fn(); - - axis = { - ...valueAxis, - name: 'LeftAxis-1', - position: Positions.LEFT, - }; - axisRight = { - ...valueAxis, - id: 'ValueAxis-2', - name: 'RightAxis-1', - position: Positions.RIGHT, - }; - chart = { - ...seriesParam, - type: ChartTypes.AREA, - }; - - defaultProps = { - aggs: createAggs([aggCount]), - isTabSelected: true, - vis: { - type: { - type: ChartTypes.AREA, - schemas: { metrics: [{ name: 'metric' }] }, - }, - setState: jest.fn(), - serialize: jest.fn(), - }, - stateParams: { - valueAxes: [axis], - seriesParams: [chart], - categoryAxes: [categoryAxis], - grid: { valueAxis: defaultValueAxisId }, - }, - setValue, - } as any; - }); - - it('should init with the default set of props', () => { - const comp = shallow(); - - expect(comp).toMatchSnapshot(); - }); - - describe('useEffect', () => { - it('should update series when new agg is added', () => { - const comp = mount(); - comp.setProps({ - aggs: createAggs([aggCount, aggAverage]), - }); - - const updatedSeries = [chart, { ...chart, data: { id: '2', label: aggAverage.makeLabel() } }]; - expect(setValue).toHaveBeenLastCalledWith(SERIES_PARAMS, updatedSeries); - }); - - it('should update series when new agg label is changed', () => { - const comp = mount(); - const agg = { id: aggCount.id, makeLabel: () => 'New label' }; - comp.setProps({ - aggs: createAggs([agg]), - }); - - const updatedSeries = [{ ...chart, data: { id: agg.id, label: agg.makeLabel() } }]; - expect(setValue).toHaveBeenCalledWith(SERIES_PARAMS, updatedSeries); - }); - }); - - describe('updateAxisTitle', () => { - it('should not update the value axis title if custom title was set', () => { - defaultProps.stateParams.valueAxes[0].title.text = 'Custom title'; - const comp = mount(); - const newAgg = { - ...aggCount, - makeLabel: () => 'Custom label', - }; - comp.setProps({ - aggs: createAggs([newAgg]), - }); - const updatedValues = [{ ...axis, title: { text: newAgg.makeLabel() } }]; - expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES, updatedValues); - }); - - it('should set the custom title to match the value axis label when only one agg exists for that axis', () => { - const comp = mount(); - const agg = { - id: aggCount.id, - params: { customLabel: 'Custom label' }, - makeLabel: () => 'Custom label', - }; - comp.setProps({ - aggs: createAggs([agg]), - }); - - const updatedSeriesParams = [{ ...chart, data: { ...chart.data, label: agg.makeLabel() } }]; - const updatedValues = [{ ...axis, title: { text: agg.makeLabel() } }]; - - expect(setValue).toHaveBeenCalledTimes(5); - expect(setValue).toHaveBeenNthCalledWith(3, SERIES_PARAMS, updatedSeriesParams); - expect(setValue).toHaveBeenNthCalledWith(5, SERIES_PARAMS, updatedSeriesParams); - expect(setValue).toHaveBeenNthCalledWith(4, VALUE_AXES, updatedValues); - }); - - it('should not set the custom title to match the value axis label when more than one agg exists for that axis', () => { - const comp = mount(); - const agg = { id: aggCount.id, makeLabel: () => 'Custom label' }; - comp.setProps({ - aggs: createAggs([agg, aggAverage]), - stateParams: { - ...defaultProps.stateParams, - seriesParams: [chart, chart], - }, - }); - - expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES); - }); - - it('should not overwrite the custom title with the value axis label if the custom title has been changed', () => { - defaultProps.stateParams.valueAxes[0].title.text = 'Custom title'; - const comp = mount(); - const agg = { - id: aggCount.id, - params: { customLabel: 'Custom label' }, - makeLabel: () => 'Custom label', - }; - comp.setProps({ - aggs: createAggs([agg]), - }); - - expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES); - }); - }); - - it('should add value axis', () => { - const comp = shallow(); - comp.find(ValueAxesPanel).prop('addValueAxis')(); - - expect(setValue).toHaveBeenCalledWith(VALUE_AXES, [axis, axisRight]); - }); - - describe('removeValueAxis', () => { - beforeEach(() => { - defaultProps.stateParams.valueAxes = [axis, axisRight]; - }); - - it('should remove value axis', () => { - const comp = shallow(); - comp.find(ValueAxesPanel).prop('removeValueAxis')(axis); - - expect(setValue).toHaveBeenCalledWith(VALUE_AXES, [axisRight]); - }); - - it('should update seriesParams "valueAxis" prop', () => { - const updatedSeriesParam = { ...chart, valueAxis: 'ValueAxis-2' }; - const comp = shallow(); - comp.find(ValueAxesPanel).prop('removeValueAxis')(axis); - - expect(setValue).toHaveBeenCalledWith(SERIES_PARAMS, [updatedSeriesParam]); - }); - - it('should reset grid "valueAxis" prop', () => { - const updatedGrid = { valueAxis: undefined }; - defaultProps.stateParams.seriesParams[0].valueAxis = 'ValueAxis-2'; - const comp = shallow(); - comp.find(ValueAxesPanel).prop('removeValueAxis')(axis); - - expect(setValue).toHaveBeenCalledWith('grid', updatedGrid); - }); - }); - - it('should update axis value when when category position chnaged', () => { - const comp = shallow(); - comp.find(CategoryAxisPanel).prop('onPositionChanged')(Positions.LEFT); - - const updatedValues = [{ ...axis, name: 'BottomAxis-1', position: Positions.BOTTOM }]; - expect(setValue).toHaveBeenCalledWith(VALUE_AXES, updatedValues); - }); -}); diff --git a/src/plugins/vis_type_vislib/public/editor/collections.ts b/src/plugins/vis_type_vislib/public/editor/collections.ts new file mode 100644 index 000000000000..f1caa0754b0b --- /dev/null +++ b/src/plugins/vis_type_vislib/public/editor/collections.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +import { colorSchemas } from '../../../charts/public'; +import { getPositions, getScaleTypes } from '../../../vis_type_xy/public'; + +import { Alignment, GaugeType } from '../types'; + +export const getGaugeTypes = () => [ + { + text: i18n.translate('visTypeVislib.gauge.gaugeTypes.arcText', { + defaultMessage: 'Arc', + }), + value: GaugeType.Arc, + }, + { + text: i18n.translate('visTypeVislib.gauge.gaugeTypes.circleText', { + defaultMessage: 'Circle', + }), + value: GaugeType.Circle, + }, +]; + +export const getAlignments = () => [ + { + text: i18n.translate('visTypeVislib.gauge.alignmentAutomaticTitle', { + defaultMessage: 'Automatic', + }), + value: Alignment.Automatic, + }, + { + text: i18n.translate('visTypeVislib.gauge.alignmentHorizontalTitle', { + defaultMessage: 'Horizontal', + }), + value: Alignment.Horizontal, + }, + { + text: i18n.translate('visTypeVislib.gauge.alignmentVerticalTitle', { + defaultMessage: 'Vertical', + }), + value: Alignment.Vertical, + }, +]; + +export const getGaugeCollections = () => ({ + gaugeTypes: getGaugeTypes(), + alignments: getAlignments(), + colorSchemas, +}); + +export const getHeatmapCollections = () => ({ + legendPositions: getPositions(), + scales: getScaleTypes(), + colorSchemas, +}); diff --git a/src/plugins/vis_type_vislib/public/components/options/gauge/index.tsx b/src/plugins/vis_type_vislib/public/editor/components/gauge/index.tsx similarity index 100% rename from src/plugins/vis_type_vislib/public/components/options/gauge/index.tsx rename to src/plugins/vis_type_vislib/public/editor/components/gauge/index.tsx diff --git a/src/plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx b/src/plugins/vis_type_vislib/public/editor/components/gauge/labels_panel.tsx similarity index 96% rename from src/plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx rename to src/plugins/vis_type_vislib/public/editor/components/gauge/labels_panel.tsx index 0bd5694f7102..e02f62fa6ed6 100644 --- a/src/plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/gauge/labels_panel.tsx @@ -21,8 +21,7 @@ import React from 'react'; import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; - -import { SwitchOption, TextInputOption } from '../../../../../charts/public'; +import { SwitchOption, TextInputOption } from '../../../../../vis_default_editor/public'; import { GaugeOptionsInternalProps } from '../gauge'; function LabelsPanel({ stateParams, setValue, setGaugeValue }: GaugeOptionsInternalProps) { diff --git a/src/plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx b/src/plugins/vis_type_vislib/public/editor/components/gauge/ranges_panel.tsx similarity index 97% rename from src/plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx rename to src/plugins/vis_type_vislib/public/editor/components/gauge/ranges_panel.tsx index c297fb08e4b6..ec5201af2e7d 100644 --- a/src/plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/gauge/ranges_panel.tsx @@ -21,15 +21,13 @@ import React, { useCallback } from 'react'; import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; - import { ColorRanges, - ColorSchemaOptions, - ColorSchemaParams, SetColorRangeValue, SwitchOption, - ColorSchemas, -} from '../../../../../charts/public'; + ColorSchemaOptions, +} from '../../../../../vis_default_editor/public'; +import { ColorSchemaParams, ColorSchemas } from '../../../../../charts/public'; import { GaugeOptionsInternalProps } from '../gauge'; import { Gauge } from '../../../gauge'; diff --git a/src/plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx b/src/plugins/vis_type_vislib/public/editor/components/gauge/style_panel.tsx similarity index 96% rename from src/plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx rename to src/plugins/vis_type_vislib/public/editor/components/gauge/style_panel.tsx index b299b2e86ca4..9cb807aac575 100644 --- a/src/plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/gauge/style_panel.tsx @@ -22,7 +22,7 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { SelectOption } from '../../../../../charts/public'; +import { SelectOption } from '../../../../../vis_default_editor/public'; import { GaugeOptionsInternalProps } from '../gauge'; import { AggGroupNames } from '../../../../../data/public'; diff --git a/src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx b/src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx similarity index 97% rename from src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx rename to src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx index 312cf60fda6b..a409762b30f9 100644 --- a/src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx @@ -23,19 +23,20 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { ValueAxis } from '../../../../../vis_type_xy/public'; import { + VisOptionsProps, BasicOptions, - ColorRanges, - ColorSchemaOptions, - NumberInputOption, SelectOption, SwitchOption, - SetColorSchemaOptionsValue, + ColorRanges, SetColorRangeValue, -} from '../../../../../charts/public'; + SetColorSchemaOptionsValue, + ColorSchemaOptions, + NumberInputOption, +} from '../../../../../vis_default_editor/public'; + import { HeatmapVisParams } from '../../../heatmap'; -import { ValueAxis } from '../../../types'; import { LabelsPanel } from './labels_panel'; function HeatmapOptions(props: VisOptionsProps) { diff --git a/src/plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx b/src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx similarity index 95% rename from src/plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx rename to src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx index 4998a8fd0252..506e5f74dc97 100644 --- a/src/plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx @@ -23,10 +23,10 @@ import { EuiColorPicker, EuiFormRow, EuiPanel, EuiSpacer, EuiTitle } from '@elas import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { ValueAxis } from '../../../types'; +import { VisOptionsProps, SwitchOption } from '../../../../../vis_default_editor/public'; +import { ValueAxis } from '../../../../../vis_type_xy/public'; + import { HeatmapVisParams } from '../../../heatmap'; -import { SwitchOption } from '../../../../../charts/public'; const VERTICAL_ROTATION = 270; diff --git a/src/plugins/vis_type_vislib/public/components/options/index.tsx b/src/plugins/vis_type_vislib/public/editor/components/index.tsx similarity index 71% rename from src/plugins/vis_type_vislib/public/components/options/index.tsx rename to src/plugins/vis_type_vislib/public/editor/components/index.tsx index 18c41bf289b1..ed8c8239a07b 100644 --- a/src/plugins/vis_type_vislib/public/components/options/index.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/index.tsx @@ -19,18 +19,15 @@ import React, { lazy } from 'react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { ValidationVisOptionsProps } from '../common'; +import { VisOptionsProps } from '../../../../vis_default_editor/public'; + 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) => ( @@ -38,14 +35,6 @@ 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/pie.tsx b/src/plugins/vis_type_vislib/public/editor/components/pie.tsx similarity index 94% rename from src/plugins/vis_type_vislib/public/components/options/pie.tsx rename to src/plugins/vis_type_vislib/public/editor/components/pie.tsx index 30828bfc6a3e..01516630287e 100644 --- a/src/plugins/vis_type_vislib/public/components/options/pie.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/pie.tsx @@ -22,9 +22,9 @@ import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { TruncateLabelsOption } from '../common'; -import { BasicOptions, SwitchOption } from '../../../../charts/public'; +import { BasicOptions, SwitchOption, VisOptionsProps } from '../../../../vis_default_editor/public'; +import { TruncateLabelsOption } from '../../../../vis_type_xy/public'; + import { PieVisParams } from '../../pie'; function PieOptions(props: VisOptionsProps) { diff --git a/src/plugins/vis_type_vislib/public/editor/index.ts b/src/plugins/vis_type_vislib/public/editor/index.ts new file mode 100644 index 000000000000..2a73b1ad8fa6 --- /dev/null +++ b/src/plugins/vis_type_vislib/public/editor/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './collections'; +export * from './components'; diff --git a/src/plugins/vis_type_vislib/public/gauge.ts b/src/plugins/vis_type_vislib/public/gauge.ts index 7cc8e03c9e4c..de32ee17a21b 100644 --- a/src/plugins/vis_type_vislib/public/gauge.ts +++ b/src/plugins/vis_type_vislib/public/gauge.ts @@ -19,24 +19,25 @@ import { i18n } from '@kbn/i18n'; +import { ColorMode, ColorSchemas, ColorSchemaParams, Labels, Style } from '../../charts/public'; import { RangeValues, Schemas } from '../../vis_default_editor/public'; 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 { toExpressionAst } from './to_ast'; import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; -import { BasicVislibParams } from './types'; + +import { Alignment, GaugeType, BasicVislibParams, VislibChartType } from './types'; +import { getGaugeCollections } from './editor'; +import { toExpressionAst } from './to_ast'; +import { GaugeOptions } from './editor/components'; export interface Gauge extends ColorSchemaParams { backStyle: 'Full'; gaugeStyle: 'Full'; orientation: 'vertical'; type: 'meter'; - alignment: Alignments; + alignment: Alignment; colorsRange: RangeValues[]; extendRange: boolean; - gaugeType: GaugeTypes; + gaugeType: GaugeType; labels: Labels; percentageMode: boolean; outline?: boolean; @@ -67,20 +68,20 @@ export const gaugeVisTypeDefinition: BaseVisTypeOptions = { toExpressionAst, visConfig: { defaults: { - type: 'gauge', + type: VislibChartType.Gauge, addTooltip: true, addLegend: true, isDisplayWarning: false, gauge: { - alignment: Alignments.AUTOMATIC, + alignment: Alignment.Automatic, extendRange: true, percentageMode: false, - gaugeType: GaugeTypes.ARC, + gaugeType: GaugeType.Arc, gaugeStyle: 'Full', backStyle: 'Full', orientation: 'vertical', colorSchema: ColorSchemas.GreenToRed, - gaugeColorMode: ColorModes.LABELS, + gaugeColorMode: ColorMode.Labels, colorsRange: [ { from: 0, to: 50 }, { from: 50, to: 75 }, diff --git a/src/plugins/vis_type_vislib/public/goal.ts b/src/plugins/vis_type_vislib/public/goal.ts index 46878ca82e45..56361421261f 100644 --- a/src/plugins/vis_type_vislib/public/goal.ts +++ b/src/plugins/vis_type_vislib/public/goal.ts @@ -19,14 +19,14 @@ import { i18n } from '@kbn/i18n'; -import { GaugeOptions } from './components/options'; -import { getGaugeCollections, GaugeTypes } from './utils/collections'; -import { ColorModes, ColorSchemas } from '../../charts/public'; import { AggGroupNames } from '../../data/public'; import { Schemas } from '../../vis_default_editor/public'; -import { toExpressionAst } from './to_ast'; +import { ColorMode, ColorSchemas } from '../../charts/public'; import { BaseVisTypeOptions } from '../../visualizations/public'; -import { BasicVislibParams } from './types'; + +import { getGaugeCollections, GaugeOptions } from './editor'; +import { toExpressionAst } from './to_ast'; +import { GaugeType, BasicVislibParams } from './types'; export const goalVisTypeDefinition: BaseVisTypeOptions = { name: 'goal', @@ -46,13 +46,13 @@ export const goalVisTypeDefinition: BaseVisTypeOptions = { verticalSplit: false, autoExtend: false, percentageMode: true, - gaugeType: GaugeTypes.ARC, + gaugeType: GaugeType.Arc, gaugeStyle: 'Full', backStyle: 'Full', orientation: 'vertical', useRanges: false, colorSchema: ColorSchemas.GreenToRed, - gaugeColorMode: ColorModes.NONE, + gaugeColorMode: ColorMode.None, colorsRange: [{ from: 0, to: 10000 }], invertColors: false, labels: { diff --git a/src/plugins/vis_type_vislib/public/heatmap.ts b/src/plugins/vis_type_vislib/public/heatmap.ts index c408ac140dd4..4a815fd8b2c7 100644 --- a/src/plugins/vis_type_vislib/public/heatmap.ts +++ b/src/plugins/vis_type_vislib/public/heatmap.ts @@ -18,15 +18,17 @@ */ import { i18n } from '@kbn/i18n'; +import { Position } from '@elastic/charts'; 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 { TimeMarker } from './vislib/visualizations/time_marker'; -import { BasicVislibParams, CommonVislibParams, ValueAxis } from './types'; import { ColorSchemas, ColorSchemaParams } from '../../charts/public'; -import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { VIS_EVENT_TO_TRIGGER, BaseVisTypeOptions } from '../../visualizations/public'; +import { ValueAxis, ScaleType, AxisType } from '../../vis_type_xy/public'; + +import { HeatmapOptions, getHeatmapCollections } from './editor'; +import { TimeMarker } from './vislib/visualizations/time_marker'; +import { CommonVislibParams, BasicVislibParams, VislibChartType } from './types'; import { toExpressionAst } from './to_ast'; export interface HeatmapVisParams extends CommonVislibParams, ColorSchemaParams { @@ -48,15 +50,15 @@ export const heatmapVisTypeDefinition: BaseVisTypeOptions = { description: i18n.translate('visTypeVislib.heatmap.heatmapDescription', { defaultMessage: 'Shade data in cells in a matrix.', }), - getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter], toExpressionAst, + getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter], visConfig: { defaults: { - type: 'heatmap', + type: VislibChartType.Heatmap, addTooltip: true, addLegend: true, enableHover: false, - legendPosition: Positions.RIGHT, + legendPosition: Position.Right, times: [], colorsNumber: 4, colorSchema: ColorSchemas.Greens, @@ -68,9 +70,9 @@ export const heatmapVisTypeDefinition: BaseVisTypeOptions = { { show: false, id: 'ValueAxis-1', - type: AxisTypes.VALUE, + type: AxisType.Value, scale: { - type: ScaleTypes.LINEAR, + type: ScaleType.Linear, defaultYExtents: false, }, labels: { diff --git a/src/plugins/vis_type_vislib/public/histogram.ts b/src/plugins/vis_type_vislib/public/histogram.ts index de4855ba9aa2..7424ef5c4df2 100644 --- a/src/plugins/vis_type_vislib/public/histogram.ts +++ b/src/plugins/vis_type_vislib/public/histogram.ts @@ -17,174 +17,14 @@ * under the License. */ -import { i18n } from '@kbn/i18n'; -// @ts-ignore -import { palettes } from '@elastic/eui/lib/services'; -// @ts-ignore -import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; +import { xyVisTypes } from '../../vis_type_xy/public'; +import { BaseVisTypeOptions } from '../../visualizations/public'; -import { AggGroupNames } from '../../data/public'; -import { Schemas } from '../../vis_default_editor/public'; -import { - Positions, - ChartTypes, - ChartModes, - AxisTypes, - ScaleTypes, - AxisModes, - ThresholdLineStyles, - getConfigCollections, -} from './utils/collections'; -import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { Rotates } from '../../charts/public'; -import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; -import { BasicVislibParams } from './types'; import { toExpressionAst } from './to_ast'; +import { BasicVislibParams } from './types'; export const histogramVisTypeDefinition: BaseVisTypeOptions = { - name: 'histogram', - title: i18n.translate('visTypeVislib.histogram.histogramTitle', { - defaultMessage: 'Vertical bar', - }), - icon: 'visBarVertical', - description: i18n.translate('visTypeVislib.histogram.histogramDescription', { - defaultMessage: 'Present data in vertical bars on an axis.', - }), - getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], + ...(xyVisTypes.histogram() as BaseVisTypeOptions), toExpressionAst, - visConfig: { - defaults: { - type: 'histogram', - grid: { - categoryLines: false, - }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: AxisTypes.CATEGORY, - position: Positions.BOTTOM, - show: true, - style: {}, - scale: { - type: ScaleTypes.LINEAR, - }, - labels: { - show: true, - filter: true, - truncate: 100, - }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: AxisTypes.VALUE, - position: Positions.LEFT, - show: true, - style: {}, - scale: { - type: ScaleTypes.LINEAR, - mode: AxisModes.NORMAL, - }, - labels: { - show: true, - rotate: Rotates.HORIZONTAL, - filter: false, - truncate: 100, - }, - title: { - text: countLabel, - }, - }, - ], - seriesParams: [ - { - show: true, - type: ChartTypes.HISTOGRAM, - mode: ChartModes.STACKED, - data: { - label: countLabel, - id: '1', - }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - lineWidth: 2, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: Positions.RIGHT, - times: [], - addTimeMarker: false, - labels: { - show: false, - }, - thresholdLine: { - show: false, - value: 10, - width: 1, - style: ThresholdLineStyles.FULL, - color: euiPaletteColorBlind()[9], - }, - }, - }, - editorConfig: { - collections: getConfigCollections(), - optionTabs: getAreaOptionTabs(), - schemas: new Schemas([ - { - group: AggGroupNames.Metrics, - name: 'metric', - title: i18n.translate('visTypeVislib.histogram.metricTitle', { - defaultMessage: 'Y-axis', - }), - min: 1, - aggFilter: ['!geo_centroid', '!geo_bounds'], - defaults: [{ schema: 'metric', type: 'count' }], - }, - { - group: AggGroupNames.Metrics, - name: 'radius', - title: i18n.translate('visTypeVislib.histogram.radiusTitle', { - defaultMessage: 'Dot size', - }), - min: 0, - max: 1, - aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality'], - }, - { - group: AggGroupNames.Buckets, - name: 'segment', - title: i18n.translate('visTypeVislib.histogram.segmentTitle', { - defaultMessage: 'X-axis', - }), - min: 0, - max: 1, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'group', - title: i18n.translate('visTypeVislib.histogram.groupTitle', { - defaultMessage: 'Split series', - }), - min: 0, - max: 3, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'split', - title: i18n.translate('visTypeVislib.histogram.splitTitle', { - defaultMessage: 'Split chart', - }), - min: 0, - max: 1, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - ]), - }, + visualization: undefined, }; diff --git a/src/plugins/vis_type_vislib/public/horizontal_bar.ts b/src/plugins/vis_type_vislib/public/horizontal_bar.ts index 144e63224533..9e919c66cb36 100644 --- a/src/plugins/vis_type_vislib/public/horizontal_bar.ts +++ b/src/plugins/vis_type_vislib/public/horizontal_bar.ts @@ -17,171 +17,14 @@ * under the License. */ -import { i18n } from '@kbn/i18n'; -// @ts-ignore -import { palettes, euiPaletteColorBlind } from '@elastic/eui/lib/services'; +import { xyVisTypes } from '../../vis_type_xy/public'; +import { BaseVisTypeOptions } from '../../visualizations/public'; -import { AggGroupNames } from '../../data/public'; -import { Schemas } from '../../vis_default_editor/public'; -import { - Positions, - ChartTypes, - ChartModes, - AxisTypes, - ScaleTypes, - AxisModes, - ThresholdLineStyles, - getConfigCollections, -} from './utils/collections'; -import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { Rotates } from '../../charts/public'; -import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; -import { BasicVislibParams } from './types'; import { toExpressionAst } from './to_ast'; +import { BasicVislibParams } from './types'; export const horizontalBarVisTypeDefinition: BaseVisTypeOptions = { - name: 'horizontal_bar', - title: i18n.translate('visTypeVislib.horizontalBar.horizontalBarTitle', { - defaultMessage: 'Horizontal bar', - }), - icon: 'visBarHorizontal', - description: i18n.translate('visTypeVislib.horizontalBar.horizontalBarDescription', { - defaultMessage: 'Present data in horizontal bars on an axis.', - }), - getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], + ...(xyVisTypes.horizontalBar() as BaseVisTypeOptions), toExpressionAst, - visConfig: { - defaults: { - type: 'histogram', - grid: { - categoryLines: false, - }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: AxisTypes.CATEGORY, - position: Positions.LEFT, - show: true, - style: {}, - scale: { - type: ScaleTypes.LINEAR, - }, - labels: { - show: true, - rotate: Rotates.HORIZONTAL, - filter: false, - truncate: 200, - }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: AxisTypes.VALUE, - position: Positions.BOTTOM, - show: true, - style: {}, - scale: { - type: ScaleTypes.LINEAR, - mode: AxisModes.NORMAL, - }, - labels: { - show: true, - rotate: Rotates.ANGLED, - filter: true, - truncate: 100, - }, - title: { - text: countLabel, - }, - }, - ], - seriesParams: [ - { - show: true, - type: ChartTypes.HISTOGRAM, - mode: ChartModes.NORMAL, - data: { - label: countLabel, - id: '1', - }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - lineWidth: 2, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: Positions.RIGHT, - times: [], - addTimeMarker: false, - labels: {}, - thresholdLine: { - show: false, - value: 10, - width: 1, - style: ThresholdLineStyles.FULL, - color: euiPaletteColorBlind()[9], - }, - }, - }, - editorConfig: { - collections: getConfigCollections(), - optionTabs: getAreaOptionTabs(), - schemas: new Schemas([ - { - group: AggGroupNames.Metrics, - name: 'metric', - title: i18n.translate('visTypeVislib.horizontalBar.metricTitle', { - defaultMessage: 'Y-axis', - }), - min: 1, - aggFilter: ['!geo_centroid', '!geo_bounds'], - defaults: [{ schema: 'metric', type: 'count' }], - }, - { - group: AggGroupNames.Metrics, - name: 'radius', - title: i18n.translate('visTypeVislib.horizontalBar.radiusTitle', { - defaultMessage: 'Dot size', - }), - min: 0, - max: 1, - aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality'], - }, - { - group: AggGroupNames.Buckets, - name: 'segment', - title: i18n.translate('visTypeVislib.horizontalBar.segmentTitle', { - defaultMessage: 'X-axis', - }), - min: 0, - max: 1, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'group', - title: i18n.translate('visTypeVislib.horizontalBar.groupTitle', { - defaultMessage: 'Split series', - }), - min: 0, - max: 3, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'split', - title: i18n.translate('visTypeVislib.horizontalBar.splitTitle', { - defaultMessage: 'Split chart', - }), - min: 0, - max: 1, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - ]), - }, + visualization: undefined, }; diff --git a/src/plugins/vis_type_vislib/public/line.ts b/src/plugins/vis_type_vislib/public/line.ts index ffa40c8c2998..15f20edd359d 100644 --- a/src/plugins/vis_type_vislib/public/line.ts +++ b/src/plugins/vis_type_vislib/public/line.ts @@ -17,164 +17,14 @@ * under the License. */ -import { i18n } from '@kbn/i18n'; -// @ts-ignore -import { palettes, euiPaletteColorBlind } from '@elastic/eui/lib/services'; +import { xyVisTypes } from '../../vis_type_xy/public'; +import { BaseVisTypeOptions } from '../../visualizations/public'; -import { AggGroupNames } from '../../data/public'; -import { Schemas } from '../../vis_default_editor/public'; -import { - Positions, - ChartTypes, - ChartModes, - AxisTypes, - ScaleTypes, - AxisModes, - ThresholdLineStyles, - InterpolationModes, - getConfigCollections, -} from './utils/collections'; -import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { Rotates } from '../../charts/public'; -import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; import { toExpressionAst } from './to_ast'; import { BasicVislibParams } from './types'; export const lineVisTypeDefinition: BaseVisTypeOptions = { - name: 'line', - title: i18n.translate('visTypeVislib.line.lineTitle', { defaultMessage: 'Line' }), - icon: 'visLine', - description: i18n.translate('visTypeVislib.line.lineDescription', { - defaultMessage: 'Display data as a series of points.', - }), - getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], + ...(xyVisTypes.line() as BaseVisTypeOptions), toExpressionAst, - visConfig: { - defaults: { - type: 'line', - grid: { - categoryLines: false, - }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: AxisTypes.CATEGORY, - position: Positions.BOTTOM, - show: true, - style: {}, - scale: { - type: ScaleTypes.LINEAR, - }, - labels: { - show: true, - filter: true, - truncate: 100, - }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: AxisTypes.VALUE, - position: Positions.LEFT, - show: true, - style: {}, - scale: { - type: ScaleTypes.LINEAR, - mode: AxisModes.NORMAL, - }, - labels: { - show: true, - rotate: Rotates.HORIZONTAL, - filter: false, - truncate: 100, - }, - title: { - text: countLabel, - }, - }, - ], - seriesParams: [ - { - show: true, - type: ChartTypes.LINE, - mode: ChartModes.NORMAL, - data: { - label: countLabel, - id: '1', - }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - lineWidth: 2, - interpolate: InterpolationModes.LINEAR, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: Positions.RIGHT, - times: [], - addTimeMarker: false, - labels: {}, - thresholdLine: { - show: false, - value: 10, - width: 1, - style: ThresholdLineStyles.FULL, - color: euiPaletteColorBlind()[9], - }, - }, - }, - editorConfig: { - collections: getConfigCollections(), - optionTabs: getAreaOptionTabs(), - schemas: new Schemas([ - { - group: AggGroupNames.Metrics, - name: 'metric', - title: i18n.translate('visTypeVislib.line.metricTitle', { defaultMessage: 'Y-axis' }), - min: 1, - aggFilter: ['!geo_centroid', '!geo_bounds'], - defaults: [{ schema: 'metric', type: 'count' }], - }, - { - group: AggGroupNames.Metrics, - name: 'radius', - title: i18n.translate('visTypeVislib.line.radiusTitle', { defaultMessage: 'Dot size' }), - min: 0, - max: 1, - aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality', 'top_hits'], - }, - { - group: AggGroupNames.Buckets, - name: 'segment', - title: i18n.translate('visTypeVislib.line.segmentTitle', { defaultMessage: 'X-axis' }), - min: 0, - max: 1, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'group', - title: i18n.translate('visTypeVislib.line.groupTitle', { - defaultMessage: 'Split series', - }), - min: 0, - max: 3, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'split', - title: i18n.translate('visTypeVislib.line.splitTitle', { - defaultMessage: 'Split chart', - }), - min: 0, - max: 1, - aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], - }, - ]), - }, + visualization: undefined, }; diff --git a/src/plugins/vis_type_vislib/public/pie.ts b/src/plugins/vis_type_vislib/public/pie.ts index 41b271054d59..aa5a3ceaaba9 100644 --- a/src/plugins/vis_type_vislib/public/pie.ts +++ b/src/plugins/vis_type_vislib/public/pie.ts @@ -18,13 +18,15 @@ */ import { i18n } from '@kbn/i18n'; +import { Position } from '@elastic/charts'; import { AggGroupNames } from '../../data/public'; import { Schemas } from '../../vis_default_editor/public'; -import { PieOptions } from './components/options'; -import { getPositions, Positions } from './utils/collections'; +import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; +import { getPositions } from '../../vis_type_xy/public'; + import { CommonVislibParams } from './types'; -import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { PieOptions } from './editor'; import { toExpressionAst } from './to_ast_pie'; export interface PieVisParams extends CommonVislibParams { @@ -52,7 +54,7 @@ export const pieVisTypeDefinition: BaseVisTypeOptions = { type: 'pie', addTooltip: true, addLegend: true, - legendPosition: Positions.RIGHT, + legendPosition: Position.Right, isDonut: true, labels: { show: false, diff --git a/src/plugins/vis_type_vislib/public/pie_fn.ts b/src/plugins/vis_type_vislib/public/pie_fn.ts index 00aa73128c34..8b16d8eb0982 100644 --- a/src/plugins/vis_type_vislib/public/pie_fn.ts +++ b/src/plugins/vis_type_vislib/public/pie_fn.ts @@ -24,6 +24,7 @@ import { ExpressionFunctionDefinition, Datatable, Render } from '../../expressio // @ts-ignore import { vislibSlicesResponseHandler } from './vislib/response_handler'; import { PieVisParams } from './pie'; +import { VislibChartType } from './types'; import { vislibVisName } from './vis_type_vislib_vis_fn'; export const vislibPieName = 'vislib_pie_vis'; @@ -32,9 +33,9 @@ interface Arguments { visConfig: string; } -interface RenderValue { +export interface PieRenderValue { + visType: Extract; visData: unknown; - visType: string; visConfig: PieVisParams; } @@ -42,7 +43,7 @@ export type VisTypeVislibPieExpressionFunctionDefinition = ExpressionFunctionDef typeof vislibPieName, Datatable, Arguments, - Render + Render >; export const createPieVisFn = (): VisTypeVislibPieExpressionFunctionDefinition => ({ @@ -73,7 +74,7 @@ export const createPieVisFn = (): VisTypeVislibPieExpressionFunctionDefinition = value: { visData, visConfig, - visType: 'pie', + visType: VislibChartType.Pie, }, }; }, diff --git a/src/plugins/vis_type_vislib/public/plugin.ts b/src/plugins/vis_type_vislib/public/plugin.ts index f183042fd520..0f849c183323 100644 --- a/src/plugins/vis_type_vislib/public/plugin.ts +++ b/src/plugins/vis_type_vislib/public/plugin.ts @@ -19,25 +19,28 @@ 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 { BaseVisTypeOptions, VisualizationsSetup } from '../../visualizations/public'; -import { createVisTypeVislibVisFn } from './vis_type_vislib_vis_fn'; -import { createPieVisFn } from './pie_fn'; -import { visLibVisTypeDefinitions, pieVisTypeDefinition } from './vis_type_vislib_vis_types'; +import { VisualizationsSetup } from '../../visualizations/public'; import { ChartsPluginSetup } from '../../charts/public'; import { DataPublicPluginStart } from '../../data/public'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; +import { LEGACY_CHARTS_LIBRARY } from '../../vis_type_xy/public'; + +import { createVisTypeVislibVisFn } from './vis_type_vislib_vis_fn'; +import { createPieVisFn } from './pie_fn'; +import { + convertedTypeDefinitions, + pieVisTypeDefinition, + visLibVisTypeDefinitions, +} from './vis_type_vislib_vis_types'; import { setFormatService, setDataActions } from './services'; import { getVislibVisRenderer } from './vis_renderer'; -import { BasicVislibParams } from './types'; /** @internal */ export interface VisTypeVislibPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; charts: ChartsPluginSetup; - visTypeXy?: VisTypeXyPluginSetup; } /** @internal */ @@ -56,23 +59,21 @@ export class VisTypeVislibPlugin public async setup( core: VisTypeVislibCoreSetup, - { expressions, visualizations, charts, visTypeXy }: VisTypeVislibPluginSetupDependencies + { expressions, visualizations, charts }: VisTypeVislibPluginSetupDependencies ) { - // if visTypeXy plugin is disabled it's config will be undefined - if (!visTypeXy) { - const convertedTypes: Array> = []; - const convertedFns: any[] = []; - - // Register legacy vislib types that have been converted - convertedFns.forEach(expressions.registerFunction); - convertedTypes.forEach(visualizations.createBaseVisualization); + if (!core.uiSettings.get(LEGACY_CHARTS_LIBRARY, false)) { + // Register only non-replaced vis types + convertedTypeDefinitions.forEach(visualizations.createBaseVisualization); + visualizations.createBaseVisualization(pieVisTypeDefinition); + expressions.registerRenderer(getVislibVisRenderer(core, charts)); + [createVisTypeVislibVisFn(), createPieVisFn()].forEach(expressions.registerFunction); + } else { + // Register all vis types + visLibVisTypeDefinitions.forEach(visualizations.createBaseVisualization); + visualizations.createBaseVisualization(pieVisTypeDefinition); expressions.registerRenderer(getVislibVisRenderer(core, charts)); + [createVisTypeVislibVisFn(), createPieVisFn()].forEach(expressions.registerFunction); } - // Register non-converted types - visLibVisTypeDefinitions.forEach(visualizations.createBaseVisualization); - visualizations.createBaseVisualization(pieVisTypeDefinition); - expressions.registerRenderer(getVislibVisRenderer(core, charts)); - [createVisTypeVislibVisFn(), createPieVisFn()].forEach(expressions.registerFunction); } public start(core: CoreStart, { data }: VisTypeVislibPluginStartDependencies) { diff --git a/src/plugins/vis_type_vislib/public/to_ast.ts b/src/plugins/vis_type_vislib/public/to_ast.ts index 3a05410ff006..30ed2e4ca1bb 100644 --- a/src/plugins/vis_type_vislib/public/to_ast.ts +++ b/src/plugins/vis_type_vislib/public/to_ast.ts @@ -21,14 +21,11 @@ import moment from 'moment'; import { VisToExpressionAst, getVisSchemas } from '../../visualizations/public'; import { buildExpression, buildExpressionFunction } from '../../expressions/public'; +import type { Dimensions, DateHistogramParams, HistogramParams } from '../../vis_type_xy/public'; +import { BUCKET_TYPES } from '../../data/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 { BasicVislibParams, VislibChartType } from './types'; import { getEsaggsFn } from './to_ast_esaggs'; export const toExpressionAst: VisToExpressionAst = async (vis, params) => { @@ -47,7 +44,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis if (dimensions.x) { const xAgg = responseAggs[dimensions.x.accessor] as any; - if (xAgg.type.name === 'date_histogram') { + if (xAgg.type.name === BUCKET_TYPES.DATE_HISTOGRAM) { (dimensions.x.params as DateHistogramParams).date = true; const { esUnit, esValue } = xAgg.buckets.getInterval(); (dimensions.x.params as DateHistogramParams).intervalESUnit = esUnit; @@ -57,7 +54,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis .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') { + } else if (xAgg.type.name === BUCKET_TYPES.HISTOGRAM) { const intervalParam = xAgg.type.paramByName('interval'); const output = { params: {} as any }; await intervalParam.modifyAggConfigOnSearchRequestStart(xAgg, vis.data.searchSource, { @@ -88,15 +85,15 @@ export const toExpressionAst: VisToExpressionAst = async (vis visConfig.dimensions = dimensions; - const visTypeXy = buildExpressionFunction( + const visTypeVislib = buildExpressionFunction( vislibVisName, { - type: vis.type.name, + type: vis.type.name as Exclude, visConfig: JSON.stringify(visConfig), } ); - const ast = buildExpression([getEsaggsFn(vis), visTypeXy]); + const ast = buildExpression([getEsaggsFn(vis), visTypeVislib]); return ast.toAst(); }; diff --git a/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts b/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts index 2835e5cc1c25..d23f1ab3626d 100644 --- a/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts +++ b/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts @@ -29,6 +29,8 @@ import { BasicVislibParams } from './types'; /** * Get esaggs expressions function + * TODO: replace this with vis.data.aggs!.toExpressionAst(); + * https://github.com/elastic/kibana/issues/61768 * @param vis */ export function getEsaggsFn(vis: Vis | Vis) { diff --git a/src/plugins/vis_type_vislib/public/types.ts b/src/plugins/vis_type_vislib/public/types.ts index c0311edf7615..4f6c42766932 100644 --- a/src/plugins/vis_type_vislib/public/types.ts +++ b/src/plugins/vis_type_vislib/public/types.ts @@ -17,87 +17,71 @@ * under the License. */ -import { TimeMarker } from './vislib/visualizations/time_marker'; +import { $Values } from '@kbn/utility-types'; +import { Position } from '@elastic/charts'; + +import { Labels } from '../../charts/public'; import { - Positions, - ChartModes, - ChartTypes, - AxisModes, - AxisTypes, - InterpolationModes, - ScaleTypes, - ThresholdLineStyles, -} from './utils/collections'; -import { Labels, Style } from '../../charts/public'; -import { Dimensions } from './vislib/helpers/point_series/point_series'; + CategoryAxis, + Dimensions, + Grid, + SeriesParam, + ThresholdLine, + ValueAxis, +} from '../../vis_type_xy/public'; +import { TimeMarker } from './vislib/visualizations/time_marker'; + +/** + * Gauge title alignment + */ +export const Alignment = Object.freeze({ + Automatic: 'automatic' as const, + Horizontal: 'horizontal' as const, + Vertical: 'vertical' as const, +}); +export type Alignment = $Values; + +export const GaugeType = Object.freeze({ + Arc: 'Arc' as const, + Circle: 'Circle' as const, +}); +export type GaugeType = $Values; + +export const VislibChartType = Object.freeze({ + Histogram: 'histogram' as const, + HorizontalBar: 'horizontal_bar' as const, + Line: 'line' as const, + Pie: 'pie' as const, + Area: 'area' as const, + PointSeries: 'point_series' as const, + Heatmap: 'heatmap' as const, + Gauge: 'gauge' as const, + Goal: 'goal' as const, + Metric: 'metric' as const, +}); +export type VislibChartType = $Values; export interface CommonVislibParams { addTooltip: boolean; addLegend: boolean; - legendPosition: Positions; + legendPosition: Position; dimensions: Dimensions; } -export interface Scale { - boundsMargin?: number | ''; - defaultYExtents?: boolean; - max?: number | null; - min?: number | null; - mode?: AxisModes; - setYExtents?: boolean; - type: ScaleTypes; -} - -interface ThresholdLine { - show: boolean; - value: number | null; - width: number | null; - style: ThresholdLineStyles; - color: string; -} - -export interface Axis { - id: string; - labels: Labels; - position: Positions; - scale: Scale; - show: boolean; - style: Style; - title: { text: string }; - type: AxisTypes; -} - -export interface ValueAxis extends Axis { - name: string; -} - -export interface SeriesParam { - data: { label: string; id: string }; - drawLinesBetweenPoints: boolean; - interpolate: InterpolationModes; - lineWidth?: number; - mode: ChartModes; - show: boolean; - showCircles: boolean; - type: ChartTypes; - valueAxis: string; -} - export interface BasicVislibParams extends CommonVislibParams { + type: VislibChartType; + addLegend: boolean; addTimeMarker: boolean; - categoryAxes: Axis[]; + categoryAxes: CategoryAxis[]; orderBucketsBySum?: boolean; labels: Labels; thresholdLine: ThresholdLine; valueAxes: ValueAxis[]; + grid: Grid; gauge?: { percentageMode: boolean; }; - grid: { - categoryLines: boolean; - valueAxis?: string; - }; seriesParams: SeriesParam[]; times: TimeMarker[]; - type: string; + radiusRatio: number; } diff --git a/src/plugins/vis_type_vislib/public/utils/collections.ts b/src/plugins/vis_type_vislib/public/utils/collections.ts deleted file mode 100644 index 44df4864bfd6..000000000000 --- a/src/plugins/vis_type_vislib/public/utils/collections.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { $Values } from '@kbn/utility-types'; - -import { colorSchemas, Rotates } from '../../../charts/public'; - -export const Positions = Object.freeze({ - RIGHT: 'right' as 'right', - LEFT: 'left' as 'left', - TOP: 'top' as 'top', - BOTTOM: 'bottom' as 'bottom', -}); -export type Positions = $Values; - -const getPositions = () => [ - { - text: i18n.translate('visTypeVislib.legendPositions.topText', { - defaultMessage: 'Top', - }), - value: Positions.TOP, - }, - { - text: i18n.translate('visTypeVislib.legendPositions.leftText', { - defaultMessage: 'Left', - }), - value: Positions.LEFT, - }, - { - text: i18n.translate('visTypeVislib.legendPositions.rightText', { - defaultMessage: 'Right', - }), - value: Positions.RIGHT, - }, - { - text: i18n.translate('visTypeVislib.legendPositions.bottomText', { - defaultMessage: 'Bottom', - }), - value: Positions.BOTTOM, - }, -]; - -export const ChartTypes = Object.freeze({ - LINE: 'line' as 'line', - AREA: 'area' as 'area', - HISTOGRAM: 'histogram' as 'histogram', -}); -export type ChartTypes = $Values; - -const getChartTypes = () => [ - { - text: i18n.translate('visTypeVislib.chartTypes.lineText', { - defaultMessage: 'Line', - }), - value: ChartTypes.LINE, - }, - { - text: i18n.translate('visTypeVislib.chartTypes.areaText', { - defaultMessage: 'Area', - }), - value: ChartTypes.AREA, - }, - { - text: i18n.translate('visTypeVislib.chartTypes.barText', { - defaultMessage: 'Bar', - }), - value: ChartTypes.HISTOGRAM, - }, -]; - -export const ChartModes = Object.freeze({ - NORMAL: 'normal' as 'normal', - STACKED: 'stacked' as 'stacked', -}); -export type ChartModes = $Values; - -const getChartModes = () => [ - { - text: i18n.translate('visTypeVislib.chartModes.normalText', { - defaultMessage: 'Normal', - }), - value: ChartModes.NORMAL, - }, - { - text: i18n.translate('visTypeVislib.chartModes.stackedText', { - defaultMessage: 'Stacked', - }), - value: ChartModes.STACKED, - }, -]; - -export const InterpolationModes = Object.freeze({ - LINEAR: 'linear' as 'linear', - CARDINAL: 'cardinal' as 'cardinal', - STEP_AFTER: 'step-after' as 'step-after', -}); -export type InterpolationModes = $Values; - -const getInterpolationModes = () => [ - { - text: i18n.translate('visTypeVislib.interpolationModes.straightText', { - defaultMessage: 'Straight', - }), - value: InterpolationModes.LINEAR, - }, - { - text: i18n.translate('visTypeVislib.interpolationModes.smoothedText', { - defaultMessage: 'Smoothed', - }), - value: InterpolationModes.CARDINAL, - }, - { - text: i18n.translate('visTypeVislib.interpolationModes.steppedText', { - defaultMessage: 'Stepped', - }), - value: InterpolationModes.STEP_AFTER, - }, -]; - -export const AxisTypes = Object.freeze({ - CATEGORY: 'category' as 'category', - VALUE: 'value' as 'value', -}); -export type AxisTypes = $Values; - -export const ScaleTypes = Object.freeze({ - LINEAR: 'linear' as 'linear', - LOG: 'log' as 'log', - SQUARE_ROOT: 'square root' as 'square root', -}); -export type ScaleTypes = $Values; - -const getScaleTypes = () => [ - { - text: i18n.translate('visTypeVislib.scaleTypes.linearText', { - defaultMessage: 'Linear', - }), - value: ScaleTypes.LINEAR, - }, - { - text: i18n.translate('visTypeVislib.scaleTypes.logText', { - defaultMessage: 'Log', - }), - value: ScaleTypes.LOG, - }, - { - text: i18n.translate('visTypeVislib.scaleTypes.squareRootText', { - defaultMessage: 'Square root', - }), - value: ScaleTypes.SQUARE_ROOT, - }, -]; - -export const AxisModes = Object.freeze({ - NORMAL: 'normal' as 'normal', - PERCENTAGE: 'percentage' as 'percentage', - WIGGLE: 'wiggle' as 'wiggle', - SILHOUETTE: 'silhouette' as 'silhouette', -}); -export type AxisModes = $Values; - -const getAxisModes = () => [ - { - text: i18n.translate('visTypeVislib.axisModes.normalText', { - defaultMessage: 'Normal', - }), - value: AxisModes.NORMAL, - }, - { - text: i18n.translate('visTypeVislib.axisModes.percentageText', { - defaultMessage: 'Percentage', - }), - value: AxisModes.PERCENTAGE, - }, - { - text: i18n.translate('visTypeVislib.axisModes.wiggleText', { - defaultMessage: 'Wiggle', - }), - value: AxisModes.WIGGLE, - }, - { - text: i18n.translate('visTypeVislib.axisModes.silhouetteText', { - defaultMessage: 'Silhouette', - }), - value: AxisModes.SILHOUETTE, - }, -]; - -export const ThresholdLineStyles = Object.freeze({ - FULL: 'full' as 'full', - DASHED: 'dashed' as 'dashed', - DOT_DASHED: 'dot-dashed' as 'dot-dashed', -}); -export type ThresholdLineStyles = $Values; - -const getThresholdLineStyles = () => [ - { - value: ThresholdLineStyles.FULL, - text: i18n.translate('visTypeVislib.thresholdLine.style.fullText', { - defaultMessage: 'Full', - }), - }, - { - value: ThresholdLineStyles.DASHED, - text: i18n.translate('visTypeVislib.thresholdLine.style.dashedText', { - defaultMessage: 'Dashed', - }), - }, - { - value: ThresholdLineStyles.DOT_DASHED, - text: i18n.translate('visTypeVislib.thresholdLine.style.dotdashedText', { - defaultMessage: 'Dot-dashed', - }), - }, -]; - -const getRotateOptions = () => [ - { - text: i18n.translate('visTypeVislib.categoryAxis.rotate.horizontalText', { - defaultMessage: 'Horizontal', - }), - value: Rotates.HORIZONTAL, - }, - { - text: i18n.translate('visTypeVislib.categoryAxis.rotate.verticalText', { - defaultMessage: 'Vertical', - }), - value: Rotates.VERTICAL, - }, - { - text: i18n.translate('visTypeVislib.categoryAxis.rotate.angledText', { - defaultMessage: 'Angled', - }), - value: Rotates.ANGLED, - }, -]; - -export const GaugeTypes = Object.freeze({ - ARC: 'Arc' as 'Arc', - CIRCLE: 'Circle' as 'Circle', -}); -export type GaugeTypes = $Values; - -const getGaugeTypes = () => [ - { - text: i18n.translate('visTypeVislib.gauge.gaugeTypes.arcText', { - defaultMessage: 'Arc', - }), - value: GaugeTypes.ARC, - }, - { - text: i18n.translate('visTypeVislib.gauge.gaugeTypes.circleText', { - defaultMessage: 'Circle', - }), - value: GaugeTypes.CIRCLE, - }, -]; - -export const Alignments = Object.freeze({ - AUTOMATIC: 'automatic' as 'automatic', - HORIZONTAL: 'horizontal' as 'horizontal', - VERTICAL: 'vertical' as 'vertical', -}); -export type Alignments = $Values; - -const getAlignments = () => [ - { - text: i18n.translate('visTypeVislib.gauge.alignmentAutomaticTitle', { - defaultMessage: 'Automatic', - }), - value: Alignments.AUTOMATIC, - }, - { - text: i18n.translate('visTypeVislib.gauge.alignmentHorizontalTitle', { - defaultMessage: 'Horizontal', - }), - value: Alignments.HORIZONTAL, - }, - { - text: i18n.translate('visTypeVislib.gauge.alignmentVerticalTitle', { - defaultMessage: 'Vertical', - }), - value: Alignments.VERTICAL, - }, -]; - -const getConfigCollections = () => ({ - legendPositions: getPositions(), - positions: getPositions(), - chartTypes: getChartTypes(), - axisModes: getAxisModes(), - scaleTypes: getScaleTypes(), - chartModes: getChartModes(), - interpolationModes: getInterpolationModes(), - thresholdLineStyles: getThresholdLineStyles(), -}); - -const getGaugeCollections = () => ({ - gaugeTypes: getGaugeTypes(), - alignments: getAlignments(), - colorSchemas, -}); - -const getHeatmapCollections = () => ({ - legendPositions: getPositions(), - scales: getScaleTypes(), - colorSchemas, -}); - -export { - getConfigCollections, - getGaugeCollections, - getHeatmapCollections, - getPositions, - getRotateOptions, - getScaleTypes, - getInterpolationModes, - getChartTypes, - getChartModes, - getAxisModes, -}; diff --git a/src/plugins/vis_type_vislib/public/vis_controller.tsx b/src/plugins/vis_type_vislib/public/vis_controller.tsx index 1804d0d52ae7..2a32d19874c2 100644 --- a/src/plugins/vis_type_vislib/public/vis_controller.tsx +++ b/src/plugins/vis_type_vislib/public/vis_controller.tsx @@ -22,7 +22,7 @@ import React, { RefObject } from 'react'; import { mountReactNode } from '../../../core/public/utils'; import { ChartsPluginSetup } from '../../charts/public'; -import { PersistedState } from '../../visualizations/public'; +import type { PersistedState } from '../../visualizations/public'; import { IInterpreterRenderHandlers } from '../../expressions/public'; import { VisTypeVislibCoreSetup } from './plugin'; @@ -115,7 +115,7 @@ export const createVislibVisController = ( }) .addClass((legendClassName as any)[visParams.legendPosition]); - this.mountLegend(esResponse, visParams, fireEvent, uiState); + this.mountLegend(esResponse, visParams, fireEvent, uiState as PersistedState); } this.vislibVis.render(esResponse, uiState); @@ -128,7 +128,7 @@ export const createVislibVisController = ( CUSTOM_LEGEND_VIS_TYPES.includes(this.vislibVis.visConfigArgs.type) ) { this.unmountLegend?.(); - this.mountLegend(esResponse, visParams, fireEvent, uiState); + this.mountLegend(esResponse, visParams, fireEvent, uiState as PersistedState); this.vislibVis.render(esResponse, uiState); } } diff --git a/src/plugins/vis_type_vislib/public/vis_renderer.tsx b/src/plugins/vis_type_vislib/public/vis_renderer.tsx index 9c697f481e63..205c22092ac6 100644 --- a/src/plugins/vis_type_vislib/public/vis_renderer.tsx +++ b/src/plugins/vis_type_vislib/public/vis_renderer.tsx @@ -26,9 +26,13 @@ import { ChartsPluginSetup } from '../../charts/public'; import { VisTypeVislibCoreSetup } from './plugin'; import { VislibRenderValue, vislibVisName } from './vis_type_vislib_vis_fn'; +import { VislibChartType } from './types'; +import { PieRenderValue } from './pie_fn'; -function shouldShowNoResultsMessage(visData: any, visType: string): boolean { - if (['goal', 'gauge'].includes(visType)) { +const VislibWrapper = lazy(() => import('./vis_wrapper')); + +function shouldShowNoResultsMessage(visData: any, visType: VislibChartType): boolean { + if (['goal', 'gauge'].includes(visType as string)) { return false; } @@ -38,13 +42,12 @@ function shouldShowNoResultsMessage(visData: any, visType: string): boolean { return Boolean(isZeroHits); } -const VislibWrapper = lazy(() => import('./vis_wrapper')); - export const getVislibVisRenderer: ( core: VisTypeVislibCoreSetup, charts: ChartsPluginSetup -) => ExpressionRenderDefinition = (core, charts) => ({ +) => ExpressionRenderDefinition = (core, charts) => ({ name: vislibVisName, + displayName: 'Vislib visualization', reuseDomNode: true, render: async (domNode, config, handlers) => { const showNoResult = shouldShowNoResultsMessage(config.visData, config.visType); 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 dc4a6314fb01..d627b8587882 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 @@ -23,18 +23,18 @@ import { ExpressionFunctionDefinition, Datatable, Render } from '../../expressio // @ts-ignore import { vislibSeriesResponseHandler } from './vislib/response_handler'; -import { BasicVislibParams } from './types'; +import { BasicVislibParams, VislibChartType } from './types'; export const vislibVisName = 'vislib_vis'; interface Arguments { - type: string; + type: Exclude; visConfig: string; } export interface VislibRenderValue { - visData: any; - visType: string; + visType: Exclude; + visData: unknown; visConfig: BasicVislibParams; } @@ -65,7 +65,7 @@ export const createVisTypeVislibVisFn = (): VisTypeVislibExpressionFunctionDefin }, }, fn(context, args, handlers) { - const visType = args.type; + const visType = args.type as Exclude; const visConfig = JSON.parse(args.visConfig) as BasicVislibParams; const visData = vislibSeriesResponseHandler(context, visConfig.dimensions); 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 1b43a213c618..28415e3e2fa8 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 @@ -36,3 +36,9 @@ export const visLibVisTypeDefinitions = [ gaugeVisTypeDefinition, goalVisTypeDefinition, ]; + +export const convertedTypeDefinitions = [ + heatmapVisTypeDefinition, + gaugeVisTypeDefinition, + goalVisTypeDefinition, +]; diff --git a/src/plugins/vis_type_vislib/public/vis_wrapper.tsx b/src/plugins/vis_type_vislib/public/vis_wrapper.tsx index 980ba1c17588..e2e8a98a9a8b 100644 --- a/src/plugins/vis_type_vislib/public/vis_wrapper.tsx +++ b/src/plugins/vis_type_vislib/public/vis_wrapper.tsx @@ -22,15 +22,17 @@ import { EuiResizeObserver } from '@elastic/eui'; import { debounce } from 'lodash'; import { IInterpreterRenderHandlers } from '../../expressions/public'; +import type { PersistedState } from '../../visualizations/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 { PieRenderValue } from './pie_fn'; import './index.scss'; -type VislibWrapperProps = VislibRenderValue & { +type VislibWrapperProps = (VislibRenderValue | PieRenderValue) & { core: VisTypeVislibCoreSetup; charts: ChartsPluginSetup; handlers: IInterpreterRenderHandlers; @@ -59,16 +61,18 @@ const VislibWrapper = ({ core, charts, visData, visConfig, handlers }: VislibWra visController.current?.destroy(); visController.current = null; }; - }, [core, charts, handlers]); + }, [core, charts]); useEffect(updateChart, [updateChart]); useEffect(() => { if (handlers.uiState) { - handlers.uiState.on('change', updateChart); + const uiState = handlers.uiState as PersistedState; + + uiState.on('change', updateChart); return () => { - handlers.uiState?.off('change', updateChart); + uiState?.off('change', updateChart); }; } }, [handlers.uiState, updateChart]); 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 a06f0cb00787..cb63811800c2 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 @@ -3,8 +3,6 @@ // NOTE: Some of the styles attempt to align with the TSVB legend $visLegendWidth: 150px; -$visColorPickerWidth: $euiSizeM * 10; -$visLegendLineHeight: $euiSize; .visLegend__toggle { border-radius: $euiBorderRadius; @@ -81,20 +79,3 @@ $visLegendLineHeight: $euiSize; visibility: hidden; } } - -.visLegend__valueColorPicker { - width: ($euiSizeL * 8); // 8 columns -} - -.visLegend__valueColorPickerDot { - cursor: pointer; - - &:hover { - transform: scale(1.4); - } - - &-isSelected { - border: $euiSizeXS solid; - border-radius: 100%; - } -} 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 7acc97404c11..5b1a2b397536 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 @@ -243,7 +243,7 @@ describe('VisLegend Component', () => { const first = getLegendItems(wrapper).first(); first.simulate('click'); - expect(wrapper.exists('.visLegend__valueDetails')).toBe(true); + expect(wrapper.exists('.visColorPicker')).toBe(true); }); }); @@ -256,8 +256,8 @@ describe('VisLegend Component', () => { const first = getLegendItems(wrapper).first(); first.simulate('click'); - const popover = wrapper.find('.visLegend__valueDetails').first(); - const firstColor = popover.find('.visLegend__valueColorPickerDot').first(); + const popover = wrapper.find('.visColorPicker').first(); + const firstColor = popover.find('.visColorPicker__valueDot').first(); firstColor.simulate('click'); const colors = mockState.get('vis.colors'); 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 cec97f0cadf1..5065642d88c6 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 @@ -78,18 +78,20 @@ export class VisLegend extends PureComponent { }); }; - setColor = (label: string, color: string) => (event: BaseSyntheticEvent) => { + setColor = (label: string | number, color: string | null, event: BaseSyntheticEvent) => { if ((event as KeyboardEvent).key && (event as KeyboardEvent).key !== keys.ENTER) { return; } - 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.refresh(); + this.setState({ selectedLabel: null }, () => { + const colors = this.props.uiState?.get('vis.colors') || {}; + if (colors[label] === color || !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.refresh(); + }); }; filter = ({ values: data }: LegendItem, negate: boolean) => { diff --git a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx index 39e6fb2d2aff..6c7e343a22d8 100644 --- a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx +++ b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx @@ -18,10 +18,8 @@ */ import React, { memo, useState, BaseSyntheticEvent, KeyboardEvent } from 'react'; -import classNames from 'classnames'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; import { EuiPopover, keys, @@ -33,7 +31,8 @@ import { EuiButtonGroupOptionProps, } from '@elastic/eui'; -import { legendColors, LegendItem } from './models'; +import { LegendItem } from './models'; +import { ColorPicker } from '../../../../../charts/public'; interface Props { item: LegendItem; @@ -45,7 +44,7 @@ interface Props { onSelect: (label: string | null) => (event?: BaseSyntheticEvent) => void; onHighlight: (event: BaseSyntheticEvent) => void; onUnhighlight: (event: BaseSyntheticEvent) => void; - setColor: (label: string, color: string) => (event: BaseSyntheticEvent) => void; + setColor: (label: string, color: string | null, event: BaseSyntheticEvent) => void; getColor: (label: string) => string; } @@ -159,40 +158,14 @@ const VisLegendItemComponent = ({ closePopover={onSelect(null)} panelPaddingSize="s" > -
- {canFilter && renderFilterBar()} + {canFilter && renderFilterBar()} -
- - - - {legendColors.map((color) => ( - - ))} -
-
+ setColor(item.label, c, e)} + /> ); diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts index ae6b365efc0c..1b51fb8a53d1 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts @@ -17,9 +17,10 @@ * under the License. */ +import type { Dimension } from '../../../../../vis_type_xy/public'; + import { addToSiri, Serie } from './_add_to_siri'; import { Point } from './_get_point'; -import { Dimension } from './point_series'; describe('addToSiri', function () { it('creates a new series the first time it sees an id', function () { diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts index 5e5185d6c31a..2e04e916e85f 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts @@ -17,8 +17,10 @@ * under the License. */ +import { getAggId } from '../../../../../vis_type_xy/public'; +import type { Dimension } from '../../../../../vis_type_xy/public'; + import { Point } from './_get_point'; -import { Dimension } from './point_series'; export interface Serie { id: string; @@ -48,7 +50,7 @@ export function addToSiri( } series.set(id, { - id: id.split('-').pop() as string, + id: getAggId(id), rawId: id, label: yLabel == null ? id : yLabel, count: 0, diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts index fb14b04357f8..5efde6342757 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts @@ -17,8 +17,10 @@ * under the License. */ +import type { Dimension, Dimensions } from '../../../../../vis_type_xy/public'; + import { getAspects } from './_get_aspects'; -import { Dimension, Dimensions, Aspect } from './point_series'; +import { Aspect } from './point_series'; import { Table, Row } from '../../types'; describe('getAspects', function () { diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts index 87819aa9b2a5..e4094a454984 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts @@ -17,8 +17,10 @@ * under the License. */ +import type { Dimensions } from '../../../../../vis_type_xy/public'; + import { makeFakeXAspect } from './_fake_x_aspect'; -import { Dimensions, Aspects } from './point_series'; +import { Aspects } from './point_series'; import { Table } from '../../types'; /** diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts index be44975bd4eb..03d41096a8c6 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts @@ -18,6 +18,7 @@ */ import { IFieldFormatsRegistry } from '../../../../../data/common'; + import { getPoint } from './_get_point'; import { setFormatService } from '../../../services'; import { Aspect } from './point_series'; @@ -94,7 +95,12 @@ describe('getPoint', function () { it('should call deserialize', function () { const seriesAspect = [ - { accessor: '1', format: { id: 'number', params: { pattern: '$' } } } as Aspect, + { + title: 'series', + accessor: '1', + format: { id: 'number', params: { pattern: '$' } }, + params: {}, + } as Aspect, ]; getPoint(table, xAspect, seriesAspect, row, 0, yAspect); diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts index 3f0560c2c9f2..aa24530b025d 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts @@ -18,16 +18,12 @@ */ import moment from 'moment'; + +import type { DateHistogramParams, HistogramParams } from '../../../../../vis_type_xy/public'; + import { initXAxis } from './_init_x_axis'; import { makeFakeXAspect } from './_fake_x_aspect'; -import { - Aspects, - Chart, - DateHistogramOrdered, - DateHistogramParams, - HistogramOrdered, - HistogramParams, -} from './point_series'; +import { Aspects, Chart, DateHistogramOrdered, HistogramOrdered } from './point_series'; import { Table, Column } from '../../types'; describe('initXAxis', function () { @@ -110,7 +106,7 @@ describe('initXAxis', function () { it('reads the date interval param from the x agg', function () { const dateHistogramParams = chart.aspects.x[0].params as DateHistogramParams; - dateHistogramParams.interval = 'P1D'; + dateHistogramParams.interval = moment.duration(1, 'd').asMilliseconds(); dateHistogramParams.intervalESValue = 1; dateHistogramParams.intervalESUnit = 'd'; dateHistogramParams.date = true; diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts index b2e4d6e4b40c..7dd1dd259f78 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts @@ -19,8 +19,11 @@ import moment from 'moment'; import _ from 'lodash'; + +import type { DateHistogramParams } from '../../../../../vis_type_xy/public/types'; + import { orderedDateAxis } from './_ordered_date_axis'; -import { DateHistogramParams, OrderedChart } from './point_series'; +import { OrderedChart } from './point_series'; describe('orderedDateAxis', function () { const baseArgs = { diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts index 2a5ab197c9ab..7c343af7840e 100644 --- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts +++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts @@ -18,7 +18,10 @@ */ import _ from 'lodash'; -import { buildPointSeriesData, Dimensions } from './point_series'; + +import type { Dimensions } from '../../../../../vis_type_xy/public'; + +import { buildPointSeriesData } from './point_series'; import { Table, Column } from '../../types'; import { setFormatService } from '../../../services'; import { Serie } from './_add_to_siri'; 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 f40d01e6a812..2bc669e0b77a 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 @@ -18,6 +18,14 @@ */ import { Duration } from 'moment'; + +import type { + Dimension, + Dimensions, + DateHistogramParams, + HistogramParams, +} from '../../../../../vis_type_xy/public'; + import { getSeries } from './_get_series'; import { getAspects } from './_get_aspects'; import { initYAxis } from './_init_y_axis'; @@ -26,41 +34,6 @@ import { orderedDateAxis } from './_ordered_date_axis'; import { Serie } from './_add_to_siri'; import { Column, Table } from '../../types'; -export interface DateHistogramParams { - date: boolean; - interval: number | string; - intervalESValue: number; - intervalESUnit: string; - format: string; - bounds?: { - min: string | number; - max: string | number; - }; -} -export interface HistogramParams { - interval: number; -} -export interface FakeParams { - defaultValue: string; -} -export interface Dimension { - accessor: number; - format: { - id?: string; - params?: { pattern?: string; [key: string]: any }; - }; - params: DateHistogramParams | HistogramParams | FakeParams | {}; -} - -export interface Dimensions { - x: Dimension | null; - y: Dimension[]; - z?: Dimension[]; - series?: Dimension | Dimension[]; - width?: Dimension[]; - splitRow?: Dimension[]; - splitColumn?: Dimension[]; -} export interface Aspect { accessor: Column['id']; column?: Dimension['accessor']; 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 938ea3adcb9b..e1908a8483fe 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/handler.js +++ b/src/plugins/vis_type_vislib/public/vislib/lib/handler.js @@ -21,15 +21,16 @@ import d3 from 'd3'; import _ from 'lodash'; import MarkdownIt from 'markdown-it'; +import { dispatchRenderComplete } from '../../../../kibana_utils/public'; + +import { visTypes as chartTypes } from '../visualizations/vis_types'; import { NoResults } from '../errors'; import { Layout } from './layout/layout'; import { ChartTitle } from './chart_title'; import { Alerts } from './alerts'; import { Axis } from './axis/axis'; import { ChartGrid as Grid } from './chart_grid'; -import { visTypes as chartTypes } from '../visualizations/vis_types'; import { Binder } from './binder'; -import { dispatchRenderComplete } from '../../../../kibana_utils/public'; const markdownIt = new MarkdownIt({ html: false, diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json index d52cb18727c0..50d6eab03e3f 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json +++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json @@ -31,7 +31,7 @@ }, "params": { "date": true, - "interval": "P1D", + "interval": 86400000, "format": "YYYY-MM-DD", "bounds": { "min": "2019-05-10T04:00:00.000Z", @@ -128,7 +128,7 @@ }, "xAxisLabel": "timestamp per day", "ordered": { - "interval": "P1D", + "interval": 86400000, "date": true, "min": 1557460800000, "max": 1557656337342 diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json index 6e1a70722997..1987c59f6722 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json +++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json @@ -31,7 +31,7 @@ }, "params": { "date": true, - "interval": "P1D", + "interval": 86400000, "format": "YYYY-MM-DD", "bounds": { "min": "2019-05-10T04:00:00.000Z", @@ -128,7 +128,7 @@ }, "xAxisLabel": "timestamp per day", "ordered": { - "interval": "P1D", + "interval": 86400000, "date": true, "min": 1557460800000, "max": 1557656337342 @@ -460,4 +460,4 @@ "50th percentile of AvgTicketPrice" ] } -} \ No newline at end of file +} diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json index f7dd18f5eb71..ae1f3cbf24c3 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json +++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json @@ -32,7 +32,7 @@ }, "params": { "date": true, - "interval": "P1D", + "interval": 86400000, "format": "YYYY-MM-DD", "bounds": { "min": "2019-05-10T04:00:00.000Z", @@ -453,4 +453,4 @@ } ], "enableHover": true -} \ No newline at end of file +} diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json index 02062c987564..f2ee245a8431 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json +++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json @@ -32,7 +32,7 @@ }, "params": { "date": true, - "interval": "P1D", + "interval": 86400000, "format": "YYYY-MM-DD", "bounds": { "min": "2019-05-10T04:00:00.000Z", @@ -455,4 +455,4 @@ } ], "enableHover": true -} \ No newline at end of file +} diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js index a2b830ffaa78..40d15733b418 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js @@ -22,8 +22,8 @@ import { Chart } from './_chart'; import { gaugeTypes } from './gauges/gauge_types'; export class GaugeChart extends Chart { - constructor(handler, chartEl, chartData, deps) { - super(handler, chartEl, chartData, deps); + constructor(handler, chartEl, chartData, uiSettings) { + super(handler, chartEl, chartData, uiSettings); this.gaugeConfig = handler.visConfig.get('gauge', {}); this.gauge = new gaugeTypes[this.gaugeConfig.type](this); } diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js index 456472146476..d725c29eef31 100644 --- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js +++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js @@ -40,8 +40,8 @@ const defaults = { * @param chartData {Object} Elasticsearch query results for this specific chart */ export class HeatmapChart 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/server/ui_settings.ts b/src/plugins/vis_type_vislib/server/ui_settings.ts index a48cbbae3d0c..58564b4055da 100644 --- a/src/plugins/vis_type_vislib/server/ui_settings.ts +++ b/src/plugins/vis_type_vislib/server/ui_settings.ts @@ -24,6 +24,8 @@ import { UiSettingsParams } from 'kibana/server'; import { DIMMING_OPACITY_SETTING, HEATMAP_MAX_BUCKETS_SETTING } from '../common'; export const uiSettings: Record = { + // TODO: move this to vis_type_xy when vislib is removed + // https://github.com/elastic/kibana/issues/56143 [DIMMING_OPACITY_SETTING]: { name: i18n.translate('visTypeVislib.advancedSettings.visualization.dimmingOpacityTitle', { defaultMessage: 'Dimming opacity', diff --git a/src/plugins/vis_type_xy/README.md b/src/plugins/vis_type_xy/README.md index 70ddb21c1e9d..549fc4e3ea18 100644 --- a/src/plugins/vis_type_xy/README.md +++ b/src/plugins/vis_type_xy/README.md @@ -1,2 +1,2 @@ Contains the new xy-axis chart using the elastic-charts library, which will eventually -replace the vislib xy-axis (bar, area, line) charts. \ No newline at end of file +replace the vislib xy-axis charts including bar, area, and line. diff --git a/src/plugins/vis_type_xy/common/index.ts b/src/plugins/vis_type_xy/common/index.ts new file mode 100644 index 000000000000..edee1ea3219d --- /dev/null +++ b/src/plugins/vis_type_xy/common/index.ts @@ -0,0 +1,37 @@ +/* + * 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 { $Values } from '@kbn/utility-types'; + +/** + * Type of charts able to render + */ +export const ChartType = Object.freeze({ + Line: 'line' as const, + Area: 'area' as const, + Histogram: 'histogram' as const, +}); +export type ChartType = $Values; + +/** + * Type of xy visualizations + */ +export type XyVisType = ChartType | 'horizontal_bar'; + +export const LEGACY_CHARTS_LIBRARY = 'visualization:visualize:legacyChartsLibrary'; diff --git a/src/plugins/vis_type_xy/jest.config.js b/src/plugins/vis_type_xy/jest.config.js new file mode 100644 index 000000000000..556e518d4f4e --- /dev/null +++ b/src/plugins/vis_type_xy/jest.config.js @@ -0,0 +1,24 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/src/plugins/vis_type_xy'], +}; diff --git a/src/plugins/vis_type_xy/kibana.json b/src/plugins/vis_type_xy/kibana.json index ca02da45e911..619fa8e71c0d 100644 --- a/src/plugins/vis_type_xy/kibana.json +++ b/src/plugins/vis_type_xy/kibana.json @@ -3,5 +3,6 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["charts", "expressions", "visualizations"] + "requiredPlugins": ["charts", "data", "expressions", "visualizations", "usageCollection"], + "requiredBundles": ["kibanaUtils", "visDefaultEditor"] } diff --git a/src/plugins/vis_type_xy/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_type_xy/public/__snapshots__/to_ast.test.ts.snap new file mode 100644 index 000000000000..e6665c26a281 --- /dev/null +++ b/src/plugins/vis_type_xy/public/__snapshots__/to_ast.test.ts.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`xy 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": "xy_vis", + "removeArgument": [Function], + "replaceArgument": [Function], + "toAst": [Function], + "toString": [Function], + "type": "expression_function_builder", +} +`; diff --git a/src/plugins/vis_type_xy/public/_chart.scss b/src/plugins/vis_type_xy/public/_chart.scss new file mode 100644 index 000000000000..ac9d4ed04aec --- /dev/null +++ b/src/plugins/vis_type_xy/public/_chart.scss @@ -0,0 +1,7 @@ +.xyChart__container { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} diff --git a/src/plugins/vis_type_xy/public/components/_detailed_tooltip.scss b/src/plugins/vis_type_xy/public/components/_detailed_tooltip.scss new file mode 100644 index 000000000000..91b0a8d02329 --- /dev/null +++ b/src/plugins/vis_type_xy/public/components/_detailed_tooltip.scss @@ -0,0 +1,34 @@ +.detailedTooltip { + @include euiToolTipStyle('s'); + pointer-events: none; + max-width: $euiSizeXL * 10; + overflow: hidden; + padding: $euiSizeS; + + table { + td, + th { + text-align: left; + padding: $euiSizeXS; + overflow-wrap: break-word; + word-wrap: break-word; + } + } +} + +.detailedTooltip__header { + > :last-child { + margin-bottom: $euiSizeS; + } +} + +.detailedTooltip__labelContainer, +.detailedTooltip__valueContainer { + overflow-wrap: break-word; + word-wrap: break-word; +} + +.detailedTooltip__label { + font-weight: $euiFontWeightMedium; + color: shade($euiColorGhost, 20%); +} diff --git a/src/plugins/vis_type_xy/public/components/detailed_tooltip.tsx b/src/plugins/vis_type_xy/public/components/detailed_tooltip.tsx new file mode 100644 index 000000000000..3427baed41b8 --- /dev/null +++ b/src/plugins/vis_type_xy/public/components/detailed_tooltip.tsx @@ -0,0 +1,142 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { isNil } from 'lodash'; + +import { + CustomTooltip, + TooltipValue, + TooltipValueFormatter, + XYChartSeriesIdentifier, +} from '@elastic/charts'; + +import { BUCKET_TYPES } from '../../../data/public'; + +import { Aspects } from '../types'; + +import './_detailed_tooltip.scss'; +import { fillEmptyValue } from '../utils/get_series_name_fn'; +import { COMPLEX_SPLIT_ACCESSOR } from '../utils/accessors'; + +interface TooltipData { + label: string; + value: string; +} + +const getTooltipData = ( + aspects: Aspects, + header: TooltipValue | null, + value: TooltipValue +): TooltipData[] => { + const data: TooltipData[] = []; + + if (header) { + const xFormatter = + aspects.x.aggType === BUCKET_TYPES.DATE_RANGE || aspects.x.aggType === BUCKET_TYPES.RANGE + ? null + : aspects.x.formatter; + data.push({ + label: aspects.x.title, + value: xFormatter ? xFormatter(header.value) : `${header.value}`, + }); + } + + const valueSeries = value.seriesIdentifier as XYChartSeriesIdentifier; + const yAccessor = aspects.y.find(({ accessor }) => accessor === valueSeries.yAccessor) ?? null; + + if (yAccessor) { + data.push({ + label: yAccessor.title, + value: yAccessor.formatter ? yAccessor.formatter(value.value) : `${value.value}`, + }); + } + + if (aspects.z && !isNil(value.markValue)) { + data.push({ + label: aspects.z.title, + value: aspects.z.formatter ? aspects.z.formatter(value.markValue) : `${value.markValue}`, + }); + } + + valueSeries.splitAccessors.forEach((splitValue, key) => { + const split = (aspects.series ?? []).find(({ accessor }, i) => { + return accessor === key || key === `${COMPLEX_SPLIT_ACCESSOR}::${i}`; + }); + + if (split) { + data.push({ + label: split?.title, + value: + split?.formatter && !key.toString().startsWith(COMPLEX_SPLIT_ACCESSOR) + ? split?.formatter(splitValue) + : `${splitValue}`, + }); + } + }); + + return data; +}; + +const renderData = ({ label, value: rawValue }: TooltipData, index: number) => { + const value = fillEmptyValue(rawValue); + return label && value ? ( + + +
{label}
+ + + +
{value}
+ + + ) : null; +}; + +export const getDetailedTooltip = (aspects: Aspects) => ( + headerFormatter?: TooltipValueFormatter +): CustomTooltip => { + return function DetailedTooltip({ header, values }) { + // Note: first value is not necessarily the closest value + // To be fixed with https://github.com/elastic/elastic-charts/issues/835 + // TODO: Allow multiple values to be displayed in tooltip + const highlightedValue = values.find(({ isHighlighted }) => isHighlighted); + + if (!highlightedValue) { + return null; + } + + const tooltipData = getTooltipData(aspects, header, highlightedValue); + + if (tooltipData.length === 0) { + return null; + } + + return ( +
+ {headerFormatter && header && ( +
{headerFormatter(header)}
+ )} + + {tooltipData.map(renderData)} +
+
+ ); + }; +}; diff --git a/src/plugins/vis_type_xy/public/components/index.ts b/src/plugins/vis_type_xy/public/components/index.ts new file mode 100644 index 000000000000..d8d55c77b7a8 --- /dev/null +++ b/src/plugins/vis_type_xy/public/components/index.ts @@ -0,0 +1,25 @@ +/* + * 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 { XYAxis } from './xy_axis'; +export { XYEndzones } from './xy_endzones'; +export { XYCurrentTime } from './xy_current_time'; +export { XYSettings } from './xy_settings'; +export { XYThresholdLine } from './xy_threshold_line'; +export { SplitChartWarning } from './split_chart_warning'; diff --git a/src/plugins/vis_type_xy/public/components/split_chart_warning.tsx b/src/plugins/vis_type_xy/public/components/split_chart_warning.tsx new file mode 100644 index 000000000000..7265e70a791a --- /dev/null +++ b/src/plugins/vis_type_xy/public/components/split_chart_warning.tsx @@ -0,0 +1,55 @@ +/* + * 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, { FC } from 'react'; + +import { EuiLink, EuiCallOut } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { getDocLinks } from '../services'; + +export const SplitChartWarning: FC = () => { + const advancedSettingsLink = getDocLinks().links.management.visualizationSettings; + + return ( + + + + + ), + }} + /> + + ); +}; diff --git a/src/plugins/vis_type_xy/public/components/xy_axis.tsx b/src/plugins/vis_type_xy/public/components/xy_axis.tsx new file mode 100644 index 000000000000..b64f2bf1ec0e --- /dev/null +++ b/src/plugins/vis_type_xy/public/components/xy_axis.tsx @@ -0,0 +1,55 @@ +/* + * 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, { FC } from 'react'; + +import { Axis } from '@elastic/charts'; + +import { AxisConfig } from '../types'; + +type XYAxisPros = AxisConfig; + +export const XYAxis: FC = ({ + id, + title, + show, + position, + groupId, + grid, + ticks, + domain, + style, + integersOnly, +}) => ( + +); diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/__mocks__/@elastic/charts.js b/src/plugins/vis_type_xy/public/components/xy_current_time.tsx similarity index 61% rename from src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/__mocks__/@elastic/charts.js rename to src/plugins/vis_type_xy/public/components/xy_current_time.tsx index 19bfe685cac9..66ad4fda3bec 100644 --- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/__mocks__/@elastic/charts.js +++ b/src/plugins/vis_type_xy/public/components/xy_current_time.tsx @@ -17,28 +17,21 @@ * under the License. */ -export const CurveType = { - CURVE_CARDINAL: 0, - CURVE_NATURAL: 1, - CURVE_MONOTONE_X: 2, - CURVE_MONOTONE_Y: 3, - CURVE_BASIS: 4, - CURVE_CATMULL_ROM: 5, - CURVE_STEP: 6, - CURVE_STEP_AFTER: 7, - CURVE_STEP_BEFORE: 8, - LINEAR: 9, -}; +import React, { FC } from 'react'; +import { DomainRange } from '@elastic/charts'; +import { CurrentTime } from '../../../charts/public'; -export const ScaleType = { - Linear: 'linear', - Ordinal: 'ordinal', - Log: 'log', - Sqrt: 'sqrt', - Time: 'time', -}; +interface XYCurrentTime { + enabled: boolean; + isDarkMode: boolean; + domain?: DomainRange; +} -export const BarSeries = () => null; -export const AreaSeries = () => null; +export const XYCurrentTime: FC = ({ enabled, isDarkMode, domain }) => { + if (!enabled) { + return null; + } -export { LIGHT_THEME, DARK_THEME } from '@elastic/charts'; + const domainEnd = domain && 'max' in domain ? domain.max : undefined; + return ; +}; diff --git a/src/plugins/vis_type_xy/public/components/xy_endzones.tsx b/src/plugins/vis_type_xy/public/components/xy_endzones.tsx new file mode 100644 index 000000000000..33e1d1e18bb1 --- /dev/null +++ b/src/plugins/vis_type_xy/public/components/xy_endzones.tsx @@ -0,0 +1,68 @@ +/* + * 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, { FC } from 'react'; + +import { DomainRange } from '@elastic/charts'; + +import { Endzones } from '../../../charts/public'; + +interface XYEndzones { + enabled: boolean; + isDarkMode: boolean; + isFullBin: boolean; + hideTooltips?: boolean; + domain?: DomainRange; + adjustedDomain?: DomainRange; +} + +export const XYEndzones: FC = ({ + enabled, + isDarkMode, + isFullBin, + hideTooltips, + domain, + adjustedDomain, +}) => { + if ( + enabled && + domain && + adjustedDomain && + 'min' in domain && + 'max' in domain && + domain.minInterval !== undefined && + 'min' in adjustedDomain && + 'max' in adjustedDomain + ) { + return ( + + ); + } + + return null; +}; diff --git a/src/plugins/vis_type_xy/public/components/xy_settings.tsx b/src/plugins/vis_type_xy/public/components/xy_settings.tsx new file mode 100644 index 000000000000..3682fdf3350b --- /dev/null +++ b/src/plugins/vis_type_xy/public/components/xy_settings.tsx @@ -0,0 +1,182 @@ +/* + * 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, { FC } from 'react'; + +import { + Direction, + Settings, + DomainRange, + Position, + PartialTheme, + ElementClickListener, + BrushEndListener, + RenderChangeListener, + LegendAction, + LegendColorPicker, + TooltipProps, + TickFormatter, +} from '@elastic/charts'; + +import { renderEndzoneTooltip } from '../../../charts/public'; + +import { getThemeService, getUISettings } from '../services'; +import { VisConfig } from '../types'; +import { fillEmptyValue } from '../utils/get_series_name_fn'; + +declare global { + interface Window { + /** + * Flag used to enable debugState on elastic charts + */ + _echDebugStateFlag?: boolean; + } +} + +type XYSettingsProps = Pick< + VisConfig, + | 'markSizeRatio' + | 'rotation' + | 'enableHistogramMode' + | 'tooltip' + | 'isTimeChart' + | 'xAxis' + | 'orderBucketsBySum' +> & { + xDomain?: DomainRange; + adjustedXDomain?: DomainRange; + showLegend: boolean; + onElementClick: ElementClickListener; + onBrushEnd?: BrushEndListener; + onRenderChange: RenderChangeListener; + legendAction?: LegendAction; + legendColorPicker: LegendColorPicker; + legendPosition: Position; +}; + +export const XYSettings: FC = ({ + markSizeRatio, + rotation, + enableHistogramMode, + tooltip, + isTimeChart, + xAxis, + orderBucketsBySum, + xDomain, + adjustedXDomain, + showLegend, + onElementClick, + onBrushEnd, + onRenderChange, + legendAction, + legendColorPicker, + legendPosition, +}) => { + const themeService = getThemeService(); + const theme = themeService.useChartsTheme(); + const baseTheme = themeService.useChartsBaseTheme(); + const dimmingOpacity = getUISettings().get('visualization:dimmingOpacity'); + const fontSize = + typeof theme.barSeriesStyle?.displayValue?.fontSize === 'number' + ? { min: theme.barSeriesStyle?.displayValue?.fontSize } + : theme.barSeriesStyle?.displayValue?.fontSize ?? { min: 8 }; + + const themeOverrides: PartialTheme = { + markSizeRatio, + sharedStyle: { + unhighlighted: { + opacity: dimmingOpacity, + }, + }, + barSeriesStyle: { + displayValue: { + fontSize, + alignment: { + horizontal: 'center', + vertical: 'middle', + }, + }, + }, + axes: { + axisTitle: { + padding: { + outer: 10, + }, + }, + }, + chartMargins: + legendPosition === Position.Top || legendPosition === Position.Right + ? { + bottom: (theme.chartMargins?.bottom ?? 0) + 10, + } + : { + right: (theme.chartMargins?.right ?? 0) + 10, + }, + }; + + const headerValueFormatter: TickFormatter | undefined = xAxis.ticks?.formatter + ? (value) => fillEmptyValue(xAxis.ticks?.formatter?.(value)) ?? '' + : undefined; + const headerFormatter = + isTimeChart && xDomain && adjustedXDomain + ? renderEndzoneTooltip( + xDomain.minInterval, + 'min' in xDomain ? xDomain.min : undefined, + 'max' in xDomain ? xDomain.max : undefined, + headerValueFormatter, + !tooltip.detailedTooltip + ) + : headerValueFormatter && + (tooltip.detailedTooltip ? undefined : ({ value }: any) => headerValueFormatter(value)); + + const tooltipProps: TooltipProps = tooltip.detailedTooltip + ? { + ...tooltip, + customTooltip: tooltip.detailedTooltip(headerFormatter), + headerFormatter: undefined, + } + : { ...tooltip, headerFormatter }; + + return ( + + ); +}; diff --git a/src/plugins/vis_type_xy/public/components/xy_threshold_line.tsx b/src/plugins/vis_type_xy/public/components/xy_threshold_line.tsx new file mode 100644 index 000000000000..46b0a009807a --- /dev/null +++ b/src/plugins/vis_type_xy/public/components/xy_threshold_line.tsx @@ -0,0 +1,58 @@ +/* + * 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, { FC } from 'react'; + +import { AnnotationDomainTypes, LineAnnotation } from '@elastic/charts'; + +import { ThresholdLineConfig } from '../types'; + +type XYThresholdLineProps = ThresholdLineConfig & { + groupId?: string; +}; + +export const XYThresholdLine: FC = ({ + show, + value: dataValue, + color, + width, + groupId, + dash, +}) => { + if (!show) { + return null; + } + + return ( + + ); +}; diff --git a/src/plugins/vis_type_xy/public/config/get_agg_id.ts b/src/plugins/vis_type_xy/public/config/get_agg_id.ts new file mode 100644 index 000000000000..7923145d8301 --- /dev/null +++ b/src/plugins/vis_type_xy/public/config/get_agg_id.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +/** + * Get agg id from accessor + * + * For now this is determined by the esaggs column name. Could be cleaned up in the future. + */ +export const getAggId = (accessor: string) => (accessor ?? '').split('-').pop() ?? ''; diff --git a/src/plugins/vis_type_xy/public/config/get_aspects.ts b/src/plugins/vis_type_xy/public/config/get_aspects.ts new file mode 100644 index 000000000000..73096de0a5d5 --- /dev/null +++ b/src/plugins/vis_type_xy/public/config/get_aspects.ts @@ -0,0 +1,95 @@ +/* + * 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 { compact } from 'lodash'; + +import { i18n } from '@kbn/i18n'; + +import { DatatableColumn } from '../../../expressions/public'; + +import { Aspect, Dimension, Aspects, Dimensions } from '../types'; +import { getFormatService } from '../services'; +import { getAggId } from './get_agg_id'; + +export function getEmptyAspect(): Aspect { + return { + accessor: null, + aggId: null, + aggType: null, + title: i18n.translate('visTypeXy.aggResponse.allDocsTitle', { + defaultMessage: 'All docs', + }), + params: { + defaultValue: '_all', + }, + }; +} +export function getAspects(columns: DatatableColumn[], { x, y, z, series }: Dimensions): Aspects { + const seriesDimensions = Array.isArray(series) || series === undefined ? series : [series]; + + return { + x: getAspectsFromDimension(columns, x) ?? getEmptyAspect(), + y: getAspectsFromDimension(columns, y) ?? [], + z: z && z?.length > 0 ? getAspectsFromDimension(columns, z[0]) : undefined, + series: getAspectsFromDimension(columns, seriesDimensions), + }; +} + +function getAspectsFromDimension( + columns: DatatableColumn[], + dimension?: Dimension | null +): Aspect | undefined; +function getAspectsFromDimension( + columns: DatatableColumn[], + dimensions?: Dimension[] | null +): Aspect[] | undefined; +function getAspectsFromDimension( + columns: DatatableColumn[], + dimensions?: Dimension | Dimension[] | null +): Aspect[] | Aspect | undefined { + if (!dimensions) { + return; + } + + if (Array.isArray(dimensions)) { + return compact( + dimensions.map((d) => { + const column = d && columns[d.accessor]; + return column && getAspect(column, d); + }) + ); + } + + const column = columns[dimensions.accessor]; + return column && getAspect(column, dimensions); +} + +const getAspect = ( + { id: accessor, name: title }: DatatableColumn, + { accessor: column, format, params, aggType }: Dimension +): Aspect => ({ + accessor, + column, + title, + format, + aggType, + aggId: getAggId(accessor), + formatter: (value: any) => getFormatService().deserialize(format).convert(value), + params, +}); diff --git a/src/plugins/vis_type_xy/public/config/get_axis.ts b/src/plugins/vis_type_xy/public/config/get_axis.ts new file mode 100644 index 000000000000..43a9e25e0e28 --- /dev/null +++ b/src/plugins/vis_type_xy/public/config/get_axis.ts @@ -0,0 +1,198 @@ +/* + * 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 { identity, isNil } from 'lodash'; + +import { AxisSpec, TickFormatter, YDomainRange, ScaleType as ECScaleType } from '@elastic/charts'; + +import { LabelRotation } from '../../../charts/public'; +import { BUCKET_TYPES } from '../../../data/public'; + +import { + Aspect, + CategoryAxis, + Grid, + AxisConfig, + TickOptions, + ScaleConfig, + Scale, + ScaleType, + AxisType, + XScaleType, + YScaleType, + SeriesParam, +} from '../types'; +import { fillEmptyValue } from '../utils/get_series_name_fn'; + +export function getAxis( + { type, title: axisTitle, labels, scale: axisScale, ...axis }: CategoryAxis, + { categoryLines, valueAxis }: Grid, + { params, format, formatter, title: fallbackTitle = '', aggType }: Aspect, + seriesParams: SeriesParam[], + isDateHistogram = false +): AxisConfig { + const isCategoryAxis = type === AxisType.Category; + // Hide unassigned axis, not supported in elastic charts + // TODO: refactor when disallowing unassigned axes + // https://github.com/elastic/kibana/issues/82752 + const show = + (isCategoryAxis || seriesParams.some(({ valueAxis: id }) => id === axis.id)) && axis.show; + const groupId = axis.id; + + const grid = isCategoryAxis + ? { + show: categoryLines, + } + : { + show: valueAxis === axis.id, + }; + // Date range formatter applied on xAccessor + const tickFormatter = + aggType === BUCKET_TYPES.DATE_RANGE || aggType === BUCKET_TYPES.RANGE ? identity : formatter; + const ticks: TickOptions = { + formatter: tickFormatter, + labelFormatter: getLabelFormatter(labels.truncate, tickFormatter), + show: labels.show, + rotation: labels.rotate, + showOverlappingLabels: !labels.filter, + showDuplicates: !labels.filter, + }; + const scale = getScale(axisScale, params, format, isCategoryAxis); + const title = axisTitle.text || fallbackTitle; + const fallbackRotation = + isCategoryAxis && isDateHistogram ? LabelRotation.Horizontal : LabelRotation.Vertical; + + return { + ...axis, + show, + groupId, + title, + ticks, + grid, + scale, + style: getAxisStyle(ticks, title, fallbackRotation), + domain: getAxisDomain(scale, isCategoryAxis), + integersOnly: aggType === 'count', + }; +} + +function getLabelFormatter( + truncate?: number | null, + formatter?: TickFormatter +): TickFormatter | undefined { + if (truncate === null || truncate === undefined) { + return formatter; + } + + return (value: any) => { + const formattedStringValue = `${formatter ? formatter(value) : value}`; + const finalValue = fillEmptyValue(formattedStringValue); + + if (finalValue.length > truncate) { + return `${finalValue.slice(0, truncate)}...`; + } + + return finalValue; + }; +} + +function getScaleType( + scale?: Scale, + isNumber?: boolean, + isTime = false, + isHistogram = false +): ECScaleType | undefined { + if (isTime) return ECScaleType.Time; + if (isHistogram) return ECScaleType.Linear; + + if (!isNumber) { + return ECScaleType.Ordinal; + } + + const type = scale?.type; + if (type === ScaleType.SquareRoot) { + return ECScaleType.Sqrt; + } + + return type; +} + +function getScale( + scale: Scale, + params: Aspect['params'], + format: Aspect['format'], + isCategoryAxis: boolean +): ScaleConfig { + const type = (isCategoryAxis + ? getScaleType( + scale, + format?.id === 'number' || (format?.params?.id === 'number' && format?.id !== 'range'), + 'date' in params, + 'interval' in params + ) + : getScaleType(scale, true)) as S; + + return { + ...scale, + type, + }; +} + +function getAxisStyle( + ticks?: TickOptions, + title?: string, + rotationFallback: LabelRotation = LabelRotation.Vertical +): AxisSpec['style'] { + return { + axisTitle: { + visible: (title ?? '').trim().length > 0, + }, + tickLabel: { + visible: ticks?.show, + rotation: -(ticks?.rotation ?? rotationFallback), + }, + }; +} + +function getAxisDomain( + scale: ScaleConfig, + isCategoryAxis: boolean +): YDomainRange | undefined { + if (isCategoryAxis || !scale) { + return; + } + + const { min, max, defaultYExtents, boundsMargin } = scale; + const fit = defaultYExtents; + const padding = boundsMargin; + + if (!isNil(min) && !isNil(max)) { + return { fit, padding, min, max }; + } + + if (!isNil(min)) { + return { fit, padding, min }; + } + + if (!isNil(max)) { + return { fit, padding, max }; + } + + return { fit, padding }; +} diff --git a/src/plugins/vis_type_xy/public/config/get_config.ts b/src/plugins/vis_type_xy/public/config/get_config.ts new file mode 100644 index 000000000000..f0c5740b1307 --- /dev/null +++ b/src/plugins/vis_type_xy/public/config/get_config.ts @@ -0,0 +1,134 @@ +/* + * 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 { ScaleContinuousType } from '@elastic/charts/dist/scales'; + +import { Datatable } from '../../../expressions/public'; +import { BUCKET_TYPES } from '../../../data/public'; + +import { + Aspect, + AxisConfig, + DateHistogramParams, + SeriesParam, + VisConfig, + VisParams, + XScaleType, + YScaleType, +} from '../types'; +import { getThresholdLine } from './get_threshold_line'; +import { getRotation } from './get_rotation'; +import { getTooltip } from './get_tooltip'; +import { getLegend } from './get_legend'; +import { getAxis } from './get_axis'; +import { getAspects } from './get_aspects'; +import { ChartType } from '../index'; + +export function getConfig(table: Datatable, params: VisParams): VisConfig { + const { + thresholdLine, + orderBucketsBySum, + addTimeMarker, + radiusRatio, + labels, + fittingFunction, + detailedTooltip, + isVislibVis, + } = params; + const aspects = getAspects(table.columns, params.dimensions); + const xAxis = getAxis( + params.categoryAxes[0], + params.grid, + aspects.x, + params.seriesParams, + params.dimensions.x?.aggType === BUCKET_TYPES.DATE_HISTOGRAM + ); + const tooltip = getTooltip(aspects, params); + const yAxes = params.valueAxes.map((a) => + // uses first y aspect in array for formatting axis + getAxis(a, params.grid, aspects.y[0], params.seriesParams) + ); + const enableHistogramMode = + (params.dimensions.x?.aggType === BUCKET_TYPES.DATE_HISTOGRAM || + params.dimensions.x?.aggType === BUCKET_TYPES.HISTOGRAM) && + shouldEnableHistogramMode(params.seriesParams, aspects.y, yAxes); + const isTimeChart = (aspects.x.params as DateHistogramParams).date ?? false; + + return { + // NOTE: downscale ratio to match current vislib implementation + markSizeRatio: radiusRatio * 0.6, + fittingFunction, + detailedTooltip, + orderBucketsBySum, + isTimeChart, + isVislibVis, + showCurrentTime: addTimeMarker && isTimeChart, + showValueLabel: labels.show ?? false, + enableHistogramMode, + tooltip, + aspects, + xAxis, + yAxes, + legend: getLegend(params), + rotation: getRotation(params.categoryAxes[0]), + thresholdLine: getThresholdLine(thresholdLine, yAxes, params.seriesParams), + }; +} + +/** + * disables histogram mode for any config that has non-stacked clustered bars + * + * @param seriesParams + * @param yAspects + * @param yAxes + */ +const shouldEnableHistogramMode = ( + seriesParams: SeriesParam[], + yAspects: Aspect[], + yAxes: Array> +): boolean => { + const bars = seriesParams.filter(({ type, data: { id: paramId } }) => { + return ( + type === ChartType.Histogram && yAspects.find(({ aggId }) => aggId === paramId) !== undefined + ); + }); + + if (bars.length === 1) { + return true; + } + + const groupIds = [ + ...bars.reduce>((acc, { valueAxis: groupId, mode }) => { + acc.add(groupId); + return acc; + }, new Set()), + ]; + + if (groupIds.length > 1) { + return false; + } + + const test = bars.every(({ valueAxis: groupId, mode }) => { + const yAxisScale = yAxes.find(({ groupId: axisGroupId }) => axisGroupId === groupId)?.scale; + + return mode === 'stacked' || yAxisScale?.mode === 'percentage'; + }); + + return test; +}; diff --git a/src/plugins/vis_type_xy/public/config/get_legend.ts b/src/plugins/vis_type_xy/public/config/get_legend.ts new file mode 100644 index 000000000000..a376ec3c4fb9 --- /dev/null +++ b/src/plugins/vis_type_xy/public/config/get_legend.ts @@ -0,0 +1,27 @@ +/* + * 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 { LegendOptions, VisParams } from '../types'; + +export function getLegend({ addLegend, legendPosition }: VisParams): LegendOptions { + return { + show: addLegend, + position: legendPosition, + }; +} diff --git a/test/functional/apps/getting_started/index.js b/src/plugins/vis_type_xy/public/config/get_rotation.ts similarity index 66% rename from test/functional/apps/getting_started/index.js rename to src/plugins/vis_type_xy/public/config/get_rotation.ts index 399d3fe87484..3c1e9a8f9130 100644 --- a/test/functional/apps/getting_started/index.js +++ b/src/plugins/vis_type_xy/public/config/get_rotation.ts @@ -17,16 +17,14 @@ * under the License. */ -export default function ({ getService, loadTestFile }) { - const browser = getService('browser'); +import { Rotation } from '@elastic/charts'; - describe('Getting Started ', function () { - this.tags(['ciGroup6']); +import { CategoryAxis } from '../types'; - before(async function () { - await browser.setWindowSize(1200, 800); - }); - // https://www.elastic.co/guide/en/kibana/current/tutorial-load-dataset.html - loadTestFile(require.resolve('./_shakespeare')); - }); +export function getRotation({ position }: CategoryAxis): Rotation { + if (position === 'left' || position === 'right') { + return 90; + } + + return 0; } diff --git a/src/plugins/vis_type_xy/public/config/get_threshold_line.ts b/src/plugins/vis_type_xy/public/config/get_threshold_line.ts new file mode 100644 index 000000000000..861769f82907 --- /dev/null +++ b/src/plugins/vis_type_xy/public/config/get_threshold_line.ts @@ -0,0 +1,54 @@ +/* + * 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 { + ThresholdLineConfig, + ThresholdLine, + ThresholdLineStyle, + AxisConfig, + SeriesParam, + YScaleType, +} from '../types'; + +export function getThresholdLine( + { style, ...rest }: ThresholdLine, + yAxes: Array>, + seriesParams: SeriesParam[] +): ThresholdLineConfig { + const groupId = yAxes.find(({ id }) => seriesParams.some(({ valueAxis }) => id === valueAxis)) + ?.groupId; + + return { + ...rest, + dash: getDash(style), + groupId, + }; +} + +function getDash(style: ThresholdLineStyle): number[] | undefined { + switch (style) { + case ThresholdLineStyle.Dashed: + return [10, 5]; + case ThresholdLineStyle.DotDashed: + return [20, 5, 5, 5]; + case ThresholdLineStyle.Full: + default: + return; + } +} diff --git a/src/plugins/vis_type_xy/public/config/get_tooltip.ts b/src/plugins/vis_type_xy/public/config/get_tooltip.ts new file mode 100644 index 000000000000..87146eeca915 --- /dev/null +++ b/src/plugins/vis_type_xy/public/config/get_tooltip.ts @@ -0,0 +1,33 @@ +/* + * 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 { TooltipType } from '@elastic/charts'; + +import { Aspects, VisParams, TooltipConfig } from '../types'; +import { getDetailedTooltip } from '../components/detailed_tooltip'; + +export function getTooltip( + aspects: Aspects, + { addTooltip, detailedTooltip }: VisParams +): TooltipConfig { + return { + type: addTooltip ? TooltipType.VerticalCursor : TooltipType.None, + detailedTooltip: detailedTooltip ? getDetailedTooltip(aspects) : undefined, + }; +} diff --git a/src/plugins/vis_type_xy/public/config/index.ts b/src/plugins/vis_type_xy/public/config/index.ts new file mode 100644 index 000000000000..2b0e32f726a6 --- /dev/null +++ b/src/plugins/vis_type_xy/public/config/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { getConfig } from './get_config'; +export { getAggId } from './get_agg_id'; diff --git a/src/plugins/vis_type_xy/public/editor/collections.ts b/src/plugins/vis_type_xy/public/editor/collections.ts new file mode 100644 index 000000000000..0149bc476f5c --- /dev/null +++ b/src/plugins/vis_type_xy/public/editor/collections.ts @@ -0,0 +1,201 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { Fit } from '@elastic/charts'; + +import { AxisMode, ChartMode, InterpolationMode, ThresholdLineStyle } from '../types'; +import { ChartType } from '../../common'; +import { LabelRotation } from '../../../charts/public'; +import { getScaleTypes } from './scale_types'; +import { getPositions } from './positions'; + +export { getScaleTypes, getPositions }; + +export const getChartTypes = () => [ + { + text: i18n.translate('visTypeXy.chartTypes.lineText', { + defaultMessage: 'Line', + }), + value: ChartType.Line, + }, + { + text: i18n.translate('visTypeXy.chartTypes.areaText', { + defaultMessage: 'Area', + }), + value: ChartType.Area, + }, + { + text: i18n.translate('visTypeXy.chartTypes.barText', { + defaultMessage: 'Bar', + }), + value: ChartType.Histogram, + }, +]; + +export const getChartModes = () => [ + { + text: i18n.translate('visTypeXy.chartModes.normalText', { + defaultMessage: 'Normal', + }), + value: ChartMode.Normal, + }, + { + text: i18n.translate('visTypeXy.chartModes.stackedText', { + defaultMessage: 'Stacked', + }), + value: ChartMode.Stacked, + }, +]; + +export const getInterpolationModes = () => [ + { + text: i18n.translate('visTypeXy.interpolationModes.straightText', { + defaultMessage: 'Straight', + }), + value: InterpolationMode.Linear, + }, + { + text: i18n.translate('visTypeXy.interpolationModes.smoothedText', { + defaultMessage: 'Smoothed', + }), + value: InterpolationMode.Cardinal, + }, + { + text: i18n.translate('visTypeXy.interpolationModes.steppedText', { + defaultMessage: 'Stepped', + }), + value: InterpolationMode.StepAfter, + }, +]; + +export const getAxisModes = () => [ + { + text: i18n.translate('visTypeXy.axisModes.normalText', { + defaultMessage: 'Normal', + }), + value: AxisMode.Normal, + }, + { + text: i18n.translate('visTypeXy.axisModes.percentageText', { + defaultMessage: 'Percentage', + }), + value: AxisMode.Percentage, + }, + { + text: i18n.translate('visTypeXy.axisModes.wiggleText', { + defaultMessage: 'Wiggle', + }), + value: AxisMode.Wiggle, + }, + { + text: i18n.translate('visTypeXy.axisModes.silhouetteText', { + defaultMessage: 'Silhouette', + }), + value: AxisMode.Silhouette, + }, +]; + +export const getThresholdLineStyles = () => [ + { + value: ThresholdLineStyle.Full, + text: i18n.translate('visTypeXy.thresholdLine.style.fullText', { + defaultMessage: 'Full', + }), + }, + { + value: ThresholdLineStyle.Dashed, + text: i18n.translate('visTypeXy.thresholdLine.style.dashedText', { + defaultMessage: 'Dashed', + }), + }, + { + value: ThresholdLineStyle.DotDashed, + text: i18n.translate('visTypeXy.thresholdLine.style.dotdashedText', { + defaultMessage: 'Dot-dashed', + }), + }, +]; + +export const getRotateOptions = () => [ + { + text: i18n.translate('visTypeXy.categoryAxis.rotate.horizontalText', { + defaultMessage: 'Horizontal', + }), + value: LabelRotation.Horizontal, + }, + { + text: i18n.translate('visTypeXy.categoryAxis.rotate.verticalText', { + defaultMessage: 'Vertical', + }), + value: LabelRotation.Vertical, + }, + { + text: i18n.translate('visTypeXy.categoryAxis.rotate.angledText', { + defaultMessage: 'Angled', + }), + value: LabelRotation.Angled, + }, +]; + +export const getFittingFunctions = () => + [ + { + value: Fit.None, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.none', { + defaultMessage: 'Hide (Do not fill gaps)', + }), + }, + { + value: Fit.Zero, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.zero', { + defaultMessage: 'Zero (Fill gaps with zeros)', + }), + }, + { + value: Fit.Linear, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.linear', { + defaultMessage: 'Linear (Fill gaps with a line)', + }), + }, + { + value: Fit.Carry, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.carry', { + defaultMessage: 'Last (Fill gaps with the last value)', + }), + }, + { + value: Fit.Lookahead, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.lookahead', { + defaultMessage: 'Next (Fill gaps with the next value)', + }), + }, + ] as const; + +export const getConfigCollections = () => ({ + legendPositions: getPositions(), + positions: getPositions(), + chartTypes: getChartTypes(), + axisModes: getAxisModes(), + scaleTypes: getScaleTypes(), + chartModes: getChartModes(), + interpolationModes: getInterpolationModes(), + thresholdLineStyles: getThresholdLineStyles(), + fittingFunctions: getFittingFunctions(), +}); diff --git a/src/plugins/vis_type_vislib/public/utils/common_config.tsx b/src/plugins/vis_type_xy/public/editor/common_config.tsx similarity index 59% rename from src/plugins/vis_type_vislib/public/utils/common_config.tsx rename to src/plugins/vis_type_xy/public/editor/common_config.tsx index de867dc72bba..31d1a9d53962 100644 --- a/src/plugins/vis_type_vislib/public/utils/common_config.tsx +++ b/src/plugins/vis_type_xy/public/editor/common_config.tsx @@ -20,36 +20,37 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { PointSeriesOptions, MetricsAxisOptions } from '../components/options'; -import { ValidationWrapper } from '../components/common'; -import { BasicVislibParams } from '../types'; +import { VisOptionsProps } from '../../../vis_default_editor/public'; -function getAreaOptionTabs() { +import { VisParams } from '../types'; +import { MetricsAxisOptions, PointSeriesOptions } from './components/options'; +import { ValidationWrapper } from './components/common'; + +export function getOptionTabs(showElasticChartsOptions = false) { return [ { name: 'advanced', - title: i18n.translate('visTypeVislib.area.tabs.metricsAxesTitle', { + title: i18n.translate('visTypeXy.area.tabs.metricsAxesTitle', { defaultMessage: 'Metrics & axes', }), - editor: (props: VisOptionsProps) => ( + editor: (props: VisOptionsProps) => ( ), }, { name: 'options', - title: i18n.translate('visTypeVislib.area.tabs.panelSettingsTitle', { + title: i18n.translate('visTypeXy.area.tabs.panelSettingsTitle', { defaultMessage: 'Panel settings', }), - editor: (props: VisOptionsProps) => ( - + editor: (props: VisOptionsProps) => ( + ), }, ]; } - -const countLabel = i18n.translate('visTypeVislib.area.countText', { - defaultMessage: 'Count', -}); - -export { getAreaOptionTabs, countLabel }; diff --git a/src/plugins/vis_type_vislib/public/components/common/index.ts b/src/plugins/vis_type_xy/public/editor/components/common/index.ts similarity index 100% rename from src/plugins/vis_type_vislib/public/components/common/index.ts rename to src/plugins/vis_type_xy/public/editor/components/common/index.ts diff --git a/src/plugins/vis_type_vislib/public/components/common/truncate_labels.tsx b/src/plugins/vis_type_xy/public/editor/components/common/truncate_labels.tsx similarity index 96% rename from src/plugins/vis_type_vislib/public/components/common/truncate_labels.tsx rename to src/plugins/vis_type_xy/public/editor/components/common/truncate_labels.tsx index 6f55f6f070d0..ae1f34376bbf 100644 --- a/src/plugins/vis_type_vislib/public/components/common/truncate_labels.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/common/truncate_labels.tsx @@ -33,7 +33,7 @@ function TruncateLabelsOption({ disabled, value = null, setValue }: TruncateLabe return ( extends VisOptionsProps { +export interface ValidationVisOptionsProps extends VisOptionsProps { setMultipleValidity(paramName: string, isValid: boolean): void; + extraProps?: E; } -interface ValidationWrapperProps extends VisOptionsProps { - component: React.ComponentType>; +interface ValidationWrapperProps extends VisOptionsProps { + component: React.ComponentType>; + extraProps?: E; } interface Item { isValid: boolean; } -function ValidationWrapper({ +function ValidationWrapper({ component: Component, ...rest -}: ValidationWrapperProps) { +}: ValidationWrapperProps) { const [panelState, setPanelState] = useState({} as { [key: string]: Item }); const isPanelValid = Object.values(panelState).every((item) => item.isValid); const { setValidity } = rest; diff --git a/src/plugins/vis_type_vislib/public/components/index.ts b/src/plugins/vis_type_xy/public/editor/components/index.ts similarity index 100% rename from src/plugins/vis_type_vislib/public/components/index.ts rename to src/plugins/vis_type_xy/public/editor/components/index.ts diff --git a/src/plugins/vis_type_xy/public/editor/components/options/index.tsx b/src/plugins/vis_type_xy/public/editor/components/options/index.tsx new file mode 100644 index 000000000000..3eba7fa3ad81 --- /dev/null +++ b/src/plugins/vis_type_xy/public/editor/components/options/index.tsx @@ -0,0 +1,39 @@ +/* + * 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 { VisParams } from '../../../types'; +import { ValidationVisOptionsProps } from '../common'; + +const PointSeriesOptionsLazy = lazy(() => import('./point_series')); +const MetricsAxisOptionsLazy = lazy(() => import('./metrics_axes')); + +export const PointSeriesOptions = ( + props: ValidationVisOptionsProps< + VisParams, + { + showElasticChartsOptions: boolean; + } + > +) => ; + +export const MetricsAxisOptions = (props: ValidationVisOptionsProps) => ( + +); diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap similarity index 94% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap index 2b7c03084ec6..bc66c1940ac7 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap @@ -10,7 +10,7 @@ exports[`CategoryAxisPanel component should init with the default set of props 1

diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap similarity index 100% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap similarity index 100% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap similarity index 99% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap index 09e0753d592e..c5ce09d4d78a 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap @@ -74,7 +74,6 @@ exports[`MetricsAxisOptions component should init with the default set of props /> diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap similarity index 100% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap similarity index 98% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap index ed7ae45eed3a..594511010b74 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap @@ -18,7 +18,7 @@ exports[`ValueAxesPanel component should init with the default set of props 1`]

@@ -120,7 +120,6 @@ exports[`ValueAxesPanel component should init with the default set of props 1`] } } index={0} - isCategoryAxisHorizontal={false} onValueAxisPositionChanged={[MockFunction]} setMultipleValidity={[MockFunction]} setParamByIndex={[MockFunction]} @@ -303,7 +302,6 @@ exports[`ValueAxesPanel component should init with the default set of props 1`] } } index={1} - isCategoryAxisHorizontal={false} onValueAxisPositionChanged={[MockFunction]} setMultipleValidity={[MockFunction]} setParamByIndex={[MockFunction]} diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap similarity index 96% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap index c4142fb487b6..3f3ee66a8592 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap @@ -7,22 +7,18 @@ exports[`ValueAxisOptions component should init with the default set of props 1` options={ Array [ Object { - "disabled": false, "text": "Top", "value": "top", }, Object { - "disabled": true, "text": "Left", "value": "left", }, Object { - "disabled": true, "text": "Right", "value": "right", }, Object { - "disabled": false, "text": "Bottom", "value": "bottom", }, diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap similarity index 100% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx similarity index 93% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.test.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx index 44ed0d5aedda..3bf844618720 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.test.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx @@ -20,16 +20,16 @@ import React from 'react'; import { shallow } from 'enzyme'; import { CategoryAxisPanel, CategoryAxisPanelProps } from './category_axis_panel'; -import { Axis } from '../../../types'; -import { Positions } from '../../../utils/collections'; +import { CategoryAxis } from '../../../../types'; import { LabelOptions } from './label_options'; import { categoryAxis, vis } from './mocks'; +import { Position } from '@elastic/charts'; describe('CategoryAxisPanel component', () => { let setCategoryAxis: jest.Mock; let onPositionChanged: jest.Mock; let defaultProps: CategoryAxisPanelProps; - let axis: Axis; + let axis: CategoryAxis; beforeEach(() => { setCategoryAxis = jest.fn(); @@ -60,7 +60,7 @@ describe('CategoryAxisPanel component', () => { }); it('should call onPositionChanged when position is changed', () => { - const value = Positions.RIGHT; + const value = Position.Right; const comp = shallow(); comp.find({ paramName: 'position' }).prop('setValue')('position', value); diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx similarity index 78% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx index 468fb1f8c315..d4647ae41a63 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx @@ -19,20 +19,24 @@ import React, { useCallback } from 'react'; -import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; +import { Position } from '@elastic/charts'; + +import { + SelectOption, + SwitchOption, + VisOptionsProps, +} from '../../../../../../vis_default_editor/public'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { Axis } from '../../../types'; -import { SelectOption, SwitchOption } from '../../../../../charts/public'; import { LabelOptions, SetAxisLabel } from './label_options'; -import { Positions } from '../../../utils/collections'; +import { CategoryAxis } from '../../../../types'; export interface CategoryAxisPanelProps { - axis: Axis; - onPositionChanged: (position: Positions) => void; - setCategoryAxis: (value: Axis) => void; + axis: CategoryAxis; + onPositionChanged: (position: Position) => void; + setCategoryAxis: (value: CategoryAxis) => void; vis: VisOptionsProps['vis']; } @@ -43,7 +47,7 @@ function CategoryAxisPanel({ setCategoryAxis, }: CategoryAxisPanelProps) { const setAxis = useCallback( - (paramName: T, value: Axis[T]) => { + (paramName: T, value: CategoryAxis[T]) => { const updatedAxis = { ...axis, [paramName]: value, @@ -54,7 +58,7 @@ function CategoryAxisPanel({ ); const setPosition = useCallback( - (paramName: 'position', value: Axis['position']) => { + (paramName: 'position', value: CategoryAxis['position']) => { setAxis(paramName, value); onPositionChanged(value); }, @@ -77,7 +81,7 @@ function CategoryAxisPanel({

@@ -85,7 +89,7 @@ function CategoryAxisPanel({ { let setParamByIndex: jest.Mock; @@ -53,14 +54,14 @@ describe('ChartOptions component', () => { }); it('should show LineOptions when type is line', () => { - chart.type = ChartTypes.LINE; + chart.type = ChartType.Line; const comp = shallow(); expect(comp.find(LineOptions).exists()).toBeTruthy(); }); it('should show line mode when type is area', () => { - chart.type = ChartTypes.AREA; + chart.type = ChartType.Area; const comp = shallow(); expect(comp.find({ paramName: 'interpolate' }).exists()).toBeTruthy(); @@ -78,8 +79,8 @@ describe('ChartOptions component', () => { it('should call setParamByIndex when mode is changed', () => { const comp = shallow(); const paramName = 'mode'; - comp.find({ paramName }).prop('setValue')(paramName, ChartModes.NORMAL); + comp.find({ paramName }).prop('setValue')(paramName, ChartMode.Normal); - expect(setParamByIndex).toBeCalledWith('seriesParams', 0, paramName, ChartModes.NORMAL); + expect(setParamByIndex).toBeCalledWith('seriesParams', 0, paramName, ChartMode.Normal); }); }); diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/chart_options.tsx similarity index 80% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/chart_options.tsx index 623a8d1f348e..070d5fe01815 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/chart_options.tsx @@ -22,12 +22,13 @@ import React, { useMemo, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { Vis } from '../../../../../visualizations/public'; -import { SeriesParam, ValueAxis } from '../../../types'; -import { ChartTypes } from '../../../utils/collections'; -import { SelectOption } from '../../../../../charts/public'; +import { Vis } from '../../../../../../visualizations/public'; +import { SelectOption } from '../../../../../../vis_default_editor/public'; + +import { SeriesParam, ValueAxis } from '../../../../types'; import { LineOptions } from './line_options'; import { SetParamByIndex, ChangeValueAxis } from '.'; +import { ChartType } from '../../../../../common'; export type SetChart = (paramName: T, value: SeriesParam[T]) => void; @@ -69,7 +70,7 @@ function ChartOptions({ value: id, })), { - text: i18n.translate('visTypeVislib.controls.pointSeries.series.newAxisLabel', { + text: i18n.translate('visTypeXy.controls.pointSeries.series.newAxisLabel', { defaultMessage: 'New axis…', }), value: 'new', @@ -82,7 +83,7 @@ function ChartOptions({ <>
- {chart.type === ChartTypes.AREA && ( + {chart.type === ChartType.Area && ( <> )} - {chart.type === ChartTypes.LINE && ( - - )} + {chart.type === ChartType.Line && } ); } diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.test.tsx similarity index 99% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.test.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.test.tsx index 4798c67928f7..82097271f881 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.test.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.test.tsx @@ -19,6 +19,7 @@ import React from 'react'; import { shallow, mount } from 'enzyme'; + import { CustomExtentsOptions, CustomExtentsOptionsProps } from './custom_extents_options'; import { YExtents } from './y_extents'; import { valueAxis } from './mocks'; diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.tsx similarity index 87% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.tsx index 634d6b3f0641..f64bdba542b9 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.tsx @@ -18,10 +18,12 @@ */ import React, { useCallback, useEffect } from 'react'; + import { i18n } from '@kbn/i18n'; -import { ValueAxis } from '../../../types'; -import { NumberInputOption, SwitchOption } from '../../../../../charts/public'; +import { NumberInputOption, SwitchOption } from '../../../../../../vis_default_editor/public'; + +import { ValueAxis } from '../../../../types'; import { YExtents } from './y_extents'; import { SetScale } from './value_axis_options'; @@ -39,7 +41,7 @@ function CustomExtentsOptions({ setValueAxisScale, }: CustomExtentsOptionsProps) { const invalidBoundsMarginMessage = i18n.translate( - 'visTypeVislib.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin', + 'visTypeXy.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin', { defaultMessage: 'Bounds margin must be greater than or equal to 0.' } ); @@ -84,12 +86,9 @@ function CustomExtentsOptions({ return ( <> ({ + SeriesPanel: () => 'SeriesPanel', +})); +jest.mock('./category_axis_panel', () => ({ + CategoryAxisPanel: () => 'CategoryAxisPanel', +})); +jest.mock('./value_axes_panel', () => ({ + ValueAxesPanel: () => 'ValueAxesPanel', +})); + +const SERIES_PARAMS = 'seriesParams'; +const VALUE_AXES = 'valueAxes'; + +const aggCount: IAggConfig = { + id: '1', + type: { name: 'count' }, + makeLabel: () => 'Count', +} as IAggConfig; + +const aggAverage: IAggConfig = { + id: '2', + type: { name: 'average' } as IAggType, + makeLabel: () => 'Average', +} as IAggConfig; + +const createAggs = (aggs: any[]) => ({ + aggs, + bySchemaName: () => aggs, +}); + +describe('MetricsAxisOptions component', () => { + let setValue: jest.Mock; + let defaultProps: ValidationVisOptionsProps; + let axis: ValueAxis; + let axisRight: ValueAxis; + let chart: SeriesParam; + + beforeEach(() => { + setValue = jest.fn(); + + axis = { + ...valueAxis, + name: 'LeftAxis-1', + position: Position.Left, + }; + axisRight = { + ...valueAxis, + id: 'ValueAxis-2', + name: 'RightAxis-1', + position: Position.Right, + }; + chart = { + ...seriesParam, + type: ChartType.Area, + }; + + defaultProps = { + aggs: createAggs([aggCount]), + isTabSelected: true, + vis: { + type: { + type: ChartType.Area, + schemas: { metrics: [{ name: 'metric' }] }, + }, + setState: jest.fn(), + serialize: jest.fn(), + }, + stateParams: { + valueAxes: [axis], + seriesParams: [chart], + categoryAxes: [categoryAxis], + grid: { + valueAxis: defaultValueAxisId, + }, + }, + setValue, + } as any; + }); + + it('should init with the default set of props', () => { + const component = shallow(); + + expect(component).toMatchSnapshot(); + }); + + describe('useEffect', () => { + it('should update series when new agg is added', () => { + const component = mount(); + component.setProps({ + aggs: createAggs([aggCount, aggAverage]), + }); + + const updatedSeries = [chart, { ...chart, data: { id: '2', label: aggAverage.makeLabel() } }]; + expect(setValue).toHaveBeenLastCalledWith(SERIES_PARAMS, updatedSeries); + }); + + it('should update series when new agg label is changed', () => { + const component = mount(); + const agg = { id: aggCount.id, makeLabel: () => 'New label' }; + component.setProps({ + aggs: createAggs([agg]), + }); + + const updatedSeries = [{ ...chart, data: { id: agg.id, label: agg.makeLabel() } }]; + expect(setValue).toHaveBeenCalledWith(SERIES_PARAMS, updatedSeries); + }); + }); + + describe('updateAxisTitle', () => { + it('should not update the value axis title if custom title was set', () => { + defaultProps.stateParams.valueAxes[0].title.text = 'Custom title'; + const component = mount(); + const newAgg = { + ...aggCount, + makeLabel: () => 'Custom label', + }; + component.setProps({ + aggs: createAggs([newAgg]), + }); + const updatedValues = [{ ...axis, title: { text: newAgg.makeLabel() } }]; + expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES, updatedValues); + }); + + it('should set the custom title to match the value axis label when only one agg exists for that axis', () => { + const component = mount(); + const agg = { + id: aggCount.id, + params: { customLabel: 'Custom label' }, + makeLabel: () => 'Custom label', + }; + component.setProps({ + aggs: createAggs([agg]), + }); + + const updatedSeriesParams = [{ ...chart, data: { ...chart.data, label: agg.makeLabel() } }]; + const updatedValues = [{ ...axis, title: { text: agg.makeLabel() } }]; + + expect(setValue).toHaveBeenCalledTimes(5); + expect(setValue).toHaveBeenNthCalledWith(3, SERIES_PARAMS, updatedSeriesParams); + expect(setValue).toHaveBeenNthCalledWith(5, SERIES_PARAMS, updatedSeriesParams); + expect(setValue).toHaveBeenNthCalledWith(4, VALUE_AXES, updatedValues); + }); + + it('should not set the custom title to match the value axis label when more than one agg exists for that axis', () => { + const component = mount(); + const agg = { id: aggCount.id, makeLabel: () => 'Custom label' }; + component.setProps({ + aggs: createAggs([agg, aggAverage]), + stateParams: { + ...defaultProps.stateParams, + seriesParams: [chart, chart], + }, + }); + + expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES); + }); + + it('should not overwrite the custom title with the value axis label if the custom title has been changed', () => { + defaultProps.stateParams.valueAxes[0].title.text = 'Custom title'; + const component = mount(); + const agg = { + id: aggCount.id, + params: { customLabel: 'Custom label' }, + makeLabel: () => 'Custom label', + }; + component.setProps({ + aggs: createAggs([agg]), + }); + + expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES); + }); + }); + + it('should add value axis', () => { + const component = shallow(); + component.find(ValueAxesPanel).prop('addValueAxis')(); + + expect(setValue).toHaveBeenCalledWith(VALUE_AXES, [axis, axisRight]); + }); + + describe('removeValueAxis', () => { + beforeEach(() => { + defaultProps.stateParams.valueAxes = [axis, axisRight]; + }); + + it('should remove value axis', () => { + const component = shallow(); + component.find(ValueAxesPanel).prop('removeValueAxis')(axis); + + expect(setValue).toHaveBeenCalledWith(VALUE_AXES, [axisRight]); + }); + + it('should update seriesParams "valueAxis" prop', () => { + const updatedSeriesParam = { ...chart, valueAxis: 'ValueAxis-2' }; + const component = shallow(); + component.find(ValueAxesPanel).prop('removeValueAxis')(axis); + + expect(setValue).toHaveBeenCalledWith(SERIES_PARAMS, [updatedSeriesParam]); + }); + + it('should reset grid "valueAxis" prop', () => { + const updatedGrid = { valueAxis: undefined }; + defaultProps.stateParams.seriesParams[0].valueAxis = 'ValueAxis-2'; + const component = shallow(); + component.find(ValueAxesPanel).prop('removeValueAxis')(axis); + + expect(setValue).toHaveBeenCalledWith('grid', updatedGrid); + }); + }); + + describe('onValueAxisPositionChanged', () => { + const getProps = ( + valuePosition1: Position = Position.Right, + valuePosition2: Position = Position.Left + ): ValidationVisOptionsProps => ({ + ...defaultProps, + stateParams: { + ...defaultProps.stateParams, + valueAxes: [ + { + ...valueAxis, + id: 'ValueAxis-1', + position: valuePosition1, + }, + { + ...valueAxis, + id: 'ValueAxis-2', + position: valuePosition2, + }, + { + ...valueAxis, + id: 'ValueAxis-3', + position: valuePosition2, + }, + ], + categoryAxes: [ + { + ...categoryAxis, + position: mapPosition(valuePosition1), + }, + ], + }, + }); + + it('should update all value axes if another value axis changes from horizontal to vertical', () => { + const component = mount(); + setValue.mockClear(); + const onValueAxisPositionChanged = component + .find(ValueAxesPanel) + .prop('onValueAxisPositionChanged'); + onValueAxisPositionChanged(0, Position.Bottom); + expect(setValue).nthCalledWith(1, 'categoryAxes', [ + expect.objectContaining({ + id: 'CategoryAxis-1', + position: Position.Right, + }), + ]); + expect(setValue).nthCalledWith(2, 'valueAxes', [ + expect.objectContaining({ + id: 'ValueAxis-1', + position: Position.Bottom, + }), + expect.objectContaining({ + id: 'ValueAxis-2', + position: Position.Top, + }), + expect.objectContaining({ + id: 'ValueAxis-3', + position: Position.Top, + }), + ]); + }); + + it('should update all value axes if another value axis changes from vertical to horizontal', () => { + const component = mount(); + setValue.mockClear(); + const onValueAxisPositionChanged = component + .find(ValueAxesPanel) + .prop('onValueAxisPositionChanged'); + onValueAxisPositionChanged(1, Position.Left); + expect(setValue).nthCalledWith(1, 'categoryAxes', [ + expect.objectContaining({ + id: 'CategoryAxis-1', + position: Position.Top, + }), + ]); + expect(setValue).nthCalledWith(2, 'valueAxes', [ + expect.objectContaining({ + id: 'ValueAxis-1', + position: Position.Right, + }), + expect.objectContaining({ + id: 'ValueAxis-2', + position: Position.Left, + }), + expect.objectContaining({ + id: 'ValueAxis-3', + position: Position.Left, + }), + ]); + }); + + it('should update only changed value axis if value axis stays horizontal', () => { + const component = mount(); + setValue.mockClear(); + const onValueAxisPositionChanged = component + .find(ValueAxesPanel) + .prop('onValueAxisPositionChanged'); + onValueAxisPositionChanged(0, Position.Left); + expect(setValue).nthCalledWith(1, 'valueAxes', [ + expect.objectContaining({ + id: 'ValueAxis-1', + position: Position.Left, + }), + expect.objectContaining({ + id: 'ValueAxis-2', + position: Position.Left, + }), + expect.objectContaining({ + id: 'ValueAxis-3', + position: Position.Left, + }), + ]); + }); + + it('should update only changed value axis if value axis stays vertical', () => { + const component = mount(); + setValue.mockClear(); + const onValueAxisPositionChanged = component + .find(ValueAxesPanel) + .prop('onValueAxisPositionChanged'); + onValueAxisPositionChanged(1, Position.Top); + expect(setValue).nthCalledWith(1, 'valueAxes', [ + expect.objectContaining({ + id: 'ValueAxis-1', + position: Position.Top, + }), + expect.objectContaining({ + id: 'ValueAxis-2', + position: Position.Top, + }), + expect.objectContaining({ + id: 'ValueAxis-3', + position: Position.Bottom, + }), + ]); + }); + }); + + describe('onCategoryAxisPositionChanged', () => { + const getProps = ( + position: Position = Position.Bottom + ): ValidationVisOptionsProps => ({ + ...defaultProps, + stateParams: { + ...defaultProps.stateParams, + valueAxes: [ + { + ...valueAxis, + id: 'ValueAxis-1', + position: mapPosition(position), + }, + { + ...valueAxis, + id: 'ValueAxis-2', + position: mapPositionOpposite(mapPosition(position)), + }, + { + ...valueAxis, + id: 'ValueAxis-3', + position: mapPosition(position), + }, + ], + categoryAxes: [ + { + ...categoryAxis, + position, + }, + ], + }, + }); + + it('should update all value axes if category axis changes from horizontal to vertical', () => { + const component = mount(); + setValue.mockClear(); + const onPositionChanged = component.find(CategoryAxisPanel).prop('onPositionChanged'); + onPositionChanged(Position.Left); + expect(setValue).nthCalledWith(1, 'valueAxes', [ + expect.objectContaining({ + id: 'ValueAxis-1', + position: Position.Bottom, + }), + expect.objectContaining({ + id: 'ValueAxis-2', + position: Position.Top, + }), + expect.objectContaining({ + id: 'ValueAxis-3', + position: Position.Bottom, + }), + ]); + }); + + it('should update all value axes if category axis changes from vertical to horizontal', () => { + const component = mount(); + setValue.mockClear(); + const onPositionChanged = component.find(CategoryAxisPanel).prop('onPositionChanged'); + onPositionChanged(Position.Top); + expect(setValue).nthCalledWith(1, 'valueAxes', [ + expect.objectContaining({ + id: 'ValueAxis-1', + position: Position.Left, + }), + expect.objectContaining({ + id: 'ValueAxis-2', + position: Position.Right, + }), + expect.objectContaining({ + id: 'ValueAxis-3', + position: Position.Left, + }), + ]); + }); + + it('should not update value axes if category axis stays horizontal', () => { + const component = mount(); + setValue.mockClear(); + const onPositionChanged = component.find(CategoryAxisPanel).prop('onPositionChanged'); + onPositionChanged(Position.Top); + expect(setValue).not.toBeCalled(); + }); + + it('should not update value axes if category axis stays vertical', () => { + const component = mount(); + setValue.mockClear(); + const onPositionChanged = component.find(CategoryAxisPanel).prop('onPositionChanged'); + onPositionChanged(Position.Right); + expect(setValue).not.toBeCalled(); + }); + }); +}); diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/index.tsx similarity index 83% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/index.tsx index 0862c47c35cf..9b4bf3127d45 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/index.tsx @@ -19,10 +19,12 @@ import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { cloneDeep, get } from 'lodash'; + import { EuiSpacer } from '@elastic/eui'; -import { IAggConfig } from 'src/plugins/data/public'; -import { BasicVislibParams, ValueAxis, SeriesParam, Axis } from '../../../types'; +import { IAggConfig } from '../../../../../../data/public'; + +import { VisParams, ValueAxis, SeriesParam, CategoryAxis } from '../../../../types'; import { ValidationVisOptionsProps } from '../../common'; import { SeriesPanel } from './series_panel'; import { CategoryAxisPanel } from './category_axis_panel'; @@ -34,6 +36,7 @@ import { getUpdatedAxisName, mapPositionOpposite, mapPosition, + mapPositionOpposingOpposite, } from './utils'; export type SetParamByIndex =

( @@ -51,11 +54,9 @@ export type ChangeValueAxis = ( const VALUE_AXIS_PREFIX = 'ValueAxis-'; -function MetricsAxisOptions(props: ValidationVisOptionsProps) { +function MetricsAxisOptions(props: ValidationVisOptionsProps) { const { stateParams, setValue, aggs, vis, isTabSelected } = props; - const [isCategoryAxisHorizontal, setIsCategoryAxisHorizontal] = useState(true); - const setParamByIndex: SetParamByIndex = useCallback( (axesName, index, paramName, value) => { const items = stateParams[axesName]; @@ -72,7 +73,7 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps) ); const setCategoryAxis = useCallback( - (value: Axis) => { + (value: CategoryAxis) => { const categoryAxes = [...stateParams.categoryAxes]; categoryAxes[0] = value; setValue('categoryAxes', categoryAxes); @@ -170,33 +171,58 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps) ); const onValueAxisPositionChanged = useCallback( - (index: number, value: ValueAxis['position']) => { + (index: number, axisPosition: ValueAxis['position']) => { + const isHorizontalAxis = isAxisHorizontal(axisPosition); const valueAxes = [...stateParams.valueAxes]; - const name = getUpdatedAxisName(value, valueAxes); + const name = getUpdatedAxisName(axisPosition, valueAxes); + const [categoryAxes] = stateParams.categoryAxes; - valueAxes[index] = { - ...valueAxes[index], - name, - position: value, - }; - setValue('valueAxes', valueAxes); + if (isAxisHorizontal(categoryAxes.position) === isHorizontalAxis) { + const updatedCategoryAxes = { + ...categoryAxes, + position: mapPosition(categoryAxes.position), + }; + + setValue('categoryAxes', [updatedCategoryAxes]); + + const oldPosition = valueAxes[index].position; + const newValueAxes = valueAxes.map(({ position, ...axis }, i) => ({ + ...axis, + position: + i === index + ? axisPosition + : mapPositionOpposingOpposite(position, oldPosition, axisPosition), + })); + setValue('valueAxes', newValueAxes); + } else { + valueAxes[index] = { + ...valueAxes[index], + name, + position: axisPosition, + }; + setValue('valueAxes', valueAxes); + } }, - [stateParams.valueAxes, setValue] + [stateParams.valueAxes, stateParams.categoryAxes, setValue] ); const onCategoryAxisPositionChanged = useCallback( - (chartPosition: Axis['position']) => { - const isChartHorizontal = isAxisHorizontal(chartPosition); - setIsCategoryAxisHorizontal(isAxisHorizontal(chartPosition)); - - stateParams.valueAxes.forEach((axis, index) => { - if (isAxisHorizontal(axis.position) === isChartHorizontal) { - const position = mapPosition(axis.position); - onValueAxisPositionChanged(index, position); - } - }); + (axisPosition: CategoryAxis['position']) => { + const isHorizontalAxis = isAxisHorizontal(axisPosition); + + if ( + stateParams.valueAxes.some( + ({ position }) => isAxisHorizontal(position) === isHorizontalAxis + ) + ) { + const newValueAxes = stateParams.valueAxes.map(({ position, ...axis }) => ({ + ...axis, + position: mapPosition(position), + })); + setValue('valueAxes', newValueAxes); + } }, - [stateParams.valueAxes, onValueAxisPositionChanged] + [setValue, stateParams.valueAxes] ); const addValueAxis = useCallback(() => { @@ -305,7 +331,6 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps) ( - paramName: T, - value: Axis['labels'][T] -) => void; +export type SetAxisLabel = (paramName: T, value: Labels[T]) => void; export interface LabelOptionsProps { - axisLabels: Axis['labels']; + axisLabels: Labels; axisFilterCheckboxName: string; setAxisLabel: SetAxisLabel; } function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: LabelOptionsProps) { const setAxisLabelRotate = useCallback( - (paramName: 'rotate', value: Axis['labels']['rotate']) => { + (paramName: 'rotate', value: Labels['rotate']) => { setAxisLabel(paramName, Number(value)); }, [setAxisLabel] @@ -54,7 +52,7 @@ function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: Labe

@@ -62,7 +60,7 @@ function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: Labe

@@ -57,13 +58,10 @@ function SeriesPanel({ seriesParams, ...chartProps }: SeriesPanelProps) { initialIsOpen={index === 0} buttonContent={chart.data.label} buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate" - aria-label={i18n.translate( - 'visTypeVislib.controls.pointSeries.seriesAccordionAriaLabel', - { - defaultMessage: 'Toggle {agg} options', - values: { agg: chart.data.label }, - } - )} + aria-label={i18n.translate('visTypeXy.controls.pointSeries.seriesAccordionAriaLabel', { + defaultMessage: 'Toggle {agg} options', + values: { agg: chart.data.label }, + })} > <> diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/utils.ts b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/utils.ts similarity index 53% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/utils.ts rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/utils.ts index 708e8cf15f02..58216ee8953c 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/utils.ts +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/utils.ts @@ -16,13 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - import { upperFirst } from 'lodash'; -import { BasicVislibParams, ValueAxis, SeriesParam } from '../../../types'; -import { ChartModes, ChartTypes, InterpolationModes, Positions } from '../../../utils/collections'; +import { Position } from '@elastic/charts'; + +import { VisParams, ValueAxis, SeriesParam, ChartMode, InterpolationMode } from '../../../../types'; +import { ChartType } from '../../../../../common'; -const makeSerie = ( +export const makeSerie = ( id: string, label: string, defaultValueAxis: ValueAxis['id'], @@ -31,11 +32,11 @@ const makeSerie = ( const data = { id, label }; const defaultSerie = { show: true, - mode: ChartModes.NORMAL, - type: ChartTypes.LINE, + mode: ChartMode.Normal, + type: ChartType.Line, drawLinesBetweenPoints: true, showCircles: true, - interpolate: InterpolationModes.LINEAR, + interpolate: InterpolationMode.Linear, lineWidth: 2, valueAxis: defaultValueAxis, data, @@ -43,12 +44,12 @@ const makeSerie = ( return lastSerie ? { ...lastSerie, data } : defaultSerie; }; -const isAxisHorizontal = (position: Positions) => - [Positions.TOP, Positions.BOTTOM].includes(position as any); +export const isAxisHorizontal = (position: Position) => + [Position.Top, Position.Bottom].includes(position as any); const RADIX = 10; -function countNextAxisNumber(axisName: string, axisProp: 'id' | 'name' = 'id') { +export function countNextAxisNumber(axisName: string, axisProp: 'id' | 'name' = 'id') { return (value: number, axis: ValueAxis) => { const nameLength = axisName.length; if (axis[axisProp].substr(0, nameLength) === axisName) { @@ -63,9 +64,9 @@ function countNextAxisNumber(axisName: string, axisProp: 'id' | 'name' = 'id') { const AXIS_PREFIX = 'Axis-'; -const getUpdatedAxisName = ( +export const getUpdatedAxisName = ( axisPosition: ValueAxis['position'], - valueAxes: BasicVislibParams['valueAxes'] + valueAxes: VisParams['valueAxes'] ) => { const axisName = upperFirst(axisPosition) + AXIS_PREFIX; const nextAxisNameNumber = valueAxes.reduce(countNextAxisNumber(axisName, 'name'), 1); @@ -73,39 +74,56 @@ const getUpdatedAxisName = ( return `${axisName}${nextAxisNameNumber}`; }; -function mapPositionOpposite(position: Positions) { +/** + * Maps axis position to opposite position + * @param position + */ +export function mapPositionOpposite(position: Position) { switch (position) { - case Positions.BOTTOM: - return Positions.TOP; - case Positions.TOP: - return Positions.BOTTOM; - case Positions.LEFT: - return Positions.RIGHT; - case Positions.RIGHT: - return Positions.LEFT; + case Position.Bottom: + return Position.Top; + case Position.Top: + return Position.Bottom; + case Position.Left: + return Position.Right; + case Position.Right: + return Position.Left; default: throw new Error('Invalid legend position.'); } } -function mapPosition(position: Positions) { - switch (position) { - case Positions.BOTTOM: - return Positions.LEFT; - case Positions.TOP: - return Positions.RIGHT; - case Positions.LEFT: - return Positions.BOTTOM; - case Positions.RIGHT: - return Positions.TOP; +/** + * Maps axis position to new position or opposite of new position based on old position + * @param position + * @param oldPosition + * @param newPosition + */ +export function mapPositionOpposingOpposite( + position: Position, + oldPosition: Position, + newPosition: Position +) { + if (position === oldPosition) { + return newPosition; } + + return mapPositionOpposite(newPosition); } -export { - makeSerie, - isAxisHorizontal, - countNextAxisNumber, - getUpdatedAxisName, - mapPositionOpposite, - mapPosition, -}; +/** + * Maps axis position to opposite rotation position + * @param position + */ +export function mapPosition(position: Position) { + switch (position) { + case Position.Bottom: + return Position.Left; + case Position.Top: + return Position.Right; + case Position.Left: + return Position.Bottom; + case Position.Right: + return Position.Top; + } +} diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.test.tsx similarity index 96% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.test.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.test.tsx index 070433ca03f6..f3286029db32 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.test.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.test.tsx @@ -19,10 +19,12 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { ValueAxesPanel, ValueAxesPanelProps } from './value_axes_panel'; -import { ValueAxis, SeriesParam } from '../../../types'; -import { Positions } from '../../../utils/collections'; + import { mountWithIntl } from '@kbn/test/jest'; +import { Position } from '@elastic/charts'; + +import { ValueAxis, SeriesParam } from '../../../../types'; +import { ValueAxesPanel, ValueAxesPanelProps } from './value_axes_panel'; import { valueAxis, seriesParam, vis } from './mocks'; describe('ValueAxesPanel component', () => { @@ -47,7 +49,7 @@ describe('ValueAxesPanel component', () => { axisRight = { ...valueAxis, id: 'ValueAxis-2', - position: Positions.RIGHT, + position: Position.Right, }; seriesParamCount = { ...seriesParam }; seriesParamAverage = { @@ -63,7 +65,6 @@ describe('ValueAxesPanel component', () => { seriesParams: [seriesParamCount, seriesParamAverage], valueAxes: [axisLeft, axisRight], vis, - isCategoryAxisHorizontal: false, setParamByIndex, onValueAxisPositionChanged, addValueAxis, diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.tsx similarity index 90% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.tsx index 5f7d33b7f1f4..397704663ff1 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.tsx @@ -31,13 +31,13 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Vis } from '../../../../../visualizations/public'; -import { SeriesParam, ValueAxis } from '../../../types'; +import { Vis } from '../../../../../../visualizations/public'; + +import { SeriesParam, ValueAxis } from '../../../../types'; import { ValueAxisOptions } from './value_axis_options'; import { SetParamByIndex } from '.'; export interface ValueAxesPanelProps { - isCategoryAxisHorizontal: boolean; addValueAxis: () => ValueAxis; removeValueAxis: (axis: ValueAxis) => void; onValueAxisPositionChanged: (index: number, value: ValueAxis['position']) => void; @@ -64,7 +64,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) { const removeButtonTooltip = useMemo( () => - i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.removeButtonTooltip', { + i18n.translate('visTypeXy.controls.pointSeries.valueAxes.removeButtonTooltip', { defaultMessage: 'Remove Y-axis', }), [] @@ -87,7 +87,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) { const addButtonTooltip = useMemo( () => - i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.addButtonTooltip', { + i18n.translate('visTypeXy.controls.pointSeries.valueAxes.addButtonTooltip', { defaultMessage: 'Add Y-axis', }), [] @@ -115,7 +115,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) {

@@ -146,7 +146,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) { buttonClassName="eui-textTruncate" buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate" aria-label={i18n.translate( - 'visTypeVislib.controls.pointSeries.valueAxes.toggleOptionsAriaLabel', + 'visTypeXy.controls.pointSeries.valueAxes.toggleOptionsAriaLabel', { defaultMessage: 'Toggle {axisName} options', values: { axisName: axis.name }, @@ -160,7 +160,6 @@ function ValueAxesPanel(props: ValueAxesPanelProps) { axis={axis} index={index} valueAxis={valueAxes[index]} - isCategoryAxisHorizontal={props.isCategoryAxisHorizontal} onValueAxisPositionChanged={props.onValueAxisPositionChanged} setParamByIndex={props.setParamByIndex} setMultipleValidity={props.setMultipleValidity} diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.test.tsx similarity index 64% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.test.tsx index 1977bdba6ead..62757d14a019 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.test.tsx @@ -19,21 +19,18 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { ValueAxisOptions, ValueAxisOptionsParams } from './value_axis_options'; -import { ValueAxis } from '../../../types'; -import { TextInputOption } from '../../../../../charts/public'; + +import { Position } from '@elastic/charts'; + +import { TextInputOption } from '../../../../../../vis_default_editor/public'; + +import { ValueAxis, ScaleType } from '../../../../types'; import { LabelOptions } from './label_options'; -import { ScaleTypes, Positions } from '../../../utils/collections'; +import { ValueAxisOptions, ValueAxisOptionsParams } from './value_axis_options'; import { valueAxis, vis } from './mocks'; const POSITION = 'position'; -interface PositionOption { - text: string; - value: Positions; - disabled: boolean; -} - describe('ValueAxisOptions component', () => { let setParamByIndex: jest.Mock; let onValueAxisPositionChanged: jest.Mock; @@ -52,7 +49,6 @@ describe('ValueAxisOptions component', () => { index: 0, valueAxis, vis, - isCategoryAxisHorizontal: false, setParamByIndex, onValueAxisPositionChanged, setMultipleValidity, @@ -73,50 +69,8 @@ describe('ValueAxisOptions component', () => { expect(comp.find(LabelOptions).exists()).toBeFalsy(); }); - it('should only allow left and right value axis position when category axis is horizontal', () => { - defaultProps.isCategoryAxisHorizontal = true; - const comp = shallow(); - - const options: PositionOption[] = comp.find({ paramName: POSITION }).prop('options'); - - expect(options.length).toBe(4); - options.forEach(({ value, disabled }) => { - switch (value) { - case Positions.LEFT: - case Positions.RIGHT: - expect(disabled).toBeFalsy(); - break; - case Positions.TOP: - case Positions.BOTTOM: - expect(disabled).toBeTruthy(); - break; - } - }); - }); - - it('should only allow top and bottom value axis position when category axis is vertical', () => { - defaultProps.isCategoryAxisHorizontal = false; - const comp = shallow(); - - const options: PositionOption[] = comp.find({ paramName: POSITION }).prop('options'); - - expect(options.length).toBe(4); - options.forEach(({ value, disabled }) => { - switch (value) { - case Positions.LEFT: - case Positions.RIGHT: - expect(disabled).toBeTruthy(); - break; - case Positions.TOP: - case Positions.BOTTOM: - expect(disabled).toBeFalsy(); - break; - } - }); - }); - it('should call onValueAxisPositionChanged when position is changed', () => { - const value = Positions.RIGHT; + const value = Position.Right; const comp = shallow(); comp.find({ paramName: POSITION }).prop('setValue')(POSITION, value); @@ -135,7 +89,7 @@ describe('ValueAxisOptions component', () => { }); it('should call setValueAxis when scale value is changed', () => { - const scaleValue = ScaleTypes.SQUARE_ROOT; + const scaleValue = ScaleType.SquareRoot; const comp = shallow(); comp.find({ paramName: 'type' }).prop('setValue')('type', scaleValue); diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.tsx similarity index 75% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.tsx index b42d038267d7..d81ddcb95ce6 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.tsx @@ -17,17 +17,20 @@ * under the License. */ -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiAccordion, EuiHorizontalRule } from '@elastic/eui'; -import { Vis } from '../../../../../visualizations/public'; -import { ValueAxis } from '../../../types'; -import { Positions } from '../../../utils/collections'; -import { SelectOption, SwitchOption, TextInputOption } from '../../../../../charts/public'; +import { Vis } from '../../../../../../visualizations/public'; +import { + SelectOption, + SwitchOption, + TextInputOption, +} from '../../../../../../vis_default_editor/public'; + +import { ValueAxis } from '../../../../types'; import { LabelOptions, SetAxisLabel } from './label_options'; import { CustomExtentsOptions } from './custom_extents_options'; -import { isAxisHorizontal } from './utils'; import { SetParamByIndex } from '.'; export type SetScale = ( @@ -38,7 +41,6 @@ export type SetScale = ( export interface ValueAxisOptionsParams { axis: ValueAxis; index: number; - isCategoryAxisHorizontal: boolean; onValueAxisPositionChanged: (index: number, value: ValueAxis['position']) => void; setParamByIndex: SetParamByIndex; valueAxis: ValueAxis; @@ -46,10 +48,9 @@ export interface ValueAxisOptionsParams { setMultipleValidity: (paramName: string, isValid: boolean) => void; } -function ValueAxisOptions({ +export function ValueAxisOptions({ axis, index, - isCategoryAxisHorizontal, valueAxis, vis, onValueAxisPositionChanged, @@ -105,34 +106,13 @@ function ValueAxisOptions({ [index, onValueAxisPositionChanged] ); - const isPositionDisabled = useCallback( - (position: Positions) => { - if (isCategoryAxisHorizontal) { - return isAxisHorizontal(position); - } - return [Positions.LEFT, Positions.RIGHT].includes(position as any); - }, - [isCategoryAxisHorizontal] - ); - - const positions = useMemo( - () => - vis.type.editorConfig.collections.positions.map( - (position: { text: string; value: Positions }) => ({ - ...position, - disabled: isPositionDisabled(position.value), - }) - ), - [vis.type.editorConfig.collections.positions, isPositionDisabled] - ); - return ( <> ); } - -export { ValueAxisOptions }; diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.test.tsx similarity index 94% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.test.tsx index 7bd5c9efdf29..27a28d96d060 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.test.tsx @@ -19,9 +19,10 @@ import React from 'react'; import { mount, shallow } from 'enzyme'; + +import { ScaleType } from '../../../../types'; import { YExtents, YExtentsProps } from './y_extents'; -import { ScaleTypes } from '../../../utils/collections'; -import { NumberInputOption } from '../../../../../charts/public'; +import { NumberInputOption } from '../../../../../../vis_default_editor/public'; describe('YExtents component', () => { let setMultipleValidity: jest.Mock; @@ -35,7 +36,7 @@ describe('YExtents component', () => { defaultProps = { scale: { - type: ScaleTypes.LINEAR, + type: ScaleType.Linear, }, setMultipleValidity, setScale, @@ -81,7 +82,7 @@ describe('YExtents component', () => { it('should call setMultipleValidity with false when min equals 0 and scale is log', () => { defaultProps.scale.min = 0; defaultProps.scale.max = 1; - defaultProps.scale.type = ScaleTypes.LOG; + defaultProps.scale.type = ScaleType.Log; mount(); expect(setMultipleValidity).toBeCalledWith(Y_EXTENTS, false); diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.tsx similarity index 83% rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.tsx index 4e23ee5a4155..ba7049e98457 100644 --- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.tsx @@ -21,15 +21,15 @@ import React, { useEffect, useCallback } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { Scale } from '../../../types'; -import { ScaleTypes } from '../../../utils/collections'; -import { NumberInputOption } from '../../../../../charts/public'; +import { NumberInputOption } from '../../../../../../vis_default_editor/public'; + +import { Scale, ScaleType } from '../../../../types'; import { SetScale } from './value_axis_options'; -const rangeError = i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.minErrorMessage', { +const rangeError = i18n.translate('visTypeXy.controls.pointSeries.valueAxes.minErrorMessage', { defaultMessage: 'Min should be less than Max.', }); -const minError = i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.minNeededScaleText', { +const minError = i18n.translate('visTypeXy.controls.pointSeries.valueAxes.minNeededScaleText', { defaultMessage: 'Min must exceed 0 when a log scale is selected.', }); @@ -59,7 +59,7 @@ function YExtents({ scale, setScale, setMultipleValidity }: YExtentsProps) { errors.push(rangeError); } - if (type === ScaleTypes.LOG && (isNullOrUndefined(min) || min <= 0)) { + if (type === ScaleType.Log && (isNullOrUndefined(min) || min <= 0)) { errors.push(minError); } @@ -86,7 +86,7 @@ function YExtents({ scale, setScale, setMultipleValidity }: YExtentsProps) { ) { + const trackUiMetric = getTrackUiMetric(); + const { stateParams, setValue, vis, aggs } = props; + + const hasLineChart = stateParams.seriesParams.some( + ({ type, data: { id: paramId } }) => + (type === ChartType.Line || type === ChartType.Area) && + aggs.aggs.find(({ id }) => id === paramId)?.enabled + ); + + return ( + <> + { + if (trackUiMetric) { + trackUiMetric(METRIC_TYPE.CLICK, 'detailed_tooltip_switched'); + } + setValue(paramName, value); + }} + /> + + {hasLineChart && ( + { + if (trackUiMetric) { + trackUiMetric(METRIC_TYPE.CLICK, 'fitting_function_selected'); + } + setValue(paramName, value); + }} + /> + )} + + ); +} diff --git a/src/plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx b/src/plugins/vis_type_xy/public/editor/components/options/point_series/grid_panel.tsx similarity index 59% rename from src/plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/point_series/grid_panel.tsx index 0126dce37c9f..9efc9b65b19e 100644 --- a/src/plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/point_series/grid_panel.tsx @@ -16,25 +16,36 @@ * specific language governing permissions and limitations * under the License. */ + import React, { useMemo, useEffect, useCallback } from 'react'; -import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { SelectOption, SwitchOption } from '../../../../../charts/public'; -import { BasicVislibParams, ValueAxis } from '../../../types'; +import { SelectOption, SwitchOption } from '../../../../../../vis_default_editor/public'; +import { VisParams, ValueAxis } from '../../../../types'; +import { ValidationVisOptionsProps } from '../../common'; -function GridPanel({ stateParams, setValue, hasHistogramAgg }: VisOptionsProps) { +type GridPanelOptions = ValidationVisOptionsProps< + VisParams, + { + showElasticChartsOptions: boolean; + } +>; + +function GridPanel({ stateParams, setValue, hasHistogramAgg, extraProps }: GridPanelOptions) { const setGrid = useCallback( - ( - paramName: T, - value: BasicVislibParams['grid'][T] - ) => setValue('grid', { ...stateParams.grid, [paramName]: value }), + (paramName: T, value: VisParams['grid'][T]) => + setValue('grid', { ...stateParams.grid, [paramName]: value }), [stateParams.grid, setValue] ); + const disableCategoryGridLines = useMemo( + () => !extraProps?.showElasticChartsOptions && hasHistogramAgg, + [extraProps?.showElasticChartsOptions, hasHistogramAgg] + ); + const options = useMemo( () => [ ...stateParams.valueAxes.map(({ id, name }: ValueAxis) => ({ @@ -42,7 +53,7 @@ function GridPanel({ stateParams, setValue, hasHistogramAgg }: VisOptionsProps { - if (hasHistogramAgg) { + if (disableCategoryGridLines) { setGrid('categoryLines', false); } - }, [hasHistogramAgg, setGrid]); + }, [disableCategoryGridLines, setGrid]); return (

@@ -71,19 +82,16 @@ function GridPanel({ stateParams, setValue, hasHistogramAgg }: VisOptionsProps
diff --git a/src/plugins/vis_type_vislib/public/components/options/point_series/index.ts b/src/plugins/vis_type_xy/public/editor/components/options/point_series/index.ts similarity index 100% rename from src/plugins/vis_type_vislib/public/components/options/point_series/index.ts rename to src/plugins/vis_type_xy/public/editor/components/options/point_series/index.ts diff --git a/src/plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx b/src/plugins/vis_type_xy/public/editor/components/options/point_series/point_series.tsx similarity index 63% rename from src/plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/point_series/point_series.tsx index 18073d221887..1d00f80e0b0d 100644 --- a/src/plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/point_series/point_series.tsx @@ -16,25 +16,41 @@ * specific language governing permissions and limitations * under the License. */ + import React, { useMemo } from 'react'; import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { uniq } from 'lodash'; -import { ValidationVisOptionsProps } from '../../common'; -import { BasicOptions, SwitchOption } from '../../../../../charts/public'; +import { BasicOptions, SwitchOption } from '../../../../../../vis_default_editor/public'; +import { BUCKET_TYPES } from '../../../../../../data/public'; + +import { VisParams } from '../../../../types'; import { GridPanel } from './grid_panel'; import { ThresholdPanel } from './threshold_panel'; -import { BasicVislibParams } from '../../../types'; -import { ChartTypes } from '../../../utils/collections'; - -function PointSeriesOptions(props: ValidationVisOptionsProps) { - const { stateParams, setValue, vis } = props; +import { ChartType } from '../../../../../common'; +import { ValidationVisOptionsProps } from '../../common'; +import { ElasticChartsOptions } from './elastic_charts_options'; - const currentChartTypes = useMemo(() => uniq(stateParams.seriesParams.map(({ type }) => type)), [ - stateParams.seriesParams, - ]); +export function PointSeriesOptions( + props: ValidationVisOptionsProps< + VisParams, + { + // TODO: Remove when vis_type_vislib is removed + // https://github.com/elastic/kibana/issues/56143 + showElasticChartsOptions: boolean; + } + > +) { + const { stateParams, setValue, vis, aggs } = props; + const hasBarChart = useMemo( + () => + stateParams.seriesParams.some( + ({ type, data: { id: paramId } }) => + type === ChartType.Histogram && aggs.aggs.find(({ id }) => id === paramId)?.enabled + ), + [stateParams.seriesParams, aggs.aggs] + ); return ( <> @@ -42,7 +58,7 @@ function PointSeriesOptions(props: ValidationVisOptionsProps)

@@ -52,10 +68,11 @@ function PointSeriesOptions(props: ValidationVisOptionsProps) {vis.data.aggs!.aggs.some( - (agg) => agg.schema === 'segment' && agg.type.name === 'date_histogram' + (agg) => agg.schema === 'segment' && agg.type.name === BUCKET_TYPES.DATE_HISTOGRAM ) ? ( ) /> ) : ( ) /> )} - {currentChartTypes.includes(ChartTypes.HISTOGRAM) && ( + {hasBarChart && ( ) } /> )} + + {props.extraProps?.showElasticChartsOptions && } @@ -98,5 +118,3 @@ function PointSeriesOptions(props: ValidationVisOptionsProps) ); } - -export { PointSeriesOptions }; diff --git a/src/plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx b/src/plugins/vis_type_xy/public/editor/components/options/point_series/threshold_panel.tsx similarity index 77% rename from src/plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx rename to src/plugins/vis_type_xy/public/editor/components/options/point_series/threshold_panel.tsx index 964bb7d569b0..8eab0c478e67 100644 --- a/src/plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/point_series/threshold_panel.tsx @@ -17,39 +17,40 @@ * under the License. */ import React, { useCallback } from 'react'; -import { EuiPanel, EuiTitle, EuiColorPicker, EuiFormRow, EuiSpacer } from '@elastic/eui'; + import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiPanel, EuiTitle, EuiColorPicker, EuiFormRow, EuiSpacer } from '@elastic/eui'; -import { ValidationVisOptionsProps } from '../../common'; import { SelectOption, SwitchOption, RequiredNumberInputOption, -} from '../../../../../charts/public'; -import { BasicVislibParams } from '../../../types'; +} from '../../../../../../vis_default_editor/public'; +import { ValidationVisOptionsProps } from '../../common'; +import { VisParams } from '../../../../types'; function ThresholdPanel({ stateParams, setValue, setMultipleValidity, vis, -}: ValidationVisOptionsProps) { +}: ValidationVisOptionsProps) { const setThresholdLine = useCallback( - ( + ( paramName: T, - value: BasicVislibParams['thresholdLine'][T] + value: VisParams['thresholdLine'][T] ) => setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value }), [stateParams.thresholdLine, setValue] ); const setThresholdLineColor = useCallback( - (value: BasicVislibParams['thresholdLine']['color']) => setThresholdLine('color', value), + (value: VisParams['thresholdLine']['color']) => setThresholdLine('color', value), [setThresholdLine] ); const setThresholdLineValidity = useCallback( - (paramName: keyof BasicVislibParams['thresholdLine'], isValid: boolean) => + (paramName: keyof VisParams['thresholdLine'], isValid: boolean) => setMultipleValidity(`thresholdLine__${paramName}`, isValid), [setMultipleValidity] ); @@ -59,7 +60,7 @@ function ThresholdPanel({

@@ -67,7 +68,7 @@ function ThresholdPanel({ [ + { + text: i18n.translate('visTypeXy.legendPositions.topText', { + defaultMessage: 'Top', + }), + value: Position.Top, + }, + { + text: i18n.translate('visTypeXy.legendPositions.leftText', { + defaultMessage: 'Left', + }), + value: Position.Left, + }, + { + text: i18n.translate('visTypeXy.legendPositions.rightText', { + defaultMessage: 'Right', + }), + value: Position.Right, + }, + { + text: i18n.translate('visTypeXy.legendPositions.bottomText', { + defaultMessage: 'Bottom', + }), + value: Position.Bottom, + }, +]; diff --git a/src/plugins/vis_type_xy/public/editor/scale_types.ts b/src/plugins/vis_type_xy/public/editor/scale_types.ts new file mode 100644 index 000000000000..c115b04ead5f --- /dev/null +++ b/src/plugins/vis_type_xy/public/editor/scale_types.ts @@ -0,0 +1,43 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +import { ScaleType } from '../types'; + +export const getScaleTypes = () => [ + { + text: i18n.translate('visTypeXy.scaleTypes.linearText', { + defaultMessage: 'Linear', + }), + value: ScaleType.Linear, + }, + { + text: i18n.translate('visTypeXy.scaleTypes.logText', { + defaultMessage: 'Log', + }), + value: ScaleType.Log, + }, + { + text: i18n.translate('visTypeXy.scaleTypes.squareRootText', { + defaultMessage: 'Square root', + }), + value: ScaleType.SquareRoot, + }, +]; diff --git a/src/plugins/vis_type_xy/public/index.ts b/src/plugins/vis_type_xy/public/index.ts index 9af75ce9059e..0739ad77a245 100644 --- a/src/plugins/vis_type_xy/public/index.ts +++ b/src/plugins/vis_type_xy/public/index.ts @@ -17,11 +17,35 @@ * under the License. */ -import { PluginInitializerContext } from '../../../core/public'; import { VisTypeXyPlugin as Plugin } from './plugin'; export { VisTypeXyPluginSetup } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { - return new Plugin(initializerContext); +// TODO: Remove when vis_type_vislib is removed +// https://github.com/elastic/kibana/issues/56143 +export { + CategoryAxis, + ThresholdLine, + ValueAxis, + Grid, + SeriesParam, + Dimension, + Dimensions, + ScaleType, + AxisType, + HistogramParams, + DateHistogramParams, +} from './types'; +export type { ValidationVisOptionsProps } from './editor/components/common/validation_wrapper'; +export { TruncateLabelsOption } from './editor/components/common/truncate_labels'; +export { getPositions } from './editor/positions'; +export { getScaleTypes } from './editor/scale_types'; +export { xyVisTypes } from './vis_types'; +export { getAggId } from './config/get_agg_id'; + +// Export common types +export * from '../common'; + +export function plugin() { + return new Plugin(); } diff --git a/src/plugins/vis_type_xy/public/plugin.ts b/src/plugins/vis_type_xy/public/plugin.ts index 667018c1e6e3..ab22ae57ebbd 100644 --- a/src/plugins/vis_type_xy/public/plugin.ts +++ b/src/plugins/vis_type_xy/public/plugin.ts @@ -17,71 +17,84 @@ * under the License. */ -import { - CoreSetup, - CoreStart, - Plugin, - IUiSettingsClient, - PluginInitializerContext, -} from 'kibana/public'; - +import { CoreSetup, CoreStart, Plugin } from '../../../core/public'; import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public'; import { VisualizationsSetup, VisualizationsStart } from '../../visualizations/public'; import { ChartsPluginSetup } from '../../charts/public'; +import { DataPublicPluginStart } from '../../data/public'; +import { UsageCollectionSetup } from '../../usage_collection/public'; -export interface VisTypeXyDependencies { - uiSettings: IUiSettingsClient; - charts: ChartsPluginSetup; -} +import { createVisTypeXyVisFn } from './xy_vis_fn'; +import { + setDataActions, + setFormatService, + setThemeService, + setColorsService, + setTimefilter, + setUISettings, + setDocLinks, + setTrackUiMetric, +} from './services'; +import { visTypesDefinitions } from './vis_types'; +import { LEGACY_CHARTS_LIBRARY } from '../common'; +import { xyVisRenderer } from './vis_renderer'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface VisTypeXyPluginSetup {} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface VisTypeXyPluginStart {} /** @internal */ export interface VisTypeXyPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; charts: ChartsPluginSetup; + usageCollection: UsageCollectionSetup; } /** @internal */ export interface VisTypeXyPluginStartDependencies { expressions: ReturnType; visualizations: VisualizationsStart; + data: DataPublicPluginStart; } -type VisTypeXyCoreSetup = CoreSetup; +type VisTypeXyCoreSetup = CoreSetup; /** @internal */ -export class VisTypeXyPlugin implements Plugin { - constructor(public initializerContext: PluginInitializerContext) {} - +export class VisTypeXyPlugin + implements + Plugin< + VisTypeXyPluginSetup, + VisTypeXyPluginStart, + VisTypeXyPluginSetupDependencies, + VisTypeXyPluginStartDependencies + > { public async setup( core: VisTypeXyCoreSetup, - { expressions, visualizations, charts }: VisTypeXyPluginSetupDependencies + { expressions, visualizations, charts, usageCollection }: VisTypeXyPluginSetupDependencies ) { - // eslint-disable-next-line no-console - console.warn( - 'The visTypeXy plugin is enabled\n\n', - 'This may negatively alter existing vislib visualization configurations if saved.' - ); - const visualizationDependencies: Readonly = { - uiSettings: core.uiSettings, - charts, - }; + if (!core.uiSettings.get(LEGACY_CHARTS_LIBRARY, false)) { + setUISettings(core.uiSettings); + setThemeService(charts.theme); + setColorsService(charts.legacyColors); - const visTypeDefinitions: any[] = []; - const visFunctions: any = []; + [createVisTypeXyVisFn].forEach(expressions.registerFunction); + expressions.registerRenderer(xyVisRenderer); + visTypesDefinitions.forEach(visualizations.createBaseVisualization); + } - visFunctions.forEach((fn: any) => expressions.registerFunction(fn)); - visTypeDefinitions.forEach((vis: any) => - visualizations.createBaseVisualization(vis(visualizationDependencies)) - ); + setTrackUiMetric(usageCollection?.reportUiCounter.bind(usageCollection, 'vis_type_xy')); return {}; } - public start(core: CoreStart, deps: VisTypeXyPluginStartDependencies) { - // nothing to do here + public start(core: CoreStart, { data }: VisTypeXyPluginStartDependencies) { + setFormatService(data.fieldFormats); + setDataActions(data.actions); + setTimefilter(data.query.timefilter.timefilter); + setDocLinks(core.docLinks); + + return {}; } } diff --git a/src/plugins/vis_type_xy/public/services.ts b/src/plugins/vis_type_xy/public/services.ts new file mode 100644 index 000000000000..086cab8fb217 --- /dev/null +++ b/src/plugins/vis_type_xy/public/services.ts @@ -0,0 +1,54 @@ +/* + * 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 { UiCounterMetricType } from '@kbn/analytics'; +import { CoreSetup, DocLinksStart } from '../../../core/public'; +import { createGetterSetter } from '../../kibana_utils/public'; +import { DataPublicPluginStart } from '../../data/public'; +import { ChartsPluginSetup } from '../../charts/public'; + +export const [getUISettings, setUISettings] = createGetterSetter( + 'xy core.uiSettings' +); + +export const [getDataActions, setDataActions] = createGetterSetter< + DataPublicPluginStart['actions'] +>('xy data.actions'); + +export const [getFormatService, setFormatService] = createGetterSetter< + DataPublicPluginStart['fieldFormats'] +>('xy data.fieldFormats'); + +export const [getTimefilter, setTimefilter] = createGetterSetter< + DataPublicPluginStart['query']['timefilter']['timefilter'] +>('xy data.query.timefilter.timefilter'); + +export const [getThemeService, setThemeService] = createGetterSetter( + 'xy charts.theme' +); + +export const [getColorsService, setColorsService] = createGetterSetter< + ChartsPluginSetup['legacyColors'] +>('xy charts.color'); + +export const [getDocLinks, setDocLinks] = createGetterSetter('DocLinks'); + +export const [getTrackUiMetric, setTrackUiMetric] = createGetterSetter< + (metricType: UiCounterMetricType, eventName: string | string[]) => void +>('trackUiMetric'); diff --git a/src/plugins/vis_type_xy/public/to_ast.test.ts b/src/plugins/vis_type_xy/public/to_ast.test.ts new file mode 100644 index 000000000000..678a9faaec58 --- /dev/null +++ b/src/plugins/vis_type_xy/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 { sampleAreaVis } from '../../vis_type_vislib/public/sample_vis.test.mocks'; + +import { toExpressionAst } from './to_ast'; +import { VisParams } from './types'; + +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('xy 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_xy/public/to_ast.ts b/src/plugins/vis_type_xy/public/to_ast.ts new file mode 100644 index 000000000000..c93dbe46dca0 --- /dev/null +++ b/src/plugins/vis_type_xy/public/to_ast.ts @@ -0,0 +1,94 @@ +/* + * 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 { BUCKET_TYPES } from '../../data/public'; + +import { DateHistogramParams, Dimensions, HistogramParams, VisParams } from './types'; +import { visName, VisTypeXyExpressionFunctionDefinition } from './xy_vis_fn'; +import { XyVisType } from '../common'; +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().filter(({ enabled }) => enabled) ?? []; + + if (dimensions.x) { + const xAgg = responseAggs[dimensions.x.accessor] as any; + if (xAgg.type.name === BUCKET_TYPES.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(); + } else if (xAgg.type.name === BUCKET_TYPES.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[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 (usedValueAxis?.scale.mode === 'percentage') { + yDimension.format = { id: 'percent' }; + } + } + }); + + visConfig.dimensions = dimensions; + + const visTypeXy = buildExpressionFunction(visName, { + type: vis.type.name as XyVisType, + visConfig: JSON.stringify(visConfig), + }); + + const ast = buildExpression([getEsaggsFn(vis), visTypeXy]); + + return ast.toAst(); +}; diff --git a/src/plugins/vis_type_xy/public/to_ast_esaggs.ts b/src/plugins/vis_type_xy/public/to_ast_esaggs.ts new file mode 100644 index 000000000000..da8d11ac8340 --- /dev/null +++ b/src/plugins/vis_type_xy/public/to_ast_esaggs.ts @@ -0,0 +1,46 @@ +/* + * 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, buildExpressionFunction } from '../../expressions/public'; +import { + EsaggsExpressionFunctionDefinition, + IndexPatternLoadExpressionFunctionDefinition, +} from '../../data/public'; + +import { VisParams } from './types'; + +/** + * Get esaggs expressions function + * TODO: replace this with vis.data.aggs!.toExpressionAst(); + * https://github.com/elastic/kibana/issues/61768 + * @param vis + */ +export function getEsaggsFn(vis: Vis) { + return buildExpressionFunction('esaggs', { + index: buildExpression([ + buildExpressionFunction('indexPatternLoad', { + id: vis.data.indexPattern!.id!, + }), + ]), + metricsAtAllLevels: vis.isHierarchical(), + partialRows: false, + aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), + }); +} diff --git a/src/plugins/vis_type_xy/public/types/config.ts b/src/plugins/vis_type_xy/public/types/config.ts new file mode 100644 index 000000000000..ec73c0f6e3fc --- /dev/null +++ b/src/plugins/vis_type_xy/public/types/config.ts @@ -0,0 +1,130 @@ +/* + * 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 { + AxisSpec, + CustomTooltip, + Fit, + GridLineStyle, + Position, + Rotation, + SeriesScales, + TickFormatter, + TooltipProps, + TooltipValueFormatter, + YDomainRange, +} from '@elastic/charts'; + +import { Dimension, Scale, ThresholdLine } from './param'; + +export interface Column { + id: string | null; + name: string; +} + +export interface Aspect { + accessor: Column['id']; + aggType: string | null; + aggId: string | null; + column?: Dimension['accessor']; + title: Column['name']; + format?: Dimension['format']; + formatter?: TickFormatter; + params: Dimension['params']; +} + +export interface Aspects { + x: Aspect; + y: Aspect[]; + z?: Aspect; + series?: Aspect[]; +} + +export interface AxisGrid { + show?: boolean; + styles?: GridLineStyle; +} + +export interface TickOptions { + show?: boolean; + size?: number; + count?: number; + padding?: number; + formatter?: TickFormatter; + labelFormatter?: TickFormatter; + rotation?: number; + showDuplicates?: boolean; + integersOnly?: boolean; + showOverlappingTicks?: boolean; + showOverlappingLabels?: boolean; +} + +export type YScaleType = SeriesScales['yScaleType']; +export type XScaleType = SeriesScales['xScaleType']; + +export type ScaleConfig = Omit & { + type?: S; +}; + +export interface AxisConfig { + id: string; + groupId?: string; + position: Position; + ticks?: TickOptions; + show: boolean; + style: AxisSpec['style']; + scale: ScaleConfig; + domain?: YDomainRange; + title?: string; + grid?: AxisGrid; + integersOnly: boolean; +} + +export interface LegendOptions { + show: boolean; + position?: Position; +} + +export type ThresholdLineConfig = Omit & { + dash?: number[]; + groupId?: string; +}; + +export type TooltipConfig = Omit & { + detailedTooltip?: (headerFormatter?: TooltipValueFormatter) => CustomTooltip; +}; + +export interface VisConfig { + legend: LegendOptions; + tooltip: TooltipConfig; + xAxis: AxisConfig; + yAxes: Array>; + aspects: Aspects; + rotation: Rotation; + thresholdLine: ThresholdLineConfig; + orderBucketsBySum?: boolean; + showCurrentTime: boolean; + isTimeChart: boolean; + markSizeRatio: number; + showValueLabel: boolean; + enableHistogramMode: boolean; + fittingFunction?: Exclude; + detailedTooltip?: boolean; + isVislibVis?: boolean; +} diff --git a/src/plugins/vis_type_xy/public/types/constants.ts b/src/plugins/vis_type_xy/public/types/constants.ts new file mode 100644 index 000000000000..f92c56e43413 --- /dev/null +++ b/src/plugins/vis_type_xy/public/types/constants.ts @@ -0,0 +1,67 @@ +/* + * 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 { $Values } from '@kbn/utility-types'; + +export const ChartMode = Object.freeze({ + Normal: 'normal' as const, + Stacked: 'stacked' as const, +}); +export type ChartMode = $Values; + +export const InterpolationMode = Object.freeze({ + Linear: 'linear' as const, + Cardinal: 'cardinal' as const, + StepAfter: 'step-after' as const, +}); +export type InterpolationMode = $Values; + +export const AxisType = Object.freeze({ + Category: 'category' as const, + Value: 'value' as const, +}); +export type AxisType = $Values; + +export const ScaleType = Object.freeze({ + Linear: 'linear' as const, + Log: 'log' as const, + SquareRoot: 'square root' as const, +}); +export type ScaleType = $Values; + +export const AxisMode = Object.freeze({ + Normal: 'normal' as const, + Percentage: 'percentage' as const, + Wiggle: 'wiggle' as const, + Silhouette: 'silhouette' as const, +}); +export type AxisMode = $Values; + +export const ThresholdLineStyle = Object.freeze({ + Full: 'full' as const, + Dashed: 'dashed' as const, + DotDashed: 'dot-dashed' as const, +}); +export type ThresholdLineStyle = $Values; + +export const ColorMode = Object.freeze({ + Background: 'Background' as const, + Labels: 'Labels' as const, + None: 'None' as const, +}); +export type ColorMode = $Values; diff --git a/src/plugins/vis_type_xy/public/types/index.ts b/src/plugins/vis_type_xy/public/types/index.ts new file mode 100644 index 000000000000..791373def201 --- /dev/null +++ b/src/plugins/vis_type_xy/public/types/index.ts @@ -0,0 +1,23 @@ +/* + * 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 * from './constants'; +export * from './config'; +export * from './param'; +export * from './vis_type'; diff --git a/src/plugins/vis_type_xy/public/types/param.ts b/src/plugins/vis_type_xy/public/types/param.ts new file mode 100644 index 000000000000..c8cd020dec03 --- /dev/null +++ b/src/plugins/vis_type_xy/public/types/param.ts @@ -0,0 +1,160 @@ +/* + * 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 { Fit, Position } from '@elastic/charts'; + +import { Style, Labels } from '../../../charts/public'; +import { SchemaConfig } from '../../../visualizations/public'; + +import { ChartType } from '../../common'; +import { + ChartMode, + AxisMode, + AxisType, + InterpolationMode, + ScaleType, + ThresholdLineStyle, +} from './constants'; + +export interface Scale { + boundsMargin?: number | ''; + defaultYExtents?: boolean; + max?: number | null; + min?: number | null; + mode?: AxisMode; + setYExtents?: boolean; + type: ScaleType; +} + +export interface CategoryAxis { + id: string; + labels: Labels; + position: Position; + scale: Scale; + show: boolean; + title: { + text?: string; + }; + type: AxisType; + /** + * Used only for heatmap, here for consistent types when used in vis_type_vislib + * + * remove with vis_type_vislib + * https://github.com/elastic/kibana/issues/56143 + */ + style: Partial