diff --git a/.ci/Jenkinsfile_flaky b/.ci/Jenkinsfile_flaky
index 3f77243da2c1b..e1cbac0528b1f 100644
--- a/.ci/Jenkinsfile_flaky
+++ b/.ci/Jenkinsfile_flaky
@@ -8,26 +8,28 @@ def JOB_PARTS = params.CI_GROUP.split(':')
def IS_XPACK = JOB_PARTS[0] == 'xpack'
def JOB = JOB_PARTS[1]
def CI_GROUP = JOB_PARTS.size() > 2 ? JOB_PARTS[2] : ''
+def EXECUTIONS = params.NUMBER_EXECUTIONS.toInteger()
+def AGENT_COUNT = getAgentCount(EXECUTIONS)
def worker = getWorkerFromParams(IS_XPACK, JOB, CI_GROUP)
def workerFailures = []
currentBuild.displayName += trunc(" ${params.GITHUB_OWNER}:${params.branch_specifier}", 24)
-currentBuild.description = "${params.CI_GROUP} Executions: ${params.NUMBER_EXECUTIONS}"
-
-// Note: If you increase agent count, it will execute NUMBER_EXECUTIONS per agent. It will not divide them up amongst the agents
-// e.g. NUMBER_EXECUTIONS = 25, agentCount = 4 results in 100 total executions
-def agentCount = 1
+currentBuild.description = "${params.CI_GROUP} Agents: ${AGENT_COUNT} Executions: ${params.NUMBER_EXECUTIONS}"
stage("Kibana Pipeline") {
timeout(time: 180, unit: 'MINUTES') {
timestamps {
ansiColor('xterm') {
def agents = [:]
- for(def agentNumber = 1; agentNumber <= agentCount; agentNumber++) {
+ for(def agentNumber = 1; agentNumber <= AGENT_COUNT; agentNumber++) {
+ def agentNumberInside = agentNumber
+ def agentExecutions = floor(EXECUTIONS/AGENT_COUNT) + (agentNumber <= EXECUTIONS%AGENT_COUNT ? 1 : 0)
agents["agent-${agentNumber}"] = {
catchError {
+ print "Agent ${agentNumberInside} - ${agentExecutions} executions"
+
kibanaPipeline.withWorkers('flaky-test-runner', {
if (!IS_XPACK) {
kibanaPipeline.buildOss()
@@ -37,7 +39,7 @@ stage("Kibana Pipeline") {
} else {
kibanaPipeline.buildXpack()
}
- }, getWorkerMap(agentNumber, params.NUMBER_EXECUTIONS.toInteger(), worker, workerFailures))()
+ }, getWorkerMap(agentNumberInside, agentExecutions, worker, workerFailures))()
}
}
}
@@ -77,9 +79,9 @@ def getWorkerFromParams(isXpack, job, ciGroup) {
}
}
-def getWorkerMap(agentNumber, numberOfExecutions, worker, workerFailures, maxWorkers = 14) {
+def getWorkerMap(agentNumber, numberOfExecutions, worker, workerFailures, maxWorkerProcesses = 12) {
def workerMap = [:]
- def numberOfWorkers = Math.min(numberOfExecutions, maxWorkers)
+ def numberOfWorkers = Math.min(numberOfExecutions, maxWorkerProcesses)
for(def i = 1; i <= numberOfWorkers; i++) {
def workerExecutions = numberOfExecutions/numberOfWorkers + (i <= numberOfExecutions%numberOfWorkers ? 1 : 0)
@@ -87,7 +89,10 @@ def getWorkerMap(agentNumber, numberOfExecutions, worker, workerFailures, maxWor
workerMap["agent-${agentNumber}-worker-${i}"] = { workerNumber ->
for(def j = 0; j < workerExecutions; j++) {
print "Execute agent-${agentNumber} worker-${workerNumber}: ${j}"
- withEnv(["JOB=agent-${agentNumber}-worker-${workerNumber}-${j}"]) {
+ withEnv([
+ "JOB=agent-${agentNumber}-worker-${workerNumber}-${j}",
+ "REMOVE_KIBANA_INSTALL_DIR=1",
+ ]) {
catchError {
try {
worker(workerNumber)
@@ -104,6 +109,11 @@ def getWorkerMap(agentNumber, numberOfExecutions, worker, workerFailures, maxWor
return workerMap
}
+def getAgentCount(executions) {
+ // Increase agent count every 24 worker processess, up to 3 agents maximum
+ return Math.min(3, 1 + floor(executions/24))
+}
+
def trunc(str, length) {
if (str.size() >= length) {
return str.take(length) + "..."
@@ -111,3 +121,11 @@ def trunc(str, length) {
return str;
}
+
+// All of the real rounding/truncating methods are sandboxed
+def floor(num) {
+ return num
+ .toString()
+ .split('\\.')[0]
+ .toInteger()
+}
diff --git a/.ci/jobs.yml b/.ci/jobs.yml
index fc3e80064fa6f..a2d8100f78efd 100644
--- a/.ci/jobs.yml
+++ b/.ci/jobs.yml
@@ -14,7 +14,8 @@ JOB:
- kibana-ciGroup10
- kibana-ciGroup11
- kibana-ciGroup12
- # - kibana-visualRegression
+ - kibana-accessibility
+ - kibana-visualRegression
# make sure all x-pack-ciGroups are listed in test/scripts/jenkins_xpack_ci_group.sh
- x-pack-firefoxSmoke
@@ -28,7 +29,8 @@ JOB:
- x-pack-ciGroup8
- x-pack-ciGroup9
- x-pack-ciGroup10
- # - x-pack-visualRegression
+ - x-pack-accessibility
+ - x-pack-visualRegression
# `~` is yaml for `null`
exclude: ~
diff --git a/.ci/run.sh b/.ci/run.sh
index 88ce0bd9986a1..9f77438be62d0 100755
--- a/.ci/run.sh
+++ b/.ci/run.sh
@@ -21,6 +21,9 @@ kibana-ciGroup*)
kibana-visualRegression*)
./test/scripts/jenkins_visual_regression.sh
;;
+kibana-accessibility*)
+ ./test/scripts/jenkins_accessibility.sh
+ ;;
kibana-firefoxSmoke*)
./test/scripts/jenkins_firefox_smoke.sh
;;
@@ -34,6 +37,9 @@ x-pack-ciGroup*)
x-pack-visualRegression*)
./test/scripts/jenkins_xpack_visual_regression.sh
;;
+x-pack-accessibility*)
+ ./test/scripts/jenkins_xpack_accessibility.sh
+ ;;
x-pack-firefoxSmoke*)
./test/scripts/jenkins_xpack_firefox_smoke.sh
;;
diff --git a/.eslintrc.js b/.eslintrc.js
index 22d8e67ea702d..16a80f01278a5 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -55,6 +55,193 @@ module.exports = {
extends: ['@elastic/eslint-config-kibana', 'plugin:@elastic/eui/recommended'],
overrides: [
+ /**
+ * Temporarily disable some react rules for specific plugins, remove in separate PRs
+ */
+ {
+ files: ['packages/kbn-ui-framework/**/*.{js,ts,tsx}'],
+ rules: {
+ 'jsx-a11y/no-onchange': 'off',
+ },
+ },
+ {
+ files: ['src/core/public/application/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react/no-danger': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/console/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/data/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/expressions/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/kbn_vislib_vis_types/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/kibana/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/rules-of-hooks': 'off',
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/tile_map/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/vis_type_markdown/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/vis_type_metric/**/*.{js,ts,tsx}'],
+ rules: {
+ 'jsx-a11y/click-events-have-key-events': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/vis_type_table/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/core_plugins/vis_type_vega/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/legacy/ui/public/vis/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/plugins/es_ui_shared/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/plugins/eui_utils/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/plugins/kibana_react/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/rules-of-hooks': 'off',
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['src/plugins/kibana_utils/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/canvas/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ 'jsx-a11y/click-events-have-key-events': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/cross_cluster_replication/**/*.{js,ts,tsx}'],
+ rules: {
+ 'jsx-a11y/click-events-have-key-events': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/graph/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/index_management/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ 'react-hooks/rules-of-hooks': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/infra/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ 'react-hooks/rules-of-hooks': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/lens/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ 'react-hooks/rules-of-hooks': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/ml/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/monitoring/**/*.{js,ts,tsx}'],
+ rules: {
+ 'jsx-a11y/click-events-have-key-events': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/siem/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ 'react-hooks/rules-of-hooks': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/snapshot_restore/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/uptime/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/exhaustive-deps': 'off',
+ 'react-hooks/rules-of-hooks': 'off',
+ },
+ },
+ {
+ files: ['x-pack/legacy/plugins/watcher/**/*.{js,ts,tsx}'],
+ rules: {
+ 'react-hooks/rules-of-hooks': 'off',
+ 'react-hooks/exhaustive-deps': 'off',
+ },
+ },
+
/**
* Prettier
*/
@@ -175,10 +362,10 @@ module.exports = {
'!src/core/server/*.test.mocks.ts',
'src/plugins/**/public/**/*',
- '!src/plugins/**/public/index*',
+ '!src/plugins/**/public/index.{js,ts,tsx}',
'src/plugins/**/server/**/*',
- '!src/plugins/**/server/index*',
+ '!src/plugins/**/server/index.{js,ts,tsx}',
],
allowSameFolder: true,
},
@@ -213,6 +400,7 @@ module.exports = {
'x-pack/test/functional/apps/**/*.js',
'x-pack/legacy/plugins/apm/**/*.js',
'test/*/config.ts',
+ 'test/*/{tests,test_suites,apis,apps}/**/*',
'test/visual_regression/tests/**/*',
'x-pack/test/*/{tests,test_suites,apis,apps}/**/*',
'x-pack/test/*/*config.*ts',
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 7001e32754abb..94296d076189b 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -8,9 +8,14 @@
# App Architecture
/src/plugins/data/ @elastic/kibana-app-arch
-/src/plugins/kibana_utils/ @elastic/kibana-app-arch
+/src/plugins/embeddable/ @elastic/kibana-app-arch
+/src/plugins/expressions/ @elastic/kibana-app-arch
/src/plugins/kibana_react/ @elastic/kibana-app-arch
+/src/plugins/kibana_utils/ @elastic/kibana-app-arch
/src/plugins/navigation/ @elastic/kibana-app-arch
+/src/plugins/ui_actions/ @elastic/kibana-app-arch
+/src/plugins/visualizations/ @elastic/kibana-app-arch
+/x-pack/plugins/advanced_ui_actions/ @elastic/kibana-app-arch
# APM
/x-pack/legacy/plugins/apm/ @elastic/apm-ui
@@ -37,7 +42,9 @@
/x-pack/test/functional/apps/machine_learning/ @elastic/ml-ui
/x-pack/test/functional/services/machine_learning/ @elastic/ml-ui
/x-pack/test/functional/services/ml.ts @elastic/ml-ui
-/x-pack/legacy/plugins/transform/ @elastic/ml-ui
+# ML team owns the transform plugin, ES team added here for visibility
+# because the plugin lives in Kibana's Elasticsearch management section.
+/x-pack/legacy/plugins/transform/ @elastic/ml-ui @elastic/es-ui
# Operations
/renovate.json5 @elastic/kibana-operations
@@ -56,11 +63,14 @@
/src/legacy/server/saved_objects/ @elastic/kibana-platform
/config/kibana.yml @elastic/kibana-platform
/x-pack/plugins/features/ @elastic/kibana-platform
+/x-pack/plugins/licensing/ @elastic/kibana-platform
# Security
/x-pack/legacy/plugins/security/ @elastic/kibana-security
/x-pack/legacy/plugins/spaces/ @elastic/kibana-security
+/x-pack/plugins/spaces/ @elastic/kibana-security
/x-pack/legacy/plugins/encrypted_saved_objects/ @elastic/kibana-security
+/x-pack/plugins/encrypted_saved_objects/ @elastic/kibana-security
/src/legacy/server/csp/ @elastic/kibana-security
/x-pack/plugins/security/ @elastic/kibana-security
/x-pack/test/api_integration/apis/security/ @elastic/kibana-security
@@ -88,9 +98,6 @@
/x-pack/legacy/plugins/rollup/ @elastic/es-ui
/x-pack/legacy/plugins/searchprofiler/ @elastic/es-ui
/x-pack/legacy/plugins/snapshot_restore/ @elastic/es-ui
-# ML team owns the transform plugin, ES team added here for visibility
-# because the plugin lives in Kibana's Elasticsearch management section.
-/x-pack/legacy/plugins/transform/ @elastic/es-ui
/x-pack/legacy/plugins/watcher/ @elastic/es-ui
# Kibana TSVB external contractors
diff --git a/.i18nrc.json b/.i18nrc.json
index d77293e3dc8f7..01065201b9d64 100644
--- a/.i18nrc.json
+++ b/.i18nrc.json
@@ -1,37 +1,39 @@
{
"paths": {
"common.ui": "src/legacy/ui",
- "data": ["src/legacy/core_plugins/data", "src/plugins/data"],
- "expressions": "src/legacy/core_plugins/expressions",
- "kibana_react": "src/legacy/core_plugins/kibana_react",
- "navigation": "src/legacy/core_plugins/navigation",
- "server": "src/legacy/server",
"console": "src/legacy/core_plugins/console",
"core": "src/core",
+ "dashboardEmbeddableContainer": "src/plugins/dashboard_embeddable_container",
+ "data": ["src/legacy/core_plugins/data", "src/plugins/data"],
+ "embeddableApi": "src/plugins/embeddable",
+ "esUi": "src/plugins/es_ui_shared",
+ "expressions_np": "src/plugins/expressions",
+ "expressions": "src/legacy/core_plugins/expressions",
"inputControl": "src/legacy/core_plugins/input_control_vis",
+ "inspector": "src/plugins/inspector",
"inspectorViews": "src/legacy/core_plugins/inspector_views",
"interpreter": "src/legacy/core_plugins/interpreter",
- "dashboardEmbeddableContainer": "src/legacy/core_plugins/dashboard_embeddable_container",
"kbn": "src/legacy/core_plugins/kibana",
"kbnDocViews": "src/legacy/core_plugins/kbn_doc_views",
- "embeddableApi": "src/plugins/embeddable",
+ "kbnESQuery": "packages/kbn-es-query",
"kbnVislibVisTypes": "src/legacy/core_plugins/kbn_vislib_vis_types",
- "visTypeMarkdown": "src/legacy/core_plugins/vis_type_markdown",
- "visTypeMetric": "src/legacy/core_plugins/vis_type_metric",
- "visTypeVega": "src/legacy/core_plugins/vis_type_vega",
- "visTypeTable": "src/legacy/core_plugins/vis_type_table",
+ "kibana_react": "src/legacy/core_plugins/kibana_react",
+ "kibana-react": "src/plugins/kibana_react",
+ "navigation": "src/legacy/core_plugins/navigation",
"regionMap": "src/legacy/core_plugins/region_map",
+ "server": "src/legacy/server",
"statusPage": "src/legacy/core_plugins/status_page",
+ "telemetry": "src/legacy/core_plugins/telemetry",
"tileMap": "src/legacy/core_plugins/tile_map",
"timelion": "src/legacy/core_plugins/timelion",
+ "uiActions": "src/plugins/ui_actions",
+ "visTypeMarkdown": "src/legacy/core_plugins/vis_type_markdown",
+ "visTypeMetric": "src/legacy/core_plugins/vis_type_metric",
+ "visTypeTable": "src/legacy/core_plugins/vis_type_table",
"visTypeTagCloud": "src/legacy/core_plugins/vis_type_tagcloud",
"visTypeTimeseries": "src/legacy/core_plugins/vis_type_timeseries",
- "kbnESQuery": "packages/kbn-es-query",
- "inspector": "src/plugins/inspector",
- "kibana-react": "src/plugins/kibana_react",
- "telemetry": "src/legacy/core_plugins/telemetry",
- "esUi": "src/plugins/es_ui_shared",
- "uiActions": "src/plugins/ui_actions"
+ "visTypeVega": "src/legacy/core_plugins/vis_type_vega",
+ "visualizations": "src/plugins/visualizations"
},
"exclude": ["src/legacy/ui/ui_render/ui_render_mixin.js"],
"translations": []
diff --git a/Jenkinsfile b/Jenkinsfile
index 4820de9876737..8d8579736f639 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -25,7 +25,8 @@ stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a
'oss-ciGroup11': kibanaPipeline.getOssCiGroupWorker(11),
'oss-ciGroup12': kibanaPipeline.getOssCiGroupWorker(12),
'oss-firefoxSmoke': kibanaPipeline.getPostBuildWorker('firefoxSmoke', { runbld './test/scripts/jenkins_firefox_smoke.sh' }),
- // 'oss-visualRegression': kibanaPipeline.getPostBuildWorker('visualRegression', { runbld './test/scripts/jenkins_visual_regression.sh' }),
+ 'oss-accessibility': kibanaPipeline.getPostBuildWorker('accessibility', { runbld './test/scripts/jenkins_accessibility.sh' }),
+ 'oss-visualRegression': kibanaPipeline.getPostBuildWorker('visualRegression', { runbld './test/scripts/jenkins_visual_regression.sh' }),
]),
'kibana-xpack-agent': kibanaPipeline.withWorkers('kibana-xpack-tests', { kibanaPipeline.buildXpack() }, [
'xpack-ciGroup1': kibanaPipeline.getXpackCiGroupWorker(1),
@@ -39,7 +40,8 @@ stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a
'xpack-ciGroup9': kibanaPipeline.getXpackCiGroupWorker(9),
'xpack-ciGroup10': kibanaPipeline.getXpackCiGroupWorker(10),
'xpack-firefoxSmoke': kibanaPipeline.getPostBuildWorker('xpack-firefoxSmoke', { runbld './test/scripts/jenkins_xpack_firefox_smoke.sh' }),
- // 'xpack-visualRegression': kibanaPipeline.getPostBuildWorker('xpack-visualRegression', { runbld './test/scripts/jenkins_xpack_visual_regression.sh' }),
+ 'xpack-accessibility': kibanaPipeline.getPostBuildWorker('xpack-accessibility', { runbld './test/scripts/jenkins_xpack_accessibility.sh' }),
+ 'xpack-visualRegression': kibanaPipeline.getPostBuildWorker('xpack-visualRegression', { runbld './test/scripts/jenkins_xpack_visual_regression.sh' }),
]),
])
}
diff --git a/README.md b/README.md
index 2d33cd218b3da..03ce6a6525873 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@ _Note: The version numbers below are only examples, meant to illustrate the rela
## Questions? Problems? Suggestions?
-- If you've found a bug or want to request a feature, please create a [GitHub Issue](https://github.com/elastic/kibana/issues/new).
-Please check to make sure someone else hasn't already created an issue for the same topic.
+- If you've found a bug or want to request a feature, please create a [GitHub Issue](https://github.com/elastic/kibana/issues/new/choose).
+ Please check to make sure someone else hasn't already created an issue for the same topic.
- Need help using Kibana? Ask away on our [Kibana Discuss Forum](https://discuss.elastic.co/c/kibana) and a fellow community member or
Elastic engineer will be glad to help you out.
diff --git a/docs/canvas/canvas-expressions.asciidoc b/docs/canvas/canvas-expressions.asciidoc
deleted file mode 100644
index 0fcc69c6db726..0000000000000
--- a/docs/canvas/canvas-expressions.asciidoc
+++ /dev/null
@@ -1,39 +0,0 @@
-[[canvas-expression-editor]]
-=== Customize your element with the expression editor
-
-Each element is backed by an expression that represents the element style and data. To further define the appearance and behavior of the element, use the expression editor.
-
-. In the lower right corner, click *Expression editor*.
-
-. Edit the style and data parts of the expression that you want to change.
-
-. Click *Run*.
-
-. If you like what you see, click *Close*.
-
-For information about the Canvas expression language, see <>.
-
-//Insert expression video.
-
-[float]
-[[canvas-expression-editor-example]]
-=== Example: Using the expression editor
-
-Build a complex element using expressions.
-
-```
-image mode="contain" dataurl={
-asset {
-filters | essql
-query="SELECT host,response
-FROM kibana_sample_data_logs
-WHERE host='artifacts.elastic.co'
-ORDER BY timestamp DESC
-LIMIT 1"|
-alterColumn "response" type="number" |
-getCell "response" |
-if {compare lt to=400} then="asset-0a807073-d056-4c7b-9bf4-225b71e47243" else="asset-1343672d-7c02-4402-929e-0f8fef69cddd"
-}
-} | render
-
-```
\ No newline at end of file
diff --git a/docs/canvas/canvas-share-workpad.asciidoc b/docs/canvas/canvas-share-workpad.asciidoc
index 5cc5b953e5775..119ede16fe1e7 100644
--- a/docs/canvas/canvas-share-workpad.asciidoc
+++ b/docs/canvas/canvas-share-workpad.asciidoc
@@ -2,47 +2,100 @@
[[workpad-share-options]]
== Share your workpad
-When you are ready to share your workpad, create a PDF, or export your workpad.
+When you've finished your workpad, you can share it outside of {kib}.
+
+[float]
+[[export-single-workpad]]
+=== Export workpads
+
+Create a JSON file of your workpad that you can export outside of {kib}.
+
+. From your workpad, click the *Share workpad* icon in the upper left corner.
+
+. Select *Download as JSON*.
++
+[role="screenshot"]
+image::images/canvas-export-workpad.png[Export single workpad]
+
+Want to export multiple workpads? Go to the *Canvas workpads* view, select the workpads you want to export, then click *Export*.
[float]
[[create-workpad-pdf]]
=== Create a PDF
-To view your workpad outside of Kibana, generate a PDF.
+Create a PDF copy of your workpad that you can save and share outside of {kib}.
. If you are using a Gold or Platinum license, enable reporting in your `config/kibana.yml` file.
. From your workpad, click the *Share workpad* icon in the upper left corner, then select *PDF reports*.
-. Click *Generate PDF*.
+. Click *Generate PDF*.
+
[role="screenshot"]
image::images/canvas-generate-pdf.gif[Generate PDF]
[float]
-[[export-workpad]]
-=== Export your workpad
+[[create-workpad-URL]]
+=== Create a POST URL
+
+Create a POST URL that you can use to automatically generate PDF reports using Watcher or a script.
+
+For more information, refer to <>.
+
+. If you are using a Gold or Platinum license, enable reporting in your `config/kibana.yml` file.
+
+. From your workpad, click the *Share workpad* icon in the upper left corner, then select *PDF reports*.
-To share your workpad with another author, export it as a JSON file.
+. Click *Copy POST URL*.
++
+[role="screenshot"]
+image::images/canvas-create-URL.gif[Create POST URL]
[float]
-[[export-single-workpad]]
-==== Export a single workpad
+[[add-workpad-website]]
+=== Share the workpad on a website
-. From your workpad, click the *Share workpad* icon in the upper left corner.
+beta[] Download the workpad and share it on any website, then customize the workpad behavior to autoplay the pages or hide the toolbar.
-. Select *Download as JSON*.
+. If you are using a Gold or Platinum license, enable reporting in your `config/kibana.yml` file.
+
+. From your workpad, click the *Share this workpad* icon in the upper left corner, then select *Share on a website*.
+
+. On the *Share on a website* pane, follow the instructions.
+
+. To customize the workpad behavior to autoplay the pages or hide the toolbar, use the inline parameters.
++
+To make sure that your data remains secure, the data in the JSON file is not connected to {kib}. Canvas does not display elements that manipulate the data on the workpad.
+
[role="screenshot"]
-image::images/canvas-export-workpad.png[Export single workpad]
+image::images/canvas-embed_workpad.gif[Share the workpad on a website]
++
+NOTE: Shareable workpads encode the current state of the workpad in a JSON file. When you make changes to the workpad, the changes do not appear in the shareable workpad on your website.
[float]
-[[export-multiple-workpads]]
-==== Export multiple workpads
+[[change-the-workpad-settings]]
+=== Change the shareable workpad settings
-. Go to the *Canvas workpads* page.
+After you've added the workpad to your website, you can change the autoplay and toolbar settings.
-. Select the workpads you want to export
+[float]
+[[shareable-workpad-enable-autoplay]]
+==== Change the autoplay settings
-. Click *Export*.
+. In the lower right corner of the shareable workpad, click the settings icon.
+. Click *Auto Play*, then change the settings.
++
+[role="screenshot"]
+image::images/canvas_share_autoplay_480.gif[Autoplay settings]
+
+[float]
+[[hide-workpad-toolbar]]
+==== Change the toolbar settings
+
+. In the lower right corner, click the settings icon.
+
+. Click *Toolbar*, then change the settings.
++
+[role="screenshot"]
+image::images/canvas_share_hidetoolbar_480.gif[Hide toolbar settings]
diff --git a/docs/canvas/canvas-workpad.asciidoc b/docs/canvas/canvas-workpad.asciidoc
index f664f055a5ff6..f833bd903b0bc 100644
--- a/docs/canvas/canvas-workpad.asciidoc
+++ b/docs/canvas/canvas-workpad.asciidoc
@@ -18,17 +18,17 @@ To create a workpad, you can:
[[blank-canvas-workpad]]
=== Start with a blank page
-To use the background colors, images, and data of your choice, start with a blank workpad.
+To use the background colors, images, and data of your choice, start with a blank workpad.
. Open *Canvas*.
-. On the *Canvas workpads* page, click *Create workpad*.
+. On the *Canvas workpads* view, click *Create workpad*.
. Add a *Name* to your workpad.
-. In the *Width* and *Height* fields, specify the size.
+. In the *Width* and *Height* fields, specify the size.
-. Select the layout.
+. Select the layout.
+
For example, click *720p* for a traditional presentation layout.
@@ -45,7 +45,7 @@ If you're unsure about where to start, you can use one of the preconfigured temp
. Open *Canvas*.
-. On the *Canvas workpads* page, select *Templates*.
+. On the *Canvas workpads* view, select *Templates*.
. Click the preconfigured template that you want to use.
@@ -59,7 +59,7 @@ When you want to use a workpad that someone else has already started, import the
. Open *Canvas*.
-. On the *Canvas workpads* page, click and drag the file to the *Import workpad JSON file* field.
+. On the *Canvas workpads* view, click and drag the file to the *Import workpad JSON file* field.
[float]
[[sample-data-workpad]]
@@ -67,11 +67,11 @@ When you want to use a workpad that someone else has already started, import the
Each of the sample data sets comes with a Canvas workpad that you can use for your own workpad inspiration.
-. Add a {kibana-ref}/add-sample-data.html[sample data set].
+. Add a {kibana-ref}/add-sample-data.html[sample data set].
. On the *Add Data to Kibana* page, click the *View data* dropdown list, then select *Canvas*.
+
-Need some more workpad inspiration? Check out the link:https://www.elastic.co/blog/[Elastic Blog].
+Need some more workpad inspiration? Check out the link:https://www.elastic.co/blog/[Elastic Blog].
[float]
[[apply-workpad-styles]]
diff --git a/docs/discover/kuery.asciidoc b/docs/discover/kuery.asciidoc
index a87b8d5a78604..abf3e05fb7819 100644
--- a/docs/discover/kuery.asciidoc
+++ b/docs/discover/kuery.asciidoc
@@ -73,3 +73,87 @@ set these terms will be matched against all fields. For example, a query for `re
in the response field, but a query for just `200` will search for 200 across all fields in your index.
============
+===== Nested Field Support
+
+KQL supports querying on {ref}/nested.html[nested fields] through a special syntax. You can query nested fields in subtly different
+ways, depending on the results you want, so crafting nested queries requires extra thought.
+
+One main consideration is how to match parts of the nested query to the individual nested documents.
+There are two main approaches to take:
+
+* *Parts of the query may only match a single nested document.* This is what most users want when querying on a nested field.
+* *Parts of the query can match different nested documents.* This is how a regular object field works.
+ Although generally less useful, there might be occasions where you want to query a nested field in this way.
+
+Let's take a look at the first approach. In the following document, `items` is a nested field:
+
+[source,json]
+----------------------------------
+{
+ "grocery_name": "Elastic Eats",
+ "items": [
+ {
+ "name": "banana",
+ "stock": "12",
+ "category": "fruit"
+ },
+ {
+ "name": "peach",
+ "stock": "10",
+ "category": "fruit"
+ },
+ {
+ "name": "carrot",
+ "stock": "9",
+ "category": "vegetable"
+ },
+ {
+ "name": "broccoli",
+ "stock": "5",
+ "category": "vegetable"
+ }
+ ]
+}
+----------------------------------
+
+To find stores that have more than 10 bananas in stock, you would write a query like this:
+
+`items:{ name:banana and stock > 10 }`
+
+`items` is the "nested path". Everything inside the curly braces (the "nested group") must match a single document.
+For example, `items:{ name:banana and stock:9 }` does not match because there isn't a single nested document that
+matches the entire query in the nested group.
+
+What if you want to find a store with more than 10 bananas that *also* stocks vegetables? This is the second way of querying a nested field, and you can do it like this:
+
+`items:{ name:banana and stock > 10 } and items:{ category:vegetable }`
+
+The first nested group (`name:banana and stock > 10`) must still match a single document, but the `category:vegetables`
+subquery can match a different nested document because it is in a separate group.
+
+KQL's syntax also supports nested fields inside of other nested fields—you simply have to specify the full path. Suppose you
+have a document where `level1` and `level2` are both nested fields:
+
+[source,json]
+----------------------------------
+{
+ "level1": [
+ {
+ "level2": [
+ {
+ "prop1": "foo",
+ "prop2": "bar"
+ },
+ {
+ "prop1": "baz",
+ "prop2": "qux"
+ }
+ ]
+ }
+ ]
+}
+----------------------------------
+
+You can match on a single nested document by specifying the full path:
+
+`level1.level2:{ prop1:foo and prop2:bar }`
diff --git a/docs/images/canvas-create-URL.gif b/docs/images/canvas-create-URL.gif
new file mode 100644
index 0000000000000..c7dfab28c681e
Binary files /dev/null and b/docs/images/canvas-create-URL.gif differ
diff --git a/docs/images/canvas-embed_workpad.gif b/docs/images/canvas-embed_workpad.gif
new file mode 100644
index 0000000000000..0ffbdeab2862d
Binary files /dev/null and b/docs/images/canvas-embed_workpad.gif differ
diff --git a/docs/images/canvas-export-workpad.png b/docs/images/canvas-export-workpad.png
index 687c8a121b65a..fa910daf948d7 100644
Binary files a/docs/images/canvas-export-workpad.png and b/docs/images/canvas-export-workpad.png differ
diff --git a/docs/images/canvas-generate-pdf.gif b/docs/images/canvas-generate-pdf.gif
index 6d60f948de77a..a51e04cb623a6 100644
Binary files a/docs/images/canvas-generate-pdf.gif and b/docs/images/canvas-generate-pdf.gif differ
diff --git a/docs/images/canvas_share_autoplay_480.gif b/docs/images/canvas_share_autoplay_480.gif
new file mode 100644
index 0000000000000..da6d8c74dd5ca
Binary files /dev/null and b/docs/images/canvas_share_autoplay_480.gif differ
diff --git a/docs/images/canvas_share_hidetoolbar_480.gif b/docs/images/canvas_share_hidetoolbar_480.gif
new file mode 100644
index 0000000000000..6206714aa2804
Binary files /dev/null and b/docs/images/canvas_share_hidetoolbar_480.gif differ
diff --git a/docs/infrastructure/getting-started.asciidoc b/docs/infrastructure/getting-started.asciidoc
index 1c5645f5a6e4e..7122ad5c19f75 100644
--- a/docs/infrastructure/getting-started.asciidoc
+++ b/docs/infrastructure/getting-started.asciidoc
@@ -1,6 +1,6 @@
[role="xpack"]
[[xpack-metrics-getting-started]]
-== Getting started with infrastructure monitoring
+== Getting started with metrics
To get started with the Metrics app in Kibana, you need to start collecting metrics data for your infrastructure.
@@ -8,4 +8,4 @@ Kibana provides step-by-step instructions to help you add metrics data.
The {metrics-guide}[Metrics Monitoring Guide] is a good source for more detailed information and instructions.
[role="screenshot"]
-image::infrastructure/images/metrics-add-data.png[Screenshot showing Add metric data to Kibana UI]
+image::infrastructure/images/metrics-add-data.png[Screenshot showing Add metric data to Kibana]
diff --git a/docs/infrastructure/index.asciidoc b/docs/infrastructure/index.asciidoc
index 17361ef6a6080..5e2d0f3e757b0 100644
--- a/docs/infrastructure/index.asciidoc
+++ b/docs/infrastructure/index.asciidoc
@@ -4,13 +4,13 @@
[partintro]
--
-The Metrics app enables you to monitor your infrastructure and identify problems in real time.
+The Metrics app enables you to monitor your infrastructure metrics and identify problems in real time.
You start with a visual summary of your infrastructure where you can view basic metrics for common servers, containers, and services.
Then you can drill down to view more detailed metrics or other information for that component.
You can:
-* View an inventory of your infrastructure by hosts, Kubernetes pod or Docker containers.
+* View your infrastructure metrics by hosts, Kubernetes pods or Docker containers.
You can group and filter the data in various ways to help you identify the items that interest you.
* View current and historic values for metrics such as CPU usage, memory usage, and network traffic for each component.
diff --git a/docs/infrastructure/infra-ui.asciidoc b/docs/infrastructure/infra-ui.asciidoc
index 5c8c50a978d63..120a22541717c 100644
--- a/docs/infrastructure/infra-ui.asciidoc
+++ b/docs/infrastructure/infra-ui.asciidoc
@@ -2,12 +2,12 @@
[[infra-ui]]
== Using the Metrics app
-Use the Metrics app in {kib} to monitor your infrastructure and identify problems in real time.
+Use the Metrics app in {kib} to monitor your infrastructure metrics and identify problems in real time.
You can explore metrics for hosts, containers, and services.
You can also drill down to view more detailed metrics, or seamlessly switch to view the corresponding logs, application traces, and uptime information.
Initially, the *Inventory* tab shows an overview of the hosts in of your infrastructure and the current CPU usage for each host.
-From here, you can drill down into areas of interest.
+From here, you can view other metrics or drill down into areas of interest.
[role="screenshot"]
image::infrastructure/images/infra-sysmon.png[Infrastructure Overview in Kibana]
diff --git a/docs/infrastructure/metrics-explorer.asciidoc b/docs/infrastructure/metrics-explorer.asciidoc
index 2919eaa976d6a..c20718dac1c7a 100644
--- a/docs/infrastructure/metrics-explorer.asciidoc
+++ b/docs/infrastructure/metrics-explorer.asciidoc
@@ -15,7 +15,7 @@ image::infrastructure/images/metrics-explorer-screen.png[Metrics Explorer in Kib
* Metrics Explorer uses data collected from {metricbeat-ref}/metricbeat-overview.html[Metricbeat].
* You need read permissions on `metricbeat-*` or the metric index specified in the Metrics configuration.
-* Metrics Explorer uses the timestamp field set in the Infrastructure configuration.
+* Metrics Explorer uses the timestamp field from the *Settings* tab.
By default that is set to `@timestamp`.
* The interval for the X Axis is set to `auto`.
The bucket size is determined by the time range.
diff --git a/docs/logs/using.asciidoc b/docs/logs/using.asciidoc
index 65693f4399e53..916ad42a6d221 100644
--- a/docs/logs/using.asciidoc
+++ b/docs/logs/using.asciidoc
@@ -17,7 +17,7 @@ image::logs/images/logs-console.png[Logs Console in Kibana]
Use the search bar to perform ad hoc searches for specific text.
You can also create structured queries using {kibana-ref}/kuery-query.html[Kibana Query Language].
For example, enter `host.hostname : "host1"` to see only the information for `host1`.
-// ++ this isn't quite the same as the corresponding infrastructure description now.
+// ++ this isn't quite the same as the corresponding metrics description now.
[float]
[[logs-configure-source]]
diff --git a/docs/maps/trouble-shooting.asciidoc b/docs/maps/trouble-shooting.asciidoc
index 542138828530b..76383f8953a78 100644
--- a/docs/maps/trouble-shooting.asciidoc
+++ b/docs/maps/trouble-shooting.asciidoc
@@ -30,4 +30,9 @@ image::maps/images/inspector.png[]
* Ensure your tile server has configured https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS[Cross-Origin Resource Sharing (CORS)] so tile requests from your Kibana domain have permission to access your tile server domain.
* Ensure tiles have the required coordinate system. Vector data must use EPSG:4326 and tiles must use EPSG:3857.
+[float]
+==== Coordinate and region map visualizations not available in New Visualization menu
+
+Kibana’s out-of-the-box settings no longer offers coordinate and region maps as a choice in the New Visualization menu because you can create these maps in *Elastic Maps*.
+If you want to create new coordinate and region map visualizations, set `xpack.maps.showMapVisualizationTypes` to `true`.
diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc
index a8d8a66fd182c..af67ff70c81b5 100644
--- a/docs/redirects.asciidoc
+++ b/docs/redirects.asciidoc
@@ -35,3 +35,7 @@ This page has moved. Please see <>.
This page has moved. Please see <>.
+[role="exclude",id="extend"]
+== Extend your use case
+
+This page was deleted. See <> and <>.
\ No newline at end of file
diff --git a/docs/settings/general-infra-logs-ui-settings.asciidoc b/docs/settings/general-infra-logs-ui-settings.asciidoc
index 31a12c6e2e905..7b32372a1f59a 100644
--- a/docs/settings/general-infra-logs-ui-settings.asciidoc
+++ b/docs/settings/general-infra-logs-ui-settings.asciidoc
@@ -1,4 +1,4 @@
-`xpack.infra.enabled`:: Set to `false` to disable the Logs and Metrics UI plugin {kib}. Defaults to `true`.
+`xpack.infra.enabled`:: Set to `false` to disable the Logs and Metrics app plugin {kib}. Defaults to `true`.
`xpack.infra.sources.default.logAlias`:: Index pattern for matching indices that contain log data. Defaults to `filebeat-*,kibana_sample_data_logs*`. To match multiple wildcard patterns, use a comma to separate the names, with no space after the comma. For example, `logstash-app1-*,default-logs-*`.
@@ -6,7 +6,7 @@
`xpack.infra.sources.default.fields.timestamp`:: Timestamp used to sort log entries. Defaults to `@timestamp`.
-`xpack.infra.sources.default.fields.message`:: Fields used to display messages in the Logs UI. Defaults to `['message', '@message']`.
+`xpack.infra.sources.default.fields.message`:: Fields used to display messages in the Logs app. Defaults to `['message', '@message']`.
`xpack.infra.sources.default.fields.tiebreaker`:: Field used to break ties between two entries with the same timestamp. Defaults to `_doc`.
diff --git a/docs/settings/infrastructure-ui-settings.asciidoc b/docs/settings/infrastructure-ui-settings.asciidoc
index 1617f2847c50e..ed69c27feab72 100644
--- a/docs/settings/infrastructure-ui-settings.asciidoc
+++ b/docs/settings/infrastructure-ui-settings.asciidoc
@@ -1,14 +1,14 @@
[role="xpack"]
[[infrastructure-ui-settings-kb]]
-=== Metrics UI settings in Kibana
+=== Metrics settings in Kibana
++++
-Metrics UI settings
+Metrics settings
++++
-You do not need to configure any settings to use the Metrics UI. It is enabled by default.
+You do not need to configure any settings to use the Metrics app in {kib}. It is enabled by default.
[float]
[[general-infra-ui-settings-kb]]
-==== General Metrics UI settings
+==== General Metrics settings
include::general-infra-logs-ui-settings.asciidoc[]
\ No newline at end of file
diff --git a/docs/settings/logs-ui-settings.asciidoc b/docs/settings/logs-ui-settings.asciidoc
index a2c9e12e22fb0..5b6dd902091ae 100644
--- a/docs/settings/logs-ui-settings.asciidoc
+++ b/docs/settings/logs-ui-settings.asciidoc
@@ -1,14 +1,14 @@
[role="xpack"]
[[logs-ui-settings-kb]]
-=== Logs UI settings in Kibana
+=== Logs app settings in Kibana
++++
-Logs UI settings
+Logs settings
++++
-You do not need to configure any settings to use the Logs UI. It is enabled by default.
+You do not need to configure any settings to use the Logs app in {kib}. It is enabled by default.
[float]
[[general-logs-ui-settings-kb]]
-==== General Logs UI settings
+==== General Logs settings
include::general-infra-logs-ui-settings.asciidoc[]
diff --git a/docs/uptime-guide/overview.asciidoc b/docs/uptime-guide/overview.asciidoc
index 09867e7b05f2a..c6bd71b1f5574 100644
--- a/docs/uptime-guide/overview.asciidoc
+++ b/docs/uptime-guide/overview.asciidoc
@@ -33,8 +33,8 @@ The {kibana-ref}/xpack-uptime.html[Elasticsearch Uptime app] in Kibana provides
[float]
=== Example deployments
-// ++ I like the Infra/logging diagram which shows Infrastructure and Logging apps as separate components inside Kibana
-// ++ In diagram, should be Uptime app, not Uptime UI, possibly even Elastic Uptime? Also applies to Infra/logging/APM.
+// ++ I like the Infra/logging diagram which shows Metrics and Logging apps as separate components inside Kibana
+// ++ In diagram, should be Uptime app, not Uptime UI, possibly even Elastic Uptime? Also applies to Metrics/Logging/APM.
// ++ Need more whitespace around components.
image::images/uptime-simple-deployment.png[Uptime simple deployment]
diff --git a/docs/uptime-guide/security.asciidoc b/docs/uptime-guide/security.asciidoc
index 41efcc25627be..2a960348b1e02 100644
--- a/docs/uptime-guide/security.asciidoc
+++ b/docs/uptime-guide/security.asciidoc
@@ -31,17 +31,6 @@ PUT /_security/role/uptime
"allow_restricted_indices" : false
}
],
- "applications" : [
- {
- "application" : "kibana-.kibana",
- "privileges" : [
- "all"
- ],
- "resources" : [
- "*"
- ]
- }
- ],
"transient_metadata" : {
"enabled" : true
}
@@ -52,7 +41,8 @@ PUT /_security/role/uptime
[float]
=== Assign the role to a user
-Next, you'll need to create a user with both the `kibana_user`, and `uptime` roles.
+Next, you'll need to create a user with both the `uptime` role, and another role with sufficient {kibana-ref}/kibana-privileges.html[Kibana privileges],
+such as the `kibana_user` role.
You can do this with the following request:
["source","sh",subs="attributes,callouts"]
diff --git a/docs/uptime/overview.asciidoc b/docs/uptime/overview.asciidoc
index ea7047ae940a8..098ce12a56991 100644
--- a/docs/uptime/overview.asciidoc
+++ b/docs/uptime/overview.asciidoc
@@ -34,7 +34,7 @@ in an `up` or `down` state are displayed, based on the last check reported by He
for each monitor.
Next to the counts, there is a histogram displaying the change over time throughout the
-selected date range.
+selected date range.
[float]
=== Monitor list
@@ -56,7 +56,7 @@ ID and URL, its IP address, and a dedicated sparkline showing its check status o
image::uptime/images/observability_integrations.png[Observability integrations]
The Monitor list also contains a menu of possible integrations. If Uptime detects Kubernetes or
-Docker related host information, it will provide links to open the Metrics UI or Logs UI pre-filtered
+Docker related host information, it will provide links to open the Metrics app or Logs app pre-filtered
for this host. Additionally, this feature supplies links to simply filter the other views on the host's
IP address, to help you quickly determine if these other solutions contain data relevant to your current
interest.
diff --git a/docs/user/canvas.asciidoc b/docs/user/canvas.asciidoc
index f3aa78e8e2e67..c58635ba97769 100644
--- a/docs/user/canvas.asciidoc
+++ b/docs/user/canvas.asciidoc
@@ -5,15 +5,15 @@
[partintro]
--
-Canvas is a data visualization and presentation tool that sits within Kibana. With Canvas, you can pull live data directly from Elasticsearch, and combine the data with colors, images, text, and your imagination to create dynamic, multi-page, pixel-perfect displays. If you are a little bit creative, a little bit technical, and a whole lot curious, then Canvas is for you.
+Canvas is a data visualization and presentation tool that sits within Kibana. With Canvas, you can pull live data directly from Elasticsearch, and combine the data with colors, images, text, and your imagination to create dynamic, multi-page, pixel-perfect displays. If you are a little bit creative, a little bit technical, and a whole lot curious, then Canvas is for you.
With Canvas, you can:
-* Create and personalize your work space with backgrounds, borders, colors, fonts, and more.
+* Create and personalize your work space with backgrounds, borders, colors, fonts, and more.
* Customize your workpad with your own visualizations, such as images and text.
-* Customize your data by pulling it directly from Elasticsearch.
+* Customize your data by pulling it directly from Elasticsearch.
* Show off your data with charts, graphs, progress monitors, and more.
@@ -37,8 +37,6 @@ include::{kib-repo-dir}/canvas/canvas-present-workpad.asciidoc[]
include::{kib-repo-dir}/canvas/canvas-share-workpad.asciidoc[]
-//include::{kib-repo-dir}/canvas/canvas-expressions.asciidoc[]
-
include::{kib-repo-dir}/canvas/canvas-function-reference.asciidoc[]
include::{kib-repo-dir}/canvas/canvas-tinymath-functions.asciidoc[]
diff --git a/docs/user/extend.asciidoc b/docs/user/extend.asciidoc
deleted file mode 100644
index c658731ce3c3d..0000000000000
--- a/docs/user/extend.asciidoc
+++ /dev/null
@@ -1,15 +0,0 @@
-[[extend]]
-= Extend your use case
-
-[partintro]
---
-//TBD
-
-* <>
-* <>
-
---
-
-include::graph/index.asciidoc[]
-
-include::ml/index.asciidoc[]
diff --git a/docs/user/graph/configuring-graph.asciidoc b/docs/user/graph/configuring-graph.asciidoc
index 9503e606406b3..d521f9d8d2846 100644
--- a/docs/user/graph/configuring-graph.asciidoc
+++ b/docs/user/graph/configuring-graph.asciidoc
@@ -1,6 +1,6 @@
[role="xpack"]
[[graph-configuration]]
-=== Configuring Graph
+== Configuring Graph
When a user saves a graph workspace in Kibana, it is stored in the `.kibana`
index along with other saved objects like visualizations and dashboards.
@@ -57,9 +57,9 @@ is displayed. For more information on granting access to Kibana, see
[role="screenshot"]
image::user/graph/images/graph-read-only-badge.png[Example of Graph's read only access indicator in Kibana's header]
-[float]
+[discrete]
[[disable-drill-down]]
-==== Disabling drill down configuration
+=== Disabling drill down configuration
By default, users can configure _drill down_ URLs to display additional
information about a selected vertex in a new browser window. For example,
diff --git a/docs/user/graph/getting-started.asciidoc b/docs/user/graph/getting-started.asciidoc
index dd5e8527c8976..19f3df341338e 100644
--- a/docs/user/graph/getting-started.asciidoc
+++ b/docs/user/graph/getting-started.asciidoc
@@ -1,6 +1,6 @@
[role="xpack"]
[[graph-getting-started]]
-=== Using Graph
+== Using Graph
Graph is automatically enabled in {es} and {kib}.
diff --git a/docs/user/graph/index.asciidoc b/docs/user/graph/index.asciidoc
index 9ca7b0e4b1a4a..f9094f5b594b1 100644
--- a/docs/user/graph/index.asciidoc
+++ b/docs/user/graph/index.asciidoc
@@ -1,7 +1,9 @@
[role="xpack"]
[[xpack-graph]]
-== Graph data connections
+= Graph data connections
+[partintro]
+--
The {graph-features} enable you to discover how items in an
Elasticsearch index are related. You can explore the connections between
indexed terms and see which connections are the most meaningful. This can be
@@ -17,9 +19,9 @@ and an interactive graph visualization tool for Kibana. Both work out of the
box with existing Elasticsearch indices--you don't need to store any
additional data to use these features.
+[discrete]
[[how-graph-works]]
-[float]
-=== How Graph works
+== How Graph works
The graph API provides an alternative way to extract and summarize information
about the documents and terms in your Elasticsearch index. A _graph_ is really
just a network of related items. In our case, this means a network of related
@@ -62,6 +64,7 @@ multi-node clusters and scales with your Elasticsearch deployment.
Advanced options let you control how your data is sampled and summarized.
You can also set timeouts to prevent graph queries from adversely
affecting the cluster.
+--
include::getting-started.asciidoc[]
diff --git a/docs/user/graph/limitations.asciidoc b/docs/user/graph/limitations.asciidoc
index b40f15000483a..e96910bd27b4c 100644
--- a/docs/user/graph/limitations.asciidoc
+++ b/docs/user/graph/limitations.asciidoc
@@ -1,12 +1,12 @@
[role="xpack"]
[[graph-limitations]]
-=== Graph limitations
+== Graph limitations
++++
Limitations
++++
-[float]
-==== Limited support for multiple indices
+[discrete]
+=== Limited support for multiple indices
The graph API can explore multiple indices, types, or aliases in a
single API request, but the assumption is that each "hop" it performs
is querying the same set of indices. Currently, it is not possible to
diff --git a/docs/user/graph/troubleshooting.asciidoc b/docs/user/graph/troubleshooting.asciidoc
index 7a87aba7b7f81..ff3568ed41afa 100644
--- a/docs/user/graph/troubleshooting.asciidoc
+++ b/docs/user/graph/troubleshooting.asciidoc
@@ -1,12 +1,12 @@
[role="xpack"]
[[graph-troubleshooting]]
-=== Graph Troubleshooting
+== Graph Troubleshooting
++++
Troubleshooting
++++
-[float]
-==== Why are results missing?
+[discrete]
+=== Why are results missing?
The default settings in Graph API requests are configured to tune out noisy
results by using the following strategies:
@@ -29,8 +29,8 @@ of any statistical correlation with the sample.
* Set the `min_doc_count` for your vertices to 1 to ensure only one document is
required to assert a relationship.
-[float]
-==== What can I do to to improve performance?
+[discrete]
+=== What can I do to to improve performance?
With the default setting of `use_significance` set to `true`, the Graph API
performs a background frequency check of the terms it discovers as part of
diff --git a/docs/user/index.asciidoc b/docs/user/index.asciidoc
index 4b29255c50a1d..ebe6c10c49872 100644
--- a/docs/user/index.asciidoc
+++ b/docs/user/index.asciidoc
@@ -16,7 +16,9 @@ include::dashboard.asciidoc[]
include::canvas.asciidoc[]
-include::extend.asciidoc[]
+include::graph/index.asciidoc[]
+
+include::ml/index.asciidoc[]
include::{kib-repo-dir}/maps/index.asciidoc[]
diff --git a/docs/user/ml/index.asciidoc b/docs/user/ml/index.asciidoc
index a5f14ed2cf944..b7bf459c39d98 100644
--- a/docs/user/ml/index.asciidoc
+++ b/docs/user/ml/index.asciidoc
@@ -1,7 +1,9 @@
[role="xpack"]
[[xpack-ml]]
-== {ml-cap}
+= {ml-cap}
+[partintro]
+--
As datasets increase in size and complexity, the human effort required to
inspect dashboards or maintain rules for spotting infrastructure problems,
cyber attacks, or business issues becomes impractical. Elastic {ml-features}
@@ -28,10 +30,10 @@ You need the following permissions to use the Data Visualizer with file upload:
For more information, see {ref}/security-privileges.html[Security privileges]
and {ref}/built-in-roles.html[Built-in roles].
+--
-[float]
[[xpack-ml-anomalies]]
-=== {anomaly-detect-cap}
+== {anomaly-detect-cap}
The Elastic {ml} {anomaly-detect} feature automatically models the normal
behavior of your time series data — learning trends, periodicity, and more — in
@@ -82,9 +84,8 @@ For more information about the {anomaly-detect} feature, see
https://www.elastic.co/what-is/elastic-stack-machine-learning[{ml-cap} in the {stack}]
and {stack-ov}/xpack-ml.html[{ml-cap} {anomaly-detect}].
-[float]
[[xpack-ml-dfanalytics]]
-=== {dfanalytics-cap}
+== {dfanalytics-cap}
The Elastic {ml} {dfanalytics} feature enables you to analyze your data using
{oldetection} and {regression} algorithms and generate new indices that contain
@@ -98,4 +99,4 @@ in {kib}. For example:
image::user/ml/images/outliers.jpg[{oldetection-cap} results in {kib}]
For more information about the {dfanalytics} feature, see
-{stack-ov}/ml-dfanalytics.html[{ml-cap} {dfanalytics}].
+{stack-ov}/ml-dfanalytics.html[{ml-cap} {dfanalytics}].
\ No newline at end of file
diff --git a/docs/user/reporting/index.asciidoc b/docs/user/reporting/index.asciidoc
index 82dd88cb57495..4a5ca41ae6be9 100644
--- a/docs/user/reporting/index.asciidoc
+++ b/docs/user/reporting/index.asciidoc
@@ -32,8 +32,8 @@ for different operating systems.
. Open {kib} in your web browser and log in. If you are running {kib}
locally, go to `http://localhost:5601`. To access {kib} and generate
-reports, you need the `kibana_user` and `reporting_user` roles. For more
-information, see <>.
+reports, you need the `reporting_user` role, and an additional role with succifient <>, such as the `kibana_user` role.
+For more information, see <>.
. Open the dashboard, visualization, or saved search you want to include
in the report.
diff --git a/docs/user/security/authentication/index.asciidoc b/docs/user/security/authentication/index.asciidoc
index 8a4678e051490..c2b1adc5e1b92 100644
--- a/docs/user/security/authentication/index.asciidoc
+++ b/docs/user/security/authentication/index.asciidoc
@@ -138,7 +138,7 @@ xpack.security.authc.saml.maxRedirectURLSize: 1kb
==== OpenID Connect Single Sign-On
Similar to SAML, authentication with OpenID Connect allows users to log in to {kib} using an OpenID Connect Provider such as Google, or Okta. OpenID Connect
-should also be configured in {es}, see {xpack-ref}/saml-guide.html[Configuring OpenID Connect Single-Sign-On on the Elastic Stack] for more details.
+should also be configured in {es}. For more details, see {ref}/oidc-guide.html[Configuring single sign-on to the {stack} using OpenID Connect].
Set the configuration values in `kibana.yml` as follows:
diff --git a/docs/user/security/reporting.asciidoc b/docs/user/security/reporting.asciidoc
index ffbef3bdc9b18..1d7a3f4978ee0 100644
--- a/docs/user/security/reporting.asciidoc
+++ b/docs/user/security/reporting.asciidoc
@@ -19,7 +19,7 @@ and `kibana_user` roles:
* If you're using the `native` realm, you can assign roles through
**Management / Users** UI in Kibana or with the `user` API. For example,
the following request creates a `reporter` user that has the
-`reporting_user` and `kibana_user` roles:
+`reporting_user` role, and another role with sufficient <>, such as the `kibana_user` role:
+
[source, sh]
---------------------------------------------------------------
diff --git a/docs/user/security/securing-kibana.asciidoc b/docs/user/security/securing-kibana.asciidoc
index fa11d5925bdbe..1c74bd98642a7 100644
--- a/docs/user/security/securing-kibana.asciidoc
+++ b/docs/user/security/securing-kibana.asciidoc
@@ -117,7 +117,7 @@ user you've assigned a {kib} user role. For example, you could log in as the
+
--
-NOTE: This must be a user who has been assigned the `kibana_user` role.
+NOTE: This must be a user who has been assigned <>.
{kib} server credentials should only be used internally by the {kib} server.
--
diff --git a/docs/visualize/regionmap.asciidoc b/docs/visualize/regionmap.asciidoc
index faecc207d81a7..c39282963ef7b 100644
--- a/docs/visualize/regionmap.asciidoc
+++ b/docs/visualize/regionmap.asciidoc
@@ -1,9 +1,12 @@
[[regionmap]]
== Region Maps
-Region maps are thematic maps in which boundary vector shapes are colored using a gradient:
-higher intensity colors indicate larger values, and lower intensity colors indicate smaller values.
-These are also known as choropleth maps.
+Region maps are thematic maps in which boundary vector shapes are colored using a gradient:
+higher intensity colors indicate larger values, and lower intensity colors indicate smaller values.
+These are also known as choropleth maps.
+
+Kibana’s out-of-the-box settings do not show a region map in the New Visualization menu. Use <> instead, which offers more functionality and is easier to use.
+If you want to create new region map visualizations, set `xpack.maps.showMapVisualizationTypes` to `true`.
image::images/regionmap.png[]
@@ -11,7 +14,7 @@ image::images/regionmap.png[]
[[regionmap-configuration]]
=== Configuration
-To create a region map, you configure an inner join that joins the result of an Elasticsearch terms aggregation
+To create a region map, you configure an inner join that joins the result of an Elasticsearch terms aggregation
and a reference vector file based on a shared key.
[float]
@@ -23,7 +26,7 @@ and a reference vector file based on a shared key.
Select any of the supported _Metric_ or _Sibling Pipeline Aggregations_.
[float]
-===== Buckets
+===== Buckets
Configure a _Terms_ aggregation. The term is the _key_ that is used to join the results to the vector data on the map.
@@ -35,7 +38,7 @@ Configure a _Terms_ aggregation. The term is the _key_ that is used to join the
- *Vector map*: select from a list of vector maps. This list includes the maps that are hosted by the © https://www.elastic.co/elastic-maps-service[Elastic Maps Service],
as well as your self-hosted layers that are configured in the *config/kibana.yml* file. To learn more about how to configure Kibana
to make self-hosted layers available, see the <> documentation. You can also explore and preview vector layers available in Elastic Maps Service at https://maps.elastic.co[https://maps.elastic.co].
-- *Join field*: this is the property from the selected vector map that will be used to join on the terms in your terms-aggregation.
+- *Join field*: this is the property from the selected vector map that will be used to join on the terms in your terms-aggregation.
When terms cannot be joined to any of the shapes in the vector layer because there is no exact match in the vector layer, Kibana will display a warning.
To turn of these warnings, go to *Management/Kibana/Advanced Settings* and set `visualization:regionmap:showWarnings` to `false`.
@@ -46,4 +49,4 @@ To turn of these warnings, go to *Management/Kibana/Advanced Settings* and set `
[float]
===== Basic Settings
- *Legend Position*: the location on the screen where the legend should be rendered.
-- *Show Tooltip*: indicates whether a tooltip should be displayed when hovering over a shape..
\ No newline at end of file
+- *Show Tooltip*: indicates whether a tooltip should be displayed when hovering over a shape..
diff --git a/docs/visualize/tilemap.asciidoc b/docs/visualize/tilemap.asciidoc
index 157eb502bedb7..0e89704b8ba0b 100644
--- a/docs/visualize/tilemap.asciidoc
+++ b/docs/visualize/tilemap.asciidoc
@@ -3,7 +3,10 @@
A coordinate map displays a geographic area overlaid with circles keyed to the data determined by the buckets you specify.
-NOTE: By default, Kibana uses the https://www.elastic.co/elastic-maps-service[Elastic Maps Service]
+Kibana’s out-of-the-box settings do not show a coordinate map in the New Visualization menu. Use <> instead, which offers more functionality and is easier to use.
+If you want to create new coordinate map visualizations, set `xpack.maps.showMapVisualizationTypes` to `true`.
+
+Kibana uses the https://www.elastic.co/elastic-maps-service[Elastic Maps Service]
to display map tiles. To use other tile service providers, configure the <>
in `kibana.yml`.
diff --git a/package.json b/package.json
index 492f5744b24c7..1b807fa94f0db 100644
--- a/package.json
+++ b/package.json
@@ -106,10 +106,10 @@
"dependencies": {
"@babel/core": "^7.5.5",
"@babel/register": "^7.5.5",
- "@elastic/charts": "^13.5.9",
+ "@elastic/charts": "^13.5.12",
"@elastic/datemath": "5.0.2",
"@elastic/ems-client": "1.0.5",
- "@elastic/eui": "14.7.0",
+ "@elastic/eui": "14.8.0",
"@elastic/filesaver": "1.1.2",
"@elastic/good": "8.1.1-kibana2",
"@elastic/numeral": "2.3.3",
@@ -158,8 +158,8 @@
"d3": "3.5.17",
"d3-cloud": "1.2.5",
"del": "^5.1.0",
- "elasticsearch": "^16.4.0",
- "elasticsearch-browser": "^16.4.0",
+ "elasticsearch": "^16.5.0",
+ "elasticsearch-browser": "^16.5.0",
"encode-uri-query": "1.0.1",
"execa": "^3.2.0",
"expiry-js": "0.1.7",
@@ -235,7 +235,7 @@
"reselect": "^3.0.1",
"resize-observer-polyfill": "^1.5.0",
"rison-node": "1.0.2",
- "rxjs": "^6.2.1",
+ "rxjs": "^6.5.3",
"script-loader": "0.7.2",
"semver": "^5.5.0",
"style-it": "^2.1.3",
@@ -352,6 +352,7 @@
"@typescript-eslint/parser": "^2.5.0",
"angular-mocks": "^1.7.8",
"archiver": "^3.1.1",
+ "axe-core": "^3.3.2",
"babel-eslint": "^10.0.3",
"babel-jest": "^24.9.0",
"babel-plugin-dynamic-import-node": "^2.3.0",
@@ -361,7 +362,7 @@
"chance": "1.0.18",
"cheerio": "0.22.0",
"chokidar": "3.2.1",
- "chromedriver": "^77.0.0",
+ "chromedriver": "^78.0.1",
"classnames": "2.2.6",
"dedent": "^0.7.0",
"delete-empty": "^2.0.0",
diff --git a/packages/eslint-config-kibana/.eslintrc.js b/packages/eslint-config-kibana/.eslintrc.js
index 4412ce81368a1..36f0b95c8e69b 100644
--- a/packages/eslint-config-kibana/.eslintrc.js
+++ b/packages/eslint-config-kibana/.eslintrc.js
@@ -3,6 +3,7 @@ module.exports = {
'./javascript.js',
'./typescript.js',
'./jest.js',
+ './react.js',
],
plugins: ['@kbn/eslint-plugin-eslint'],
diff --git a/packages/eslint-config-kibana/javascript.js b/packages/eslint-config-kibana/javascript.js
index 8462da5cac801..0c79669c15e73 100644
--- a/packages/eslint-config-kibana/javascript.js
+++ b/packages/eslint-config-kibana/javascript.js
@@ -1,6 +1,3 @@
-const semver = require('semver');
-const { readdirSync } = require('fs');
-const PKG = require('../../package.json');
const RESTRICTED_GLOBALS = require('./restricted_globals');
const RESTRICTED_MODULES = { paths: ['gulp-util'] };
@@ -16,18 +13,12 @@ module.exports = {
plugins: [
'mocha',
'babel',
- 'react',
- 'react-hooks',
'import',
'no-unsanitized',
'prefer-object-spread',
- 'jsx-a11y',
],
settings: {
- react: {
- version: semver.valid(semver.coerce(PKG.dependencies.react)),
- },
'import/resolver': {
'@kbn/eslint-import-resolver-kibana': {
forceNode: true,
@@ -120,64 +111,6 @@ module.exports = {
'object-curly-spacing': 'off', // overridden with babel/object-curly-spacing
'babel/object-curly-spacing': [ 'error', 'always' ],
- 'jsx-quotes': ['error', 'prefer-double'],
- 'react/jsx-uses-react': 'error',
- 'react/react-in-jsx-scope': 'error',
- 'react/jsx-uses-vars': 'error',
- 'react/jsx-no-undef': 'error',
- 'react/jsx-pascal-case': 'error',
- 'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
- 'react/jsx-closing-tag-location': 'error',
- 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
- 'react/jsx-indent-props': ['error', 2],
- 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }],
- 'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }],
- 'react/no-danger': 'error',
- 'react/self-closing-comp': 'error',
- 'react/jsx-wrap-multilines': ['error', {
- declaration: true,
- assignment: true,
- return: true,
- arrow: true,
- }],
- 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
- 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
- 'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies
- 'jsx-a11y/accessible-emoji': 'error',
- 'jsx-a11y/alt-text': 'error',
- 'jsx-a11y/anchor-has-content': 'error',
- 'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
- 'jsx-a11y/aria-props': 'error',
- 'jsx-a11y/aria-proptypes': 'error',
- 'jsx-a11y/aria-role': 'error',
- 'jsx-a11y/aria-unsupported-elements': 'error',
- 'jsx-a11y/heading-has-content': 'error',
- 'jsx-a11y/html-has-lang': 'error',
- 'jsx-a11y/iframe-has-title': 'error',
- 'jsx-a11y/interactive-supports-focus': 'error',
- 'jsx-a11y/media-has-caption': 'error',
- 'jsx-a11y/mouse-events-have-key-events': 'error',
- 'jsx-a11y/no-access-key': 'error',
- 'jsx-a11y/no-distracting-elements': 'error',
- 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
- 'jsx-a11y/no-noninteractive-element-interactions': 'error',
- 'jsx-a11y/no-noninteractive-element-to-interactive-role': 'error',
- 'jsx-a11y/no-redundant-roles': 'error',
- 'jsx-a11y/role-has-required-aria-props': 'error',
- 'jsx-a11y/role-supports-aria-props': 'error',
- 'jsx-a11y/scope': 'error',
- 'jsx-a11y/tabindex-no-positive': 'error',
- 'jsx-a11y/label-has-associated-control': 'error',
- 'react/jsx-equals-spacing': ['error', 'never'],
- 'react/jsx-indent': ['error', 2],
- 'react/no-will-update-set-state': 'error',
- 'react/no-is-mounted': 'error',
- 'react/no-multi-comp': ['error', { ignoreStateless: true }],
- 'react/no-unknown-property': 'error',
- 'react/prefer-es6-class': ['error', 'always'],
- 'react/prefer-stateless-function': ['error', { ignorePureComponents: true }],
- 'react/no-unescaped-entities': 'error',
-
'mocha/handle-done-callback': 'error',
'mocha/no-exclusive-tests': 'error',
diff --git a/packages/eslint-config-kibana/react.js b/packages/eslint-config-kibana/react.js
new file mode 100644
index 0000000000000..163bd6ca73a07
--- /dev/null
+++ b/packages/eslint-config-kibana/react.js
@@ -0,0 +1,84 @@
+const semver = require('semver')
+const PKG = require('../../package.json')
+
+module.exports = {
+ plugins: [
+ 'react',
+ 'react-hooks',
+ 'jsx-a11y',
+ ],
+
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true
+ }
+ },
+
+ settings: {
+ react: {
+ version: semver.valid(semver.coerce(PKG.dependencies.react)),
+ },
+ },
+
+ rules: {
+ 'jsx-quotes': ['error', 'prefer-double'],
+ 'react/jsx-uses-react': 'error',
+ 'react/react-in-jsx-scope': 'error',
+ 'react/jsx-uses-vars': 'error',
+ 'react/jsx-no-undef': 'error',
+ 'react/jsx-pascal-case': 'error',
+ 'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
+ 'react/jsx-closing-tag-location': 'error',
+ 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
+ 'react/jsx-indent-props': ['error', 2],
+ 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }],
+ 'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }],
+ 'react/no-danger': 'error',
+ 'react/self-closing-comp': 'error',
+ 'react/jsx-wrap-multilines': ['error', {
+ declaration: true,
+ assignment: true,
+ return: true,
+ arrow: true,
+ }],
+ 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
+ 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
+ 'react-hooks/exhaustive-deps': 'error', // Checks effect dependencies
+ 'jsx-a11y/accessible-emoji': 'error',
+ 'jsx-a11y/alt-text': 'error',
+ 'jsx-a11y/anchor-has-content': 'error',
+ 'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
+ 'jsx-a11y/aria-props': 'error',
+ 'jsx-a11y/aria-proptypes': 'error',
+ 'jsx-a11y/aria-role': 'error',
+ 'jsx-a11y/aria-unsupported-elements': 'error',
+ 'jsx-a11y/click-events-have-key-events': 'error',
+ 'jsx-a11y/heading-has-content': 'error',
+ 'jsx-a11y/html-has-lang': 'error',
+ 'jsx-a11y/iframe-has-title': 'error',
+ 'jsx-a11y/interactive-supports-focus': 'error',
+ 'jsx-a11y/label-has-associated-control': 'error',
+ 'jsx-a11y/media-has-caption': 'error',
+ 'jsx-a11y/mouse-events-have-key-events': 'error',
+ 'jsx-a11y/no-access-key': 'error',
+ 'jsx-a11y/no-distracting-elements': 'error',
+ 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
+ 'jsx-a11y/no-noninteractive-element-interactions': 'error',
+ 'jsx-a11y/no-noninteractive-element-to-interactive-role': 'error',
+ 'jsx-a11y/no-onchange': 'error',
+ 'jsx-a11y/no-redundant-roles': 'error',
+ 'jsx-a11y/role-has-required-aria-props': 'error',
+ 'jsx-a11y/role-supports-aria-props': 'error',
+ 'jsx-a11y/scope': 'error',
+ 'jsx-a11y/tabindex-no-positive': 'error',
+ 'react/jsx-equals-spacing': ['error', 'never'],
+ 'react/jsx-indent': ['error', 2],
+ 'react/no-will-update-set-state': 'error',
+ 'react/no-is-mounted': 'error',
+ 'react/no-multi-comp': ['error', { ignoreStateless: true }],
+ 'react/no-unknown-property': 'error',
+ 'react/prefer-es6-class': ['error', 'always'],
+ 'react/prefer-stateless-function': ['error', { ignorePureComponents: true }],
+ 'react/no-unescaped-entities': 'error',
+ },
+}
diff --git a/packages/eslint-config-kibana/typescript.js b/packages/eslint-config-kibana/typescript.js
index 7653c9bb0c332..757616f36180b 100644
--- a/packages/eslint-config-kibana/typescript.js
+++ b/packages/eslint-config-kibana/typescript.js
@@ -18,7 +18,6 @@ module.exports = {
'@typescript-eslint',
'ban',
'import',
- 'jsx-a11y',
'prefer-object-spread',
],
@@ -171,33 +170,6 @@ module.exports = {
{'name': ['test', 'only'], 'message': 'No exclusive tests.'},
],
- 'jsx-a11y/accessible-emoji': 'error',
- 'jsx-a11y/alt-text': 'error',
- 'jsx-a11y/anchor-has-content': 'error',
- 'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
- 'jsx-a11y/aria-props': 'error',
- 'jsx-a11y/aria-proptypes': 'error',
- 'jsx-a11y/aria-role': 'error',
- 'jsx-a11y/aria-unsupported-elements': 'error',
- 'jsx-a11y/click-events-have-key-events': 'error',
- 'jsx-a11y/heading-has-content': 'error',
- 'jsx-a11y/html-has-lang': 'error',
- 'jsx-a11y/iframe-has-title': 'error',
- 'jsx-a11y/interactive-supports-focus': 'error',
- 'jsx-a11y/media-has-caption': 'error',
- 'jsx-a11y/mouse-events-have-key-events': 'error',
- 'jsx-a11y/no-access-key': 'error',
- 'jsx-a11y/no-distracting-elements': 'error',
- 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
- 'jsx-a11y/no-noninteractive-element-interactions': 'error',
- 'jsx-a11y/no-noninteractive-element-to-interactive-role': 'error',
- 'jsx-a11y/no-onchange': 'error',
- 'jsx-a11y/no-redundant-roles': 'error',
- 'jsx-a11y/role-has-required-aria-props': 'error',
- 'jsx-a11y/role-supports-aria-props': 'error',
- 'jsx-a11y/scope': 'error',
- 'jsx-a11y/tabindex-no-positive': 'error',
- 'jsx-a11y/label-has-associated-control': 'error',
'import/no-default-export': 'error',
},
eslintConfigPrettierTypescriptEslintRules
diff --git a/packages/kbn-babel-preset/node_preset.js b/packages/kbn-babel-preset/node_preset.js
index 5ef4219df59f7..793044e3796ea 100644
--- a/packages/kbn-babel-preset/node_preset.js
+++ b/packages/kbn-babel-preset/node_preset.js
@@ -18,6 +18,25 @@
*/
module.exports = (_, options = {}) => {
+ const overrides = [];
+ if (!process.env.ALLOW_PERFORMANCE_HOOKS_IN_TASK_MANAGER) {
+ overrides.push(
+ {
+ test: [/x-pack[\/\\]legacy[\/\\]plugins[\/\\]task_manager/],
+ plugins: [
+ [
+ require.resolve('babel-plugin-filter-imports'),
+ {
+ imports: {
+ perf_hooks: ['performance'],
+ },
+ },
+ ],
+ ],
+ }
+ );
+ }
+
return {
presets: [
[
@@ -39,7 +58,7 @@ module.exports = (_, options = {}) => {
modules: 'cjs',
corejs: 3,
- ...(options['@babel/preset-env'] || {})
+ ...(options['@babel/preset-env'] || {}),
},
],
require('./common_preset'),
@@ -48,9 +67,10 @@ module.exports = (_, options = {}) => {
[
require.resolve('babel-plugin-transform-define'),
{
- 'global.__BUILT_WITH_BABEL__': 'true'
- }
- ]
- ]
+ 'global.__BUILT_WITH_BABEL__': 'true',
+ },
+ ],
+ ],
+ overrides,
};
};
diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json
index 4b18357745360..c22cf175b29e5 100644
--- a/packages/kbn-babel-preset/package.json
+++ b/packages/kbn-babel-preset/package.json
@@ -8,10 +8,11 @@
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-transform-modules-commonjs": "^7.5.0",
"@babel/preset-env": "^7.5.5",
- "@babel/preset-react":"^7.0.0",
+ "@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.3.3",
"@kbn/elastic-idx": "1.0.0",
"babel-plugin-add-module-exports": "^1.0.2",
+ "babel-plugin-filter-imports": "^3.0.0",
"babel-plugin-transform-define": "^1.3.1",
"babel-plugin-typescript-strip-namespaces": "^1.1.1"
}
diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json
index a5789a0a105b3..e8781f6d901d9 100644
--- a/packages/kbn-dev-utils/package.json
+++ b/packages/kbn-dev-utils/package.json
@@ -16,7 +16,7 @@
"exit-hook": "^2.2.0",
"getopts": "^2.2.5",
"moment": "^2.24.0",
- "rxjs": "^6.2.1",
+ "rxjs": "^6.5.3",
"tree-kill": "^1.2.1",
"tslib": "^1.9.3"
},
diff --git a/packages/kbn-dev-utils/src/proc_runner/proc.ts b/packages/kbn-dev-utils/src/proc_runner/proc.ts
index dab69de47af61..c899293191f2a 100644
--- a/packages/kbn-dev-utils/src/proc_runner/proc.ts
+++ b/packages/kbn-dev-utils/src/proc_runner/proc.ts
@@ -100,9 +100,9 @@ export function startProc(name: string, options: ProcOptions, log: ToolingLog) {
const outcome$: Rx.Observable = Rx.race(
// observe first exit event
- Rx.fromEvent(childProcess, 'exit').pipe(
+ Rx.fromEvent<[number]>(childProcess, 'exit').pipe(
take(1),
- map(([code]: [number]) => {
+ map(([code]) => {
if (stopCalled) {
return null;
}
diff --git a/packages/kbn-es-query/src/__fixtures__/index_pattern_response.json b/packages/kbn-es-query/src/__fixtures__/index_pattern_response.json
index 408e839596ae2..588e6ada69cfe 100644
--- a/packages/kbn-es-query/src/__fixtures__/index_pattern_response.json
+++ b/packages/kbn-es-query/src/__fixtures__/index_pattern_response.json
@@ -161,8 +161,7 @@
"searchable": true,
"aggregatable": true,
"readFromDocValues": true,
- "parent": "machine.os",
- "subType": "multi"
+ "subType": { "multi": { "parent": "machine.os" } }
},
{
"name": "geo.src",
@@ -277,6 +276,28 @@
"searchable": true,
"aggregatable": true,
"readFromDocValues": false
+ },
+ {
+ "name": "nestedField.child",
+ "type": "string",
+ "esTypes": ["text"],
+ "count": 0,
+ "scripted": false,
+ "searchable": true,
+ "aggregatable": false,
+ "readFromDocValues": false,
+ "subType": { "nested": { "path": "nestedField" } }
+ },
+ {
+ "name": "nestedField.nestedChild.doublyNestedChild",
+ "type": "string",
+ "esTypes": ["text"],
+ "count": 0,
+ "scripted": false,
+ "searchable": true,
+ "aggregatable": false,
+ "readFromDocValues": false,
+ "subType": { "nested": { "path": "nestedField.nestedChild" } }
}
]
}
diff --git a/packages/kbn-es-query/src/es_query/migrate_filter.js b/packages/kbn-es-query/src/es_query/migrate_filter.js
index d5f52648b027e..b74fc485a6184 100644
--- a/packages/kbn-es-query/src/es_query/migrate_filter.js
+++ b/packages/kbn-es-query/src/es_query/migrate_filter.js
@@ -18,7 +18,7 @@
*/
import _ from 'lodash';
-import { getConvertedValueForField } from '../filters';
+import { getConvertedValueForField } from '../utils/filters';
export function migrateFilter(filter, indexPattern) {
if (filter.match) {
diff --git a/packages/kbn-es-query/src/filters/__tests__/phrase.js b/packages/kbn-es-query/src/filters/__tests__/phrase.js
deleted file mode 100644
index dbd794a018d9e..0000000000000
--- a/packages/kbn-es-query/src/filters/__tests__/phrase.js
+++ /dev/null
@@ -1,92 +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 { buildInlineScriptForPhraseFilter, buildPhraseFilter } from '../phrase';
-import expect from '@kbn/expect';
-import _ from 'lodash';
-import indexPattern from '../../__fixtures__/index_pattern_response.json';
-import filterSkeleton from '../../__fixtures__/filter_skeleton';
-
-let expected;
-
-describe('Filter Manager', function () {
- describe('Phrase filter builder', function () {
- beforeEach(() => {
- expected = _.cloneDeep(filterSkeleton);
- });
-
- it('should be a function', function () {
- expect(buildPhraseFilter).to.be.a(Function);
- });
-
- it('should return a match query filter when passed a standard field', function () {
- const field = getField(indexPattern, 'bytes');
- expected.query = {
- match_phrase: {
- bytes: 5
- }
- };
- expect(buildPhraseFilter(field, 5, indexPattern)).to.eql(expected);
- });
-
- it('should return a script filter when passed a scripted field', function () {
- const field = getField(indexPattern, 'script number');
- expected.meta.field = 'script number';
- _.set(expected, 'script.script', {
- source: '(' + field.script + ') == value',
- lang: 'expression',
- params: {
- value: 5,
- }
- });
- expect(buildPhraseFilter(field, 5, indexPattern)).to.eql(expected);
- });
- });
-
- describe('buildInlineScriptForPhraseFilter', function () {
-
- it('should wrap painless scripts in a lambda', function () {
- const field = {
- lang: 'painless',
- script: 'return foo;',
- };
-
- const expected = `boolean compare(Supplier s, def v) {return s.get() == v;}` +
- `compare(() -> { return foo; }, params.value);`;
-
- expect(buildInlineScriptForPhraseFilter(field)).to.be(expected);
- });
-
- it('should create a simple comparison for other langs', function () {
- const field = {
- lang: 'expression',
- script: 'doc[bytes].value',
- };
-
- const expected = `(doc[bytes].value) == value`;
-
- expect(buildInlineScriptForPhraseFilter(field)).to.be(expected);
- });
- });
-});
-
-function getField(indexPattern, name) {
- return indexPattern.fields.find(field => field.name === name);
-}
diff --git a/packages/kbn-es-query/src/filters/__tests__/query.js b/packages/kbn-es-query/src/filters/__tests__/query.js
deleted file mode 100644
index 8b774f05c29d3..0000000000000
--- a/packages/kbn-es-query/src/filters/__tests__/query.js
+++ /dev/null
@@ -1,46 +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 { buildQueryFilter } from '../query';
-import { cloneDeep } from 'lodash';
-import expect from '@kbn/expect';
-import indexPattern from '../../__fixtures__/index_pattern_response.json';
-import filterSkeleton from '../../__fixtures__/filter_skeleton';
-
-let expected;
-
-describe('Filter Manager', function () {
- describe('Phrase filter builder', function () {
- beforeEach(() => {
- expected = cloneDeep(filterSkeleton);
- });
-
- it('should be a function', function () {
- expect(buildQueryFilter).to.be.a(Function);
- });
-
- it('should return a query filter when passed a standard field', function () {
- expected.query = {
- foo: 'bar'
- };
- expect(buildQueryFilter({ foo: 'bar' }, indexPattern.id)).to.eql(expected);
- });
-
- });
-});
diff --git a/packages/kbn-es-query/src/filters/__tests__/range.js b/packages/kbn-es-query/src/filters/__tests__/range.js
deleted file mode 100644
index 9b23fc23908d4..0000000000000
--- a/packages/kbn-es-query/src/filters/__tests__/range.js
+++ /dev/null
@@ -1,156 +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 { buildRangeFilter } from '../range';
-import expect from '@kbn/expect';
-import _ from 'lodash';
-import indexPattern from '../../__fixtures__/index_pattern_response.json';
-import filterSkeleton from '../../__fixtures__/filter_skeleton';
-
-let expected;
-
-describe('Filter Manager', function () {
- describe('Range filter builder', function () {
- beforeEach(() => {
- expected = _.cloneDeep(filterSkeleton);
- });
-
- it('should be a function', function () {
- expect(buildRangeFilter).to.be.a(Function);
- });
-
- it('should return a range filter when passed a standard field', function () {
- const field = getField(indexPattern, 'bytes');
- expected.range = {
- bytes: {
- gte: 1,
- lte: 3
- }
- };
- expect(buildRangeFilter(field, { gte: 1, lte: 3 }, indexPattern)).to.eql(expected);
- });
-
- it('should return a script filter when passed a scripted field', function () {
- const field = getField(indexPattern, 'script number');
- expected.meta.field = 'script number';
- _.set(expected, 'script.script', {
- lang: 'expression',
- source: '(' + field.script + ')>=gte && (' + field.script + ')<=lte',
- params: {
- value: '>=1 <=3',
- gte: 1,
- lte: 3
- }
- });
- expect(buildRangeFilter(field, { gte: 1, lte: 3 }, indexPattern)).to.eql(expected);
- });
-
- it('should wrap painless scripts in comparator lambdas', function () {
- const field = getField(indexPattern, 'script date');
- const expected = `boolean gte(Supplier s, def v) {return !s.get().toInstant().isBefore(Instant.parse(v))} ` +
- `boolean lte(Supplier s, def v) {return !s.get().toInstant().isAfter(Instant.parse(v))}` +
- `gte(() -> { ${field.script} }, params.gte) && ` +
- `lte(() -> { ${field.script} }, params.lte)`;
-
- const inlineScript = buildRangeFilter(field, { gte: 1, lte: 3 }, indexPattern).script.script.source;
- expect(inlineScript).to.be(expected);
- });
-
- it('should throw an error when gte and gt, or lte and lt are both passed', function () {
- const field = getField(indexPattern, 'script number');
- expect(function () {
- buildRangeFilter(field, { gte: 1, gt: 3 }, indexPattern);
- }).to.throwError();
- expect(function () {
- buildRangeFilter(field, { lte: 1, lt: 3 }, indexPattern);
- }).to.throwError();
- });
-
- it('to use the right operator for each of gte, gt, lt and lte', function () {
- const field = getField(indexPattern, 'script number');
- _.each({ gte: '>=', gt: '>', lte: '<=', lt: '<' }, function (operator, key) {
- const params = {};
- params[key] = 5;
- const filter = buildRangeFilter(field, params, indexPattern);
-
- expect(filter.script.script.source).to.be(
- '(' + field.script + ')' + operator + key);
- expect(filter.script.script.params[key]).to.be(5);
- expect(filter.script.script.params.value).to.be(operator + 5);
-
- });
- });
-
- describe('when given params where one side is infinite', function () {
- const field = getField(indexPattern, 'script number');
- let filter;
- beforeEach(function () {
- filter = buildRangeFilter(field, { gte: 0, lt: Infinity }, indexPattern);
- });
-
- describe('returned filter', function () {
- it('is a script filter', function () {
- expect(filter).to.have.property('script');
- });
-
- it('contain a param for the finite side', function () {
- expect(filter.script.script.params).to.have.property('gte', 0);
- });
-
- it('does not contain a param for the infinite side', function () {
- expect(filter.script.script.params).not.to.have.property('lt');
- });
-
- it('does not contain a script condition for the infinite side', function () {
- const field = getField(indexPattern, 'script number');
- const script = field.script;
- expect(filter.script.script.source).to.equal(`(${script})>=gte`);
- });
- });
- });
-
- describe('when given params where both sides are infinite', function () {
- const field = getField(indexPattern, 'script number');
- let filter;
- beforeEach(function () {
- filter = buildRangeFilter(
- field, { gte: -Infinity, lt: Infinity }, indexPattern);
- });
-
- describe('returned filter', function () {
- it('is a match_all filter', function () {
- expect(filter).not.to.have.property('script');
- expect(filter).to.have.property('match_all');
- });
-
- it('does not contain params', function () {
- expect(filter).not.to.have.property('params');
- });
-
- it('meta field is set to field name', function () {
- expect(filter.meta.field).to.equal('script number');
- });
- });
- });
- });
-});
-
-function getField(indexPattern, name) {
- return indexPattern.fields.find(field => field.name === name);
-}
diff --git a/packages/kbn-es-query/src/filters/index.d.ts b/packages/kbn-es-query/src/filters/index.d.ts
deleted file mode 100644
index c05e32dbf07b9..0000000000000
--- a/packages/kbn-es-query/src/filters/index.d.ts
+++ /dev/null
@@ -1,51 +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 { CustomFilter, ExistsFilter, PhraseFilter, PhrasesFilter, RangeFilter } from './lib';
-import { RangeFilterParams } from './lib/range_filter';
-
-export * from './lib';
-
-// We can't import the real types from the data plugin, so need to either duplicate
-// them here or figure out another solution, perhaps housing them in this package
-type Field = any;
-type IndexPattern = any;
-
-export function buildExistsFilter(field: Field, indexPattern: IndexPattern): ExistsFilter;
-
-export function buildPhraseFilter(
- field: Field,
- value: string,
- indexPattern: IndexPattern
-): PhraseFilter;
-
-export function buildPhrasesFilter(
- field: Field,
- values: string[],
- indexPattern: IndexPattern
-): PhrasesFilter;
-
-export function buildQueryFilter(query: any, index: string, alias?: string): CustomFilter;
-
-export function buildRangeFilter(
- field: Field,
- params: RangeFilterParams,
- indexPattern: IndexPattern,
- formattedValue?: string
-): RangeFilter;
diff --git a/packages/kbn-es-query/src/filters/index.js b/packages/kbn-es-query/src/filters/index.js
deleted file mode 100644
index d7d092eabd8a2..0000000000000
--- a/packages/kbn-es-query/src/filters/index.js
+++ /dev/null
@@ -1,25 +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.
- */
-
-export * from './exists';
-export * from './phrase';
-export * from './phrases';
-export * from './query';
-export * from './range';
-export * from './lib';
diff --git a/packages/kbn-es-query/src/filters/lib/index.ts b/packages/kbn-es-query/src/filters/lib/index.ts
deleted file mode 100644
index ea02398710341..0000000000000
--- a/packages/kbn-es-query/src/filters/lib/index.ts
+++ /dev/null
@@ -1,95 +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.
- */
-
-// The interface the other filters extend
-export * from './meta_filter';
-
-// The actual filter types
-import { CustomFilter } from './custom_filter';
-import { ExistsFilter, isExistsFilter } from './exists_filter';
-import { GeoBoundingBoxFilter, isGeoBoundingBoxFilter } from './geo_bounding_box_filter';
-import { GeoPolygonFilter, isGeoPolygonFilter } from './geo_polygon_filter';
-import {
- PhraseFilter,
- isPhraseFilter,
- isScriptedPhraseFilter,
- getPhraseFilterField,
- getPhraseFilterValue,
-} from './phrase_filter';
-import { PhrasesFilter, isPhrasesFilter } from './phrases_filter';
-import { QueryStringFilter, isQueryStringFilter } from './query_string_filter';
-import {
- RangeFilter,
- isRangeFilter,
- isScriptedRangeFilter,
- RangeFilterParams,
-} from './range_filter';
-import { MatchAllFilter, isMatchAllFilter } from './match_all_filter';
-import { MissingFilter, isMissingFilter } from './missing_filter';
-
-export {
- CustomFilter,
- ExistsFilter,
- isExistsFilter,
- GeoBoundingBoxFilter,
- isGeoBoundingBoxFilter,
- GeoPolygonFilter,
- isGeoPolygonFilter,
- PhraseFilter,
- isPhraseFilter,
- isScriptedPhraseFilter,
- getPhraseFilterField,
- getPhraseFilterValue,
- PhrasesFilter,
- isPhrasesFilter,
- QueryStringFilter,
- isQueryStringFilter,
- RangeFilter,
- isRangeFilter,
- isScriptedRangeFilter,
- RangeFilterParams,
- MatchAllFilter,
- isMatchAllFilter,
- MissingFilter,
- isMissingFilter,
-};
-
-// Any filter associated with a field (used in the filter bar/editor)
-export type FieldFilter =
- | ExistsFilter
- | GeoBoundingBoxFilter
- | GeoPolygonFilter
- | PhraseFilter
- | PhrasesFilter
- | RangeFilter
- | MatchAllFilter
- | MissingFilter;
-
-export enum FILTERS {
- CUSTOM = 'custom',
- PHRASES = 'phrases',
- PHRASE = 'phrase',
- EXISTS = 'exists',
- MATCH_ALL = 'match_all',
- MISSING = 'missing',
- QUERY_STRING = 'query_string',
- RANGE = 'range',
- GEO_BOUNDING_BOX = 'geo_bounding_box',
- GEO_POLYGON = 'geo_polygon',
-}
diff --git a/packages/kbn-es-query/src/filters/lib/phrase_filter.ts b/packages/kbn-es-query/src/filters/lib/phrase_filter.ts
deleted file mode 100644
index 124a5da372487..0000000000000
--- a/packages/kbn-es-query/src/filters/lib/phrase_filter.ts
+++ /dev/null
@@ -1,65 +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 { get, isPlainObject } from 'lodash';
-import { Filter, FilterMeta } from './meta_filter';
-
-export type PhraseFilterMeta = FilterMeta & {
- params: {
- query: string; // The unformatted value
- };
- script?: {
- script: {
- params: any;
- };
- };
- field?: any;
-};
-
-export type PhraseFilter = Filter & {
- meta: PhraseFilterMeta;
-};
-
-type PhraseFilterValue = string | number | boolean;
-
-export const isPhraseFilter = (filter: any): filter is PhraseFilter => {
- const isMatchPhraseQuery = filter && filter.query && filter.query.match_phrase;
-
- const isDeprecatedMatchPhraseQuery =
- filter &&
- filter.query &&
- filter.query.match &&
- Object.values(filter.query.match).find((params: any) => params.type === 'phrase');
-
- return !!(isMatchPhraseQuery || isDeprecatedMatchPhraseQuery);
-};
-
-export const isScriptedPhraseFilter = (filter: any): filter is PhraseFilter =>
- Boolean(get(filter, 'script.script.params.value'));
-
-export const getPhraseFilterField = (filter: PhraseFilter) => {
- const queryConfig = filter.query.match_phrase || filter.query.match;
- return Object.keys(queryConfig)[0];
-};
-
-export const getPhraseFilterValue = (filter: PhraseFilter): PhraseFilterValue => {
- const queryConfig = filter.query.match_phrase || filter.query.match;
- const queryValue = Object.values(queryConfig)[0] as any;
- return isPlainObject(queryValue) ? queryValue.query : queryValue;
-};
diff --git a/packages/kbn-es-query/src/filters/lib/range_filter.ts b/packages/kbn-es-query/src/filters/lib/range_filter.ts
deleted file mode 100644
index fc8d05d575d59..0000000000000
--- a/packages/kbn-es-query/src/filters/lib/range_filter.ts
+++ /dev/null
@@ -1,58 +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 { get, keys } from 'lodash';
-import { Filter, FilterMeta } from './meta_filter';
-
-export interface RangeFilterParams {
- from?: number | string;
- to?: number | string;
- gt?: number | string;
- lt?: number | string;
- gte?: number | string;
- lte?: number | string;
- format?: string;
-}
-
-export type RangeFilterMeta = FilterMeta & {
- params: RangeFilterParams;
- field?: any;
-};
-
-export type RangeFilter = Filter & {
- meta: RangeFilterMeta;
- script?: {
- script: {
- params: any;
- };
- };
- range: { [key: string]: RangeFilterParams };
-};
-
-const hasRangeKeys = (params: RangeFilterParams) =>
- Boolean(
- keys(params).find((key: string) => ['gte', 'gt', 'lte', 'lt', 'from', 'to'].includes(key))
- );
-
-export const isRangeFilter = (filter: any): filter is RangeFilter => filter && filter.range;
-
-export const isScriptedRangeFilter = (filter: any): filter is RangeFilter => {
- const params: RangeFilterParams = get(filter, 'script.script.params', {});
-
- return hasRangeKeys(params);
-};
diff --git a/packages/kbn-es-query/src/filters/phrase.js b/packages/kbn-es-query/src/filters/phrase.js
deleted file mode 100644
index f0134f289ad9d..0000000000000
--- a/packages/kbn-es-query/src/filters/phrase.js
+++ /dev/null
@@ -1,85 +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.
- */
-
-// Creates an filter where the given field matches the given value
-export function buildPhraseFilter(field, value, indexPattern) {
- const filter = { meta: { index: indexPattern.id } };
- const convertedValue = getConvertedValueForField(field, value);
-
- if (field.scripted) {
- filter.script = getPhraseScript(field, value);
- filter.meta.field = field.name;
- } else {
- filter.query = { match_phrase: {} };
- filter.query.match_phrase[field.name] = convertedValue;
- }
- return filter;
-}
-
-export function getPhraseScript(field, value) {
- const convertedValue = getConvertedValueForField(field, value);
- const script = buildInlineScriptForPhraseFilter(field);
-
- return {
- script: {
- source: script,
- lang: field.lang,
- params: {
- value: convertedValue
- }
- }
- };
-}
-
-// See https://github.com/elastic/elasticsearch/issues/20941 and https://github.com/elastic/kibana/issues/8677
-// and https://github.com/elastic/elasticsearch/pull/22201
-// for the reason behind this change. Aggs now return boolean buckets with a key of 1 or 0.
-export function getConvertedValueForField(field, value) {
- if (typeof value !== 'boolean' && field.type === 'boolean') {
- if ([1, 'true'].includes(value)) {
- return true;
- }
- else if ([0, 'false'].includes(value)) {
- return false;
- }
- else {
- throw new Error(`${value} is not a valid boolean value for boolean field ${field.name}`);
- }
- }
- return value;
-}
-
-/**
- * Takes a scripted field and returns an inline script appropriate for use in a script query.
- * Handles lucene expression and Painless scripts. Other langs aren't guaranteed to generate valid
- * scripts.
- *
- * @param {object} scriptedField A Field object representing a scripted field
- * @returns {string} The inline script string
- */
-export function buildInlineScriptForPhraseFilter(scriptedField) {
- // We must wrap painless scripts in a lambda in case they're more than a simple expression
- if (scriptedField.lang === 'painless') {
- return `boolean compare(Supplier s, def v) {return s.get() == v;}` +
- `compare(() -> { ${scriptedField.script} }, params.value);`;
- }
- else {
- return `(${scriptedField.script}) == value`;
- }
-}
diff --git a/packages/kbn-es-query/src/index.d.ts b/packages/kbn-es-query/src/index.d.ts
index ca4455da33f45..c06cef6367fe7 100644
--- a/packages/kbn-es-query/src/index.d.ts
+++ b/packages/kbn-es-query/src/index.d.ts
@@ -19,4 +19,3 @@
export * from './es_query';
export * from './kuery';
-export * from './filters';
diff --git a/packages/kbn-es-query/src/index.js b/packages/kbn-es-query/src/index.js
index 086b2f6db8d0d..963999bd0999b 100644
--- a/packages/kbn-es-query/src/index.js
+++ b/packages/kbn-es-query/src/index.js
@@ -18,5 +18,4 @@
*/
export * from './kuery';
-export * from './filters';
export * from './es_query';
diff --git a/packages/kbn-es-query/src/kuery/ast/__tests__/ast.js b/packages/kbn-es-query/src/kuery/ast/__tests__/ast.js
index 1ba10ddca54ac..3cbe1203bc533 100644
--- a/packages/kbn-es-query/src/kuery/ast/__tests__/ast.js
+++ b/packages/kbn-es-query/src/kuery/ast/__tests__/ast.js
@@ -198,6 +198,68 @@ describe('kuery AST API', function () {
expect(actual).to.eql(expected);
});
+ it('should support nested queries indicated by curly braces', () => {
+ const expected = nodeTypes.function.buildNode(
+ 'nested',
+ 'nestedField',
+ nodeTypes.function.buildNode('is', 'childOfNested', 'foo')
+ );
+ const actual = ast.fromKueryExpression('nestedField:{ childOfNested: foo }');
+ expect(actual).to.eql(expected);
+ });
+
+ it('should support nested subqueries and subqueries inside nested queries', () => {
+ const expected = nodeTypes.function.buildNode(
+ 'and',
+ [
+ nodeTypes.function.buildNode('is', 'response', '200'),
+ nodeTypes.function.buildNode(
+ 'nested',
+ 'nestedField',
+ nodeTypes.function.buildNode('or', [
+ nodeTypes.function.buildNode('is', 'childOfNested', 'foo'),
+ nodeTypes.function.buildNode('is', 'childOfNested', 'bar'),
+ ])
+ )]);
+ const actual = ast.fromKueryExpression('response:200 and nestedField:{ childOfNested:foo or childOfNested:bar }');
+ expect(actual).to.eql(expected);
+ });
+
+ it('should support nested sub-queries inside paren groups', () => {
+ const expected = nodeTypes.function.buildNode(
+ 'and',
+ [
+ nodeTypes.function.buildNode('is', 'response', '200'),
+ nodeTypes.function.buildNode('or', [
+ nodeTypes.function.buildNode(
+ 'nested',
+ 'nestedField',
+ nodeTypes.function.buildNode('is', 'childOfNested', 'foo')
+ ),
+ nodeTypes.function.buildNode(
+ 'nested',
+ 'nestedField',
+ nodeTypes.function.buildNode('is', 'childOfNested', 'bar')
+ ),
+ ])
+ ]);
+ const actual = ast.fromKueryExpression('response:200 and ( nestedField:{ childOfNested:foo } or nestedField:{ childOfNested:bar } )');
+ expect(actual).to.eql(expected);
+ });
+
+ it('should support nested groups inside other nested groups', () => {
+ const expected = nodeTypes.function.buildNode(
+ 'nested',
+ 'nestedField',
+ nodeTypes.function.buildNode(
+ 'nested',
+ 'nestedChild',
+ nodeTypes.function.buildNode('is', 'doublyNestedChild', 'foo')
+ )
+ );
+ const actual = ast.fromKueryExpression('nestedField:{ nestedChild:{ doublyNestedChild:foo } }');
+ expect(actual).to.eql(expected);
+ });
});
describe('fromLiteralExpression', function () {
diff --git a/packages/kbn-es-query/src/kuery/ast/ast.js b/packages/kbn-es-query/src/kuery/ast/ast.js
index 0bf2b258ba1f4..1688995d46f80 100644
--- a/packages/kbn-es-query/src/kuery/ast/ast.js
+++ b/packages/kbn-es-query/src/kuery/ast/ast.js
@@ -63,12 +63,12 @@ function fromExpression(expression, parseOptions = {}, parse = parseKuery) {
* IndexPattern isn't required, but if you pass one in, we can be more intelligent
* about how we craft the queries (e.g. scripted fields)
*/
-export function toElasticsearchQuery(node, indexPattern, config = {}) {
+export function toElasticsearchQuery(node, indexPattern, config = {}, context = {}) {
if (!node || !node.type || !nodeTypes[node.type]) {
return toElasticsearchQuery(nodeTypes.function.buildNode('and', []));
}
- return nodeTypes[node.type].toElasticsearchQuery(node, indexPattern, config);
+ return nodeTypes[node.type].toElasticsearchQuery(node, indexPattern, config, context);
}
export function doesKueryExpressionHaveLuceneSyntaxError(expression) {
diff --git a/packages/kbn-es-query/src/kuery/ast/kuery.js b/packages/kbn-es-query/src/kuery/ast/kuery.js
index d39145df79073..f745f01873bae 100644
--- a/packages/kbn-es-query/src/kuery/ast/kuery.js
+++ b/packages/kbn-es-query/src/kuery/ast/kuery.js
@@ -74,8 +74,30 @@ module.exports = (function() {
}
return query;
},
- peg$c10 = { type: "other", description: "fieldName" },
- peg$c11 = function(field, operator, value) {
+ peg$c10 = ":",
+ peg$c11 = { type: "literal", value: ":", description: "\":\"" },
+ peg$c12 = "{",
+ peg$c13 = { type: "literal", value: "{", description: "\"{\"" },
+ peg$c14 = "}",
+ peg$c15 = { type: "literal", value: "}", description: "\"}\"" },
+ peg$c16 = function(field, query, trailing) {
+ if (query.type === 'cursor') {
+ return {
+ ...query,
+ nestedPath: query.nestedPath ? `${field.value}.${query.nestedPath}` : field.value,
+ }
+ };
+
+ if (trailing.type === 'cursor') {
+ return {
+ ...trailing,
+ suggestionTypes: ['conjunction']
+ };
+ }
+ return buildFunctionNode('nested', [field, query]);
+ },
+ peg$c17 = { type: "other", description: "fieldName" },
+ peg$c18 = function(field, operator, value) {
if (value.type === 'cursor') {
return {
...value,
@@ -85,9 +107,7 @@ module.exports = (function() {
const range = buildNamedArgNode(operator, value);
return buildFunctionNode('range', [field, range]);
},
- peg$c12 = ":",
- peg$c13 = { type: "literal", value: ":", description: "\":\"" },
- peg$c14 = function(field, partial) {
+ peg$c19 = function(field, partial) {
if (partial.type === 'cursor') {
return {
...partial,
@@ -97,7 +117,7 @@ module.exports = (function() {
}
return partial(field);
},
- peg$c15 = function(partial) {
+ peg$c20 = function(partial) {
if (partial.type === 'cursor') {
const fieldName = `${partial.prefix}${partial.suffix}`.trim();
return {
@@ -109,7 +129,7 @@ module.exports = (function() {
const field = buildLiteralNode(null);
return partial(field);
},
- peg$c16 = function(partial, trailing) {
+ peg$c21 = function(partial, trailing) {
if (trailing.type === 'cursor') {
return {
...trailing,
@@ -118,7 +138,7 @@ module.exports = (function() {
}
return partial;
},
- peg$c17 = function(partialLeft, partialRight) {
+ peg$c22 = function(partialLeft, partialRight) {
const cursor = [partialLeft, partialRight].find(node => node.type === 'cursor');
if (cursor) {
return {
@@ -128,7 +148,7 @@ module.exports = (function() {
}
return (field) => buildFunctionNode('or', [partialLeft(field), partialRight(field)]);
},
- peg$c18 = function(partialLeft, partialRight) {
+ peg$c23 = function(partialLeft, partialRight) {
const cursor = [partialLeft, partialRight].find(node => node.type === 'cursor');
if (cursor) {
return {
@@ -138,7 +158,7 @@ module.exports = (function() {
}
return (field) => buildFunctionNode('and', [partialLeft(field), partialRight(field)]);
},
- peg$c19 = function(partial) {
+ peg$c24 = function(partial) {
if (partial.type === 'cursor') {
return {
...list,
@@ -147,13 +167,13 @@ module.exports = (function() {
}
return (field) => buildFunctionNode('not', [partial(field)]);
},
- peg$c20 = { type: "other", description: "value" },
- peg$c21 = function(value) {
+ peg$c25 = { type: "other", description: "value" },
+ peg$c26 = function(value) {
if (value.type === 'cursor') return value;
const isPhrase = buildLiteralNode(true);
return (field) => buildFunctionNode('is', [field, value, isPhrase]);
},
- peg$c22 = function(value) {
+ peg$c27 = function(value) {
if (value.type === 'cursor') return value;
if (!allowLeadingWildcards && value.type === 'wildcard' && nodeTypes.wildcard.hasLeadingWildcard(value)) {
@@ -163,19 +183,19 @@ module.exports = (function() {
const isPhrase = buildLiteralNode(false);
return (field) => buildFunctionNode('is', [field, value, isPhrase]);
},
- peg$c23 = { type: "other", description: "OR" },
- peg$c24 = "or",
- peg$c25 = { type: "literal", value: "or", description: "\"or\"" },
- peg$c26 = { type: "other", description: "AND" },
- peg$c27 = "and",
- peg$c28 = { type: "literal", value: "and", description: "\"and\"" },
- peg$c29 = { type: "other", description: "NOT" },
- peg$c30 = "not",
- peg$c31 = { type: "literal", value: "not", description: "\"not\"" },
- peg$c32 = { type: "other", description: "literal" },
- peg$c33 = "\"",
- peg$c34 = { type: "literal", value: "\"", description: "\"\\\"\"" },
- peg$c35 = function(prefix, cursor, suffix) {
+ peg$c28 = { type: "other", description: "OR" },
+ peg$c29 = "or",
+ peg$c30 = { type: "literal", value: "or", description: "\"or\"" },
+ peg$c31 = { type: "other", description: "AND" },
+ peg$c32 = "and",
+ peg$c33 = { type: "literal", value: "and", description: "\"and\"" },
+ peg$c34 = { type: "other", description: "NOT" },
+ peg$c35 = "not",
+ peg$c36 = { type: "literal", value: "not", description: "\"not\"" },
+ peg$c37 = { type: "other", description: "literal" },
+ peg$c38 = "\"",
+ peg$c39 = { type: "literal", value: "\"", description: "\"\\\"\"" },
+ peg$c40 = function(prefix, cursor, suffix) {
const { start, end } = location();
return {
type: 'cursor',
@@ -186,17 +206,17 @@ module.exports = (function() {
text: text().replace(cursor, '')
};
},
- peg$c36 = function(chars) {
+ peg$c41 = function(chars) {
return buildLiteralNode(chars.join(''));
},
- peg$c37 = "\\",
- peg$c38 = { type: "literal", value: "\\", description: "\"\\\\\"" },
- peg$c39 = /^[\\"]/,
- peg$c40 = { type: "class", value: "[\\\\\"]", description: "[\\\\\"]" },
- peg$c41 = function(char) { return char; },
- peg$c42 = /^[^"]/,
- peg$c43 = { type: "class", value: "[^\"]", description: "[^\"]" },
- peg$c44 = function(chars) {
+ peg$c42 = "\\",
+ peg$c43 = { type: "literal", value: "\\", description: "\"\\\\\"" },
+ peg$c44 = /^[\\"]/,
+ peg$c45 = { type: "class", value: "[\\\\\"]", description: "[\\\\\"]" },
+ peg$c46 = function(char) { return char; },
+ peg$c47 = /^[^"]/,
+ peg$c48 = { type: "class", value: "[^\"]", description: "[^\"]" },
+ peg$c49 = function(chars) {
const sequence = chars.join('').trim();
if (sequence === 'null') return buildLiteralNode(null);
if (sequence === 'true') return buildLiteralNode(true);
@@ -206,108 +226,104 @@ module.exports = (function() {
const value = isNaN(number) ? sequence : number;
return buildLiteralNode(value);
},
- peg$c45 = { type: "any", description: "any character" },
- peg$c46 = "*",
- peg$c47 = { type: "literal", value: "*", description: "\"*\"" },
- peg$c48 = function() { return wildcardSymbol; },
- peg$c49 = "\\t",
- peg$c50 = { type: "literal", value: "\\t", description: "\"\\\\t\"" },
- peg$c51 = function() { return '\t'; },
- peg$c52 = "\\r",
- peg$c53 = { type: "literal", value: "\\r", description: "\"\\\\r\"" },
- peg$c54 = function() { return '\r'; },
- peg$c55 = "\\n",
- peg$c56 = { type: "literal", value: "\\n", description: "\"\\\\n\"" },
- peg$c57 = function() { return '\n'; },
- peg$c58 = function(keyword) { return keyword; },
- peg$c59 = /^[\\():<>"*]/,
- peg$c60 = { type: "class", value: "[\\\\():<>\"*]", description: "[\\\\():<>\"*]" },
- peg$c61 = "<=",
- peg$c62 = { type: "literal", value: "<=", description: "\"<=\"" },
- peg$c63 = function() { return 'lte'; },
- peg$c64 = ">=",
- peg$c65 = { type: "literal", value: ">=", description: "\">=\"" },
- peg$c66 = function() { return 'gte'; },
- peg$c67 = "<",
- peg$c68 = { type: "literal", value: "<", description: "\"<\"" },
- peg$c69 = function() { return 'lt'; },
- peg$c70 = ">",
- peg$c71 = { type: "literal", value: ">", description: "\">\"" },
- peg$c72 = function() { return 'gt'; },
- peg$c73 = { type: "other", description: "whitespace" },
- peg$c74 = /^[ \t\r\n]/,
- peg$c75 = { type: "class", value: "[\\ \\t\\r\\n]", description: "[\\ \\t\\r\\n]" },
- peg$c76 = function() { return parseCursor; },
- peg$c77 = "@kuery-cursor@",
- peg$c78 = { type: "literal", value: "@kuery-cursor@", description: "\"@kuery-cursor@\"" },
- peg$c79 = function() { return cursorSymbol; },
- peg$c80 = "||",
- peg$c81 = { type: "literal", value: "||", description: "\"||\"" },
- peg$c82 = function() {
+ peg$c50 = { type: "any", description: "any character" },
+ peg$c51 = "*",
+ peg$c52 = { type: "literal", value: "*", description: "\"*\"" },
+ peg$c53 = function() { return wildcardSymbol; },
+ peg$c54 = "\\t",
+ peg$c55 = { type: "literal", value: "\\t", description: "\"\\\\t\"" },
+ peg$c56 = function() { return '\t'; },
+ peg$c57 = "\\r",
+ peg$c58 = { type: "literal", value: "\\r", description: "\"\\\\r\"" },
+ peg$c59 = function() { return '\r'; },
+ peg$c60 = "\\n",
+ peg$c61 = { type: "literal", value: "\\n", description: "\"\\\\n\"" },
+ peg$c62 = function() { return '\n'; },
+ peg$c63 = function(keyword) { return keyword; },
+ peg$c64 = /^[\\():<>"*{}]/,
+ peg$c65 = { type: "class", value: "[\\\\():<>\"*{}]", description: "[\\\\():<>\"*{}]" },
+ peg$c66 = "<=",
+ peg$c67 = { type: "literal", value: "<=", description: "\"<=\"" },
+ peg$c68 = function() { return 'lte'; },
+ peg$c69 = ">=",
+ peg$c70 = { type: "literal", value: ">=", description: "\">=\"" },
+ peg$c71 = function() { return 'gte'; },
+ peg$c72 = "<",
+ peg$c73 = { type: "literal", value: "<", description: "\"<\"" },
+ peg$c74 = function() { return 'lt'; },
+ peg$c75 = ">",
+ peg$c76 = { type: "literal", value: ">", description: "\">\"" },
+ peg$c77 = function() { return 'gt'; },
+ peg$c78 = { type: "other", description: "whitespace" },
+ peg$c79 = /^[ \t\r\n]/,
+ peg$c80 = { type: "class", value: "[\\ \\t\\r\\n]", description: "[\\ \\t\\r\\n]" },
+ peg$c81 = function() { return parseCursor; },
+ peg$c82 = "@kuery-cursor@",
+ peg$c83 = { type: "literal", value: "@kuery-cursor@", description: "\"@kuery-cursor@\"" },
+ peg$c84 = function() { return cursorSymbol; },
+ peg$c85 = "||",
+ peg$c86 = { type: "literal", value: "||", description: "\"||\"" },
+ peg$c87 = function() {
error('LuceneOr');
},
- peg$c83 = "&&",
- peg$c84 = { type: "literal", value: "&&", description: "\"&&\"" },
- peg$c85 = function() {
+ peg$c88 = "&&",
+ peg$c89 = { type: "literal", value: "&&", description: "\"&&\"" },
+ peg$c90 = function() {
error('LuceneAnd');
},
- peg$c86 = "+",
- peg$c87 = { type: "literal", value: "+", description: "\"+\"" },
- peg$c88 = "-",
- peg$c89 = { type: "literal", value: "-", description: "\"-\"" },
- peg$c90 = function() {
+ peg$c91 = "+",
+ peg$c92 = { type: "literal", value: "+", description: "\"+\"" },
+ peg$c93 = "-",
+ peg$c94 = { type: "literal", value: "-", description: "\"-\"" },
+ peg$c95 = function() {
error('LuceneNot');
},
- peg$c91 = "!",
- peg$c92 = { type: "literal", value: "!", description: "\"!\"" },
- peg$c93 = "_exists_",
- peg$c94 = { type: "literal", value: "_exists_", description: "\"_exists_\"" },
- peg$c95 = function() {
+ peg$c96 = "!",
+ peg$c97 = { type: "literal", value: "!", description: "\"!\"" },
+ peg$c98 = "_exists_",
+ peg$c99 = { type: "literal", value: "_exists_", description: "\"_exists_\"" },
+ peg$c100 = function() {
error('LuceneExists');
},
- peg$c96 = function() {
+ peg$c101 = function() {
error('LuceneRange');
},
- peg$c97 = "?",
- peg$c98 = { type: "literal", value: "?", description: "\"?\"" },
- peg$c99 = function() {
+ peg$c102 = "?",
+ peg$c103 = { type: "literal", value: "?", description: "\"?\"" },
+ peg$c104 = function() {
error('LuceneWildcard');
},
- peg$c100 = "/",
- peg$c101 = { type: "literal", value: "/", description: "\"/\"" },
- peg$c102 = /^[^\/]/,
- peg$c103 = { type: "class", value: "[^/]", description: "[^/]" },
- peg$c104 = function() {
+ peg$c105 = "/",
+ peg$c106 = { type: "literal", value: "/", description: "\"/\"" },
+ peg$c107 = /^[^\/]/,
+ peg$c108 = { type: "class", value: "[^/]", description: "[^/]" },
+ peg$c109 = function() {
error('LuceneRegex');
},
- peg$c105 = "~",
- peg$c106 = { type: "literal", value: "~", description: "\"~\"" },
- peg$c107 = /^[0-9]/,
- peg$c108 = { type: "class", value: "[0-9]", description: "[0-9]" },
- peg$c109 = function() {
+ peg$c110 = "~",
+ peg$c111 = { type: "literal", value: "~", description: "\"~\"" },
+ peg$c112 = /^[0-9]/,
+ peg$c113 = { type: "class", value: "[0-9]", description: "[0-9]" },
+ peg$c114 = function() {
error('LuceneFuzzy');
},
- peg$c110 = function() {
+ peg$c115 = function() {
error('LuceneProximity');
},
- peg$c111 = "^",
- peg$c112 = { type: "literal", value: "^", description: "\"^\"" },
- peg$c113 = function() {
+ peg$c116 = "^",
+ peg$c117 = { type: "literal", value: "^", description: "\"^\"" },
+ peg$c118 = function() {
error('LuceneBoost');
},
- peg$c114 = function() { return char; },
- peg$c115 = "=",
- peg$c116 = { type: "literal", value: "=", description: "\"=\"" },
- peg$c117 = "{",
- peg$c118 = { type: "literal", value: "{", description: "\"{\"" },
- peg$c119 = "}",
- peg$c120 = { type: "literal", value: "}", description: "\"}\"" },
- peg$c121 = "[",
- peg$c122 = { type: "literal", value: "[", description: "\"[\"" },
- peg$c123 = "]",
- peg$c124 = { type: "literal", value: "]", description: "\"]\"" },
- peg$c125 = "TO",
- peg$c126 = { type: "literal", value: "TO", description: "\"TO\"" },
+ peg$c119 = function() { return char; },
+ peg$c120 = "=",
+ peg$c121 = { type: "literal", value: "=", description: "\"=\"" },
+ peg$c122 = "[",
+ peg$c123 = { type: "literal", value: "[", description: "\"[\"" },
+ peg$c124 = "]",
+ peg$c125 = { type: "literal", value: "]", description: "\"]\"" },
+ peg$c126 = "TO",
+ peg$c127 = { type: "literal", value: "TO", description: "\"TO\"" },
peg$currPos = 0,
peg$savedPos = 0,
@@ -698,6 +714,107 @@ module.exports = (function() {
peg$currPos = s0;
s0 = peg$FAILED;
}
+ if (s0 === peg$FAILED) {
+ s0 = peg$parseNestedQuery();
+ }
+
+ return s0;
+ }
+
+ function peg$parseNestedQuery() {
+ var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
+
+ s0 = peg$currPos;
+ s1 = peg$parseField();
+ if (s1 !== peg$FAILED) {
+ s2 = [];
+ s3 = peg$parseSpace();
+ while (s3 !== peg$FAILED) {
+ s2.push(s3);
+ s3 = peg$parseSpace();
+ }
+ if (s2 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 58) {
+ s3 = peg$c10;
+ peg$currPos++;
+ } else {
+ s3 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c11); }
+ }
+ if (s3 !== peg$FAILED) {
+ s4 = [];
+ s5 = peg$parseSpace();
+ while (s5 !== peg$FAILED) {
+ s4.push(s5);
+ s5 = peg$parseSpace();
+ }
+ if (s4 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 123) {
+ s5 = peg$c12;
+ peg$currPos++;
+ } else {
+ s5 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c13); }
+ }
+ if (s5 !== peg$FAILED) {
+ s6 = [];
+ s7 = peg$parseSpace();
+ while (s7 !== peg$FAILED) {
+ s6.push(s7);
+ s7 = peg$parseSpace();
+ }
+ if (s6 !== peg$FAILED) {
+ s7 = peg$parseOrQuery();
+ if (s7 !== peg$FAILED) {
+ s8 = peg$parseOptionalSpace();
+ if (s8 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 125) {
+ s9 = peg$c14;
+ peg$currPos++;
+ } else {
+ s9 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c15); }
+ }
+ if (s9 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c16(s1, s7, s8);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
if (s0 === peg$FAILED) {
s0 = peg$parseExpression();
}
@@ -727,7 +844,7 @@ module.exports = (function() {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c10); }
+ if (peg$silentFails === 0) { peg$fail(peg$c17); }
}
return s0;
@@ -758,7 +875,7 @@ module.exports = (function() {
s5 = peg$parseLiteral();
if (s5 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c11(s1, s3, s5);
+ s1 = peg$c18(s1, s3, s5);
s0 = s1;
} else {
peg$currPos = s0;
@@ -798,11 +915,11 @@ module.exports = (function() {
}
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 58) {
- s3 = peg$c12;
+ s3 = peg$c10;
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c13); }
+ if (peg$silentFails === 0) { peg$fail(peg$c11); }
}
if (s3 !== peg$FAILED) {
s4 = [];
@@ -815,7 +932,7 @@ module.exports = (function() {
s5 = peg$parseListOfValues();
if (s5 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c14(s1, s5);
+ s1 = peg$c19(s1, s5);
s0 = s1;
} else {
peg$currPos = s0;
@@ -848,7 +965,7 @@ module.exports = (function() {
s1 = peg$parseValue();
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c15(s1);
+ s1 = peg$c20(s1);
}
s0 = s1;
@@ -887,7 +1004,7 @@ module.exports = (function() {
}
if (s5 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c16(s3, s4);
+ s1 = peg$c21(s3, s4);
s0 = s1;
} else {
peg$currPos = s0;
@@ -927,7 +1044,7 @@ module.exports = (function() {
s3 = peg$parseOrListOfValues();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c17(s1, s3);
+ s1 = peg$c22(s1, s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -959,7 +1076,7 @@ module.exports = (function() {
s3 = peg$parseAndListOfValues();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c18(s1, s3);
+ s1 = peg$c23(s1, s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -989,7 +1106,7 @@ module.exports = (function() {
s2 = peg$parseListOfValues();
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c19(s2);
+ s1 = peg$c24(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1014,7 +1131,7 @@ module.exports = (function() {
s1 = peg$parseQuotedString();
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c21(s1);
+ s1 = peg$c26(s1);
}
s0 = s1;
if (s0 === peg$FAILED) {
@@ -1022,14 +1139,14 @@ module.exports = (function() {
s1 = peg$parseUnquotedLiteral();
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c22(s1);
+ s1 = peg$c27(s1);
}
s0 = s1;
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c20); }
+ if (peg$silentFails === 0) { peg$fail(peg$c25); }
}
return s0;
@@ -1051,12 +1168,12 @@ module.exports = (function() {
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
- if (input.substr(peg$currPos, 2).toLowerCase() === peg$c24) {
+ if (input.substr(peg$currPos, 2).toLowerCase() === peg$c29) {
s2 = input.substr(peg$currPos, 2);
peg$currPos += 2;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c25); }
+ if (peg$silentFails === 0) { peg$fail(peg$c30); }
}
if (s2 !== peg$FAILED) {
s3 = [];
@@ -1110,7 +1227,7 @@ module.exports = (function() {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c23); }
+ if (peg$silentFails === 0) { peg$fail(peg$c28); }
}
return s0;
@@ -1132,12 +1249,12 @@ module.exports = (function() {
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
- if (input.substr(peg$currPos, 3).toLowerCase() === peg$c27) {
+ if (input.substr(peg$currPos, 3).toLowerCase() === peg$c32) {
s2 = input.substr(peg$currPos, 3);
peg$currPos += 3;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c28); }
+ if (peg$silentFails === 0) { peg$fail(peg$c33); }
}
if (s2 !== peg$FAILED) {
s3 = [];
@@ -1191,7 +1308,7 @@ module.exports = (function() {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c26); }
+ if (peg$silentFails === 0) { peg$fail(peg$c31); }
}
return s0;
@@ -1202,12 +1319,12 @@ module.exports = (function() {
peg$silentFails++;
s0 = peg$currPos;
- if (input.substr(peg$currPos, 3).toLowerCase() === peg$c30) {
+ if (input.substr(peg$currPos, 3).toLowerCase() === peg$c35) {
s1 = input.substr(peg$currPos, 3);
peg$currPos += 3;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c31); }
+ if (peg$silentFails === 0) { peg$fail(peg$c36); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1257,7 +1374,7 @@ module.exports = (function() {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c29); }
+ if (peg$silentFails === 0) { peg$fail(peg$c34); }
}
return s0;
@@ -1274,7 +1391,7 @@ module.exports = (function() {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c32); }
+ if (peg$silentFails === 0) { peg$fail(peg$c37); }
}
return s0;
@@ -1285,11 +1402,11 @@ module.exports = (function() {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 34) {
- s1 = peg$c33;
+ s1 = peg$c38;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c34); }
+ if (peg$silentFails === 0) { peg$fail(peg$c39); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1309,15 +1426,15 @@ module.exports = (function() {
}
if (s4 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 34) {
- s5 = peg$c33;
+ s5 = peg$c38;
peg$currPos++;
} else {
s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c34); }
+ if (peg$silentFails === 0) { peg$fail(peg$c39); }
}
if (s5 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c35(s2, s3, s4);
+ s1 = peg$c40(s2, s3, s4);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1342,11 +1459,11 @@ module.exports = (function() {
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 34) {
- s1 = peg$c33;
+ s1 = peg$c38;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c34); }
+ if (peg$silentFails === 0) { peg$fail(peg$c39); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1357,15 +1474,15 @@ module.exports = (function() {
}
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 34) {
- s3 = peg$c33;
+ s3 = peg$c38;
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c34); }
+ if (peg$silentFails === 0) { peg$fail(peg$c39); }
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c36(s2);
+ s1 = peg$c41(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1391,23 +1508,23 @@ module.exports = (function() {
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 92) {
- s1 = peg$c37;
+ s1 = peg$c42;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c38); }
+ if (peg$silentFails === 0) { peg$fail(peg$c43); }
}
if (s1 !== peg$FAILED) {
- if (peg$c39.test(input.charAt(peg$currPos))) {
+ if (peg$c44.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c40); }
+ if (peg$silentFails === 0) { peg$fail(peg$c45); }
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c41(s2);
+ s1 = peg$c46(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1430,16 +1547,16 @@ module.exports = (function() {
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
- if (peg$c42.test(input.charAt(peg$currPos))) {
+ if (peg$c47.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c43); }
+ if (peg$silentFails === 0) { peg$fail(peg$c48); }
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c41(s2);
+ s1 = peg$c46(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1476,7 +1593,7 @@ module.exports = (function() {
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c35(s1, s2, s3);
+ s1 = peg$c40(s1, s2, s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1504,7 +1621,7 @@ module.exports = (function() {
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c44(s1);
+ s1 = peg$c49(s1);
}
s0 = s1;
}
@@ -1562,11 +1679,11 @@ module.exports = (function() {
peg$currPos++;
} else {
s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c45); }
+ if (peg$silentFails === 0) { peg$fail(peg$c50); }
}
if (s4 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c41(s4);
+ s1 = peg$c46(s4);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1597,15 +1714,15 @@ module.exports = (function() {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 42) {
- s1 = peg$c46;
+ s1 = peg$c51;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c47); }
+ if (peg$silentFails === 0) { peg$fail(peg$c52); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c48();
+ s1 = peg$c53();
}
s0 = s1;
@@ -1633,7 +1750,7 @@ module.exports = (function() {
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c35(s1, s2, s3);
+ s1 = peg$c40(s1, s2, s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1663,44 +1780,44 @@ module.exports = (function() {
var s0, s1;
s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c49) {
- s1 = peg$c49;
+ if (input.substr(peg$currPos, 2) === peg$c54) {
+ s1 = peg$c54;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c50); }
+ if (peg$silentFails === 0) { peg$fail(peg$c55); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c51();
+ s1 = peg$c56();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c52) {
- s1 = peg$c52;
+ if (input.substr(peg$currPos, 2) === peg$c57) {
+ s1 = peg$c57;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c53); }
+ if (peg$silentFails === 0) { peg$fail(peg$c58); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c54();
+ s1 = peg$c59();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c55) {
- s1 = peg$c55;
+ if (input.substr(peg$currPos, 2) === peg$c60) {
+ s1 = peg$c60;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c56); }
+ if (peg$silentFails === 0) { peg$fail(peg$c61); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c57();
+ s1 = peg$c62();
}
s0 = s1;
}
@@ -1714,17 +1831,17 @@ module.exports = (function() {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 92) {
- s1 = peg$c37;
+ s1 = peg$c42;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c38); }
+ if (peg$silentFails === 0) { peg$fail(peg$c43); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parseSpecialCharacter();
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c41(s2);
+ s1 = peg$c46(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1743,41 +1860,41 @@ module.exports = (function() {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 92) {
- s1 = peg$c37;
+ s1 = peg$c42;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c38); }
+ if (peg$silentFails === 0) { peg$fail(peg$c43); }
}
if (s1 !== peg$FAILED) {
- if (input.substr(peg$currPos, 2).toLowerCase() === peg$c24) {
+ if (input.substr(peg$currPos, 2).toLowerCase() === peg$c29) {
s2 = input.substr(peg$currPos, 2);
peg$currPos += 2;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c25); }
+ if (peg$silentFails === 0) { peg$fail(peg$c30); }
}
if (s2 === peg$FAILED) {
- if (input.substr(peg$currPos, 3).toLowerCase() === peg$c27) {
+ if (input.substr(peg$currPos, 3).toLowerCase() === peg$c32) {
s2 = input.substr(peg$currPos, 3);
peg$currPos += 3;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c28); }
+ if (peg$silentFails === 0) { peg$fail(peg$c33); }
}
if (s2 === peg$FAILED) {
- if (input.substr(peg$currPos, 3).toLowerCase() === peg$c30) {
+ if (input.substr(peg$currPos, 3).toLowerCase() === peg$c35) {
s2 = input.substr(peg$currPos, 3);
peg$currPos += 3;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c31); }
+ if (peg$silentFails === 0) { peg$fail(peg$c36); }
}
}
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c58(s2);
+ s1 = peg$c63(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1808,12 +1925,12 @@ module.exports = (function() {
function peg$parseSpecialCharacter() {
var s0;
- if (peg$c59.test(input.charAt(peg$currPos))) {
+ if (peg$c64.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c60); }
+ if (peg$silentFails === 0) { peg$fail(peg$c65); }
}
return s0;
@@ -1823,58 +1940,58 @@ module.exports = (function() {
var s0, s1;
s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c61) {
- s1 = peg$c61;
+ if (input.substr(peg$currPos, 2) === peg$c66) {
+ s1 = peg$c66;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c62); }
+ if (peg$silentFails === 0) { peg$fail(peg$c67); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c63();
+ s1 = peg$c68();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c64) {
- s1 = peg$c64;
+ if (input.substr(peg$currPos, 2) === peg$c69) {
+ s1 = peg$c69;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c65); }
+ if (peg$silentFails === 0) { peg$fail(peg$c70); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c66();
+ s1 = peg$c71();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 60) {
- s1 = peg$c67;
+ s1 = peg$c72;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c68); }
+ if (peg$silentFails === 0) { peg$fail(peg$c73); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c69();
+ s1 = peg$c74();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 62) {
- s1 = peg$c70;
+ s1 = peg$c75;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c71); }
+ if (peg$silentFails === 0) { peg$fail(peg$c76); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c72();
+ s1 = peg$c77();
}
s0 = s1;
}
@@ -1888,17 +2005,17 @@ module.exports = (function() {
var s0, s1;
peg$silentFails++;
- if (peg$c74.test(input.charAt(peg$currPos))) {
+ if (peg$c79.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c75); }
+ if (peg$silentFails === 0) { peg$fail(peg$c80); }
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c73); }
+ if (peg$silentFails === 0) { peg$fail(peg$c78); }
}
return s0;
@@ -1909,23 +2026,23 @@ module.exports = (function() {
s0 = peg$currPos;
peg$savedPos = peg$currPos;
- s1 = peg$c76();
+ s1 = peg$c81();
if (s1) {
s1 = void 0;
} else {
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
- if (input.substr(peg$currPos, 14) === peg$c77) {
- s2 = peg$c77;
+ if (input.substr(peg$currPos, 14) === peg$c82) {
+ s2 = peg$c82;
peg$currPos += 14;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c78); }
+ if (peg$silentFails === 0) { peg$fail(peg$c83); }
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c79();
+ s1 = peg$c84();
s0 = s1;
} else {
peg$currPos = s0;
@@ -1950,12 +2067,12 @@ module.exports = (function() {
s2 = peg$parseSpace();
}
if (s1 !== peg$FAILED) {
- if (input.substr(peg$currPos, 2) === peg$c80) {
- s2 = peg$c80;
+ if (input.substr(peg$currPos, 2) === peg$c85) {
+ s2 = peg$c85;
peg$currPos += 2;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c81); }
+ if (peg$silentFails === 0) { peg$fail(peg$c86); }
}
if (s2 !== peg$FAILED) {
s3 = [];
@@ -1966,7 +2083,7 @@ module.exports = (function() {
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c82();
+ s1 = peg$c87();
s0 = s1;
} else {
peg$currPos = s0;
@@ -1995,12 +2112,12 @@ module.exports = (function() {
s2 = peg$parseSpace();
}
if (s1 !== peg$FAILED) {
- if (input.substr(peg$currPos, 2) === peg$c83) {
- s2 = peg$c83;
+ if (input.substr(peg$currPos, 2) === peg$c88) {
+ s2 = peg$c88;
peg$currPos += 2;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c84); }
+ if (peg$silentFails === 0) { peg$fail(peg$c89); }
}
if (s2 !== peg$FAILED) {
s3 = [];
@@ -2011,7 +2128,7 @@ module.exports = (function() {
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c85();
+ s1 = peg$c90();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2028,15 +2145,15 @@ module.exports = (function() {
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 43) {
- s1 = peg$c86;
+ s1 = peg$c91;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c87); }
+ if (peg$silentFails === 0) { peg$fail(peg$c92); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c85();
+ s1 = peg$c90();
}
s0 = s1;
}
@@ -2049,29 +2166,29 @@ module.exports = (function() {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 45) {
- s1 = peg$c88;
+ s1 = peg$c93;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c89); }
+ if (peg$silentFails === 0) { peg$fail(peg$c94); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c90();
+ s1 = peg$c95();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 33) {
- s1 = peg$c91;
+ s1 = peg$c96;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c92); }
+ if (peg$silentFails === 0) { peg$fail(peg$c97); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c90();
+ s1 = peg$c95();
}
s0 = s1;
}
@@ -2107,11 +2224,11 @@ module.exports = (function() {
}
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 58) {
- s3 = peg$c12;
+ s3 = peg$c10;
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c13); }
+ if (peg$silentFails === 0) { peg$fail(peg$c11); }
}
if (s3 !== peg$FAILED) {
s4 = [];
@@ -2176,12 +2293,12 @@ module.exports = (function() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
- if (input.substr(peg$currPos, 8) === peg$c93) {
- s1 = peg$c93;
+ if (input.substr(peg$currPos, 8) === peg$c98) {
+ s1 = peg$c98;
peg$currPos += 8;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c94); }
+ if (peg$silentFails === 0) { peg$fail(peg$c99); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -2192,11 +2309,11 @@ module.exports = (function() {
}
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 58) {
- s3 = peg$c12;
+ s3 = peg$c10;
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c13); }
+ if (peg$silentFails === 0) { peg$fail(peg$c11); }
}
if (s3 !== peg$FAILED) {
s4 = [];
@@ -2209,7 +2326,7 @@ module.exports = (function() {
s5 = peg$parseLuceneLiteral();
if (s5 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c95();
+ s1 = peg$c100();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2251,7 +2368,7 @@ module.exports = (function() {
s3 = peg$parseLuceneLiteral();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c96();
+ s1 = peg$c101();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2285,7 +2402,7 @@ module.exports = (function() {
s6 = peg$parseLuceneRangeEnd();
if (s6 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c96();
+ s1 = peg$c101();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2324,11 +2441,11 @@ module.exports = (function() {
s2 = peg$parseLuceneUnquotedCharacter();
if (s2 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 42) {
- s2 = peg$c46;
+ s2 = peg$c51;
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c47); }
+ if (peg$silentFails === 0) { peg$fail(peg$c52); }
}
}
while (s2 !== peg$FAILED) {
@@ -2336,21 +2453,21 @@ module.exports = (function() {
s2 = peg$parseLuceneUnquotedCharacter();
if (s2 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 42) {
- s2 = peg$c46;
+ s2 = peg$c51;
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c47); }
+ if (peg$silentFails === 0) { peg$fail(peg$c52); }
}
}
}
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 63) {
- s2 = peg$c97;
+ s2 = peg$c102;
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c98); }
+ if (peg$silentFails === 0) { peg$fail(peg$c103); }
}
if (s2 !== peg$FAILED) {
s3 = [];
@@ -2361,7 +2478,7 @@ module.exports = (function() {
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c99();
+ s1 = peg$c104();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2384,42 +2501,42 @@ module.exports = (function() {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 47) {
- s1 = peg$c100;
+ s1 = peg$c105;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c101); }
+ if (peg$silentFails === 0) { peg$fail(peg$c106); }
}
if (s1 !== peg$FAILED) {
s2 = [];
- if (peg$c102.test(input.charAt(peg$currPos))) {
+ if (peg$c107.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c103); }
+ if (peg$silentFails === 0) { peg$fail(peg$c108); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
- if (peg$c102.test(input.charAt(peg$currPos))) {
+ if (peg$c107.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c103); }
+ if (peg$silentFails === 0) { peg$fail(peg$c108); }
}
}
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 47) {
- s3 = peg$c100;
+ s3 = peg$c105;
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c101); }
+ if (peg$silentFails === 0) { peg$fail(peg$c106); }
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c104();
+ s1 = peg$c109();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2444,34 +2561,34 @@ module.exports = (function() {
s1 = peg$parseLuceneUnquotedLiteral();
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 126) {
- s2 = peg$c105;
+ s2 = peg$c110;
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c106); }
+ if (peg$silentFails === 0) { peg$fail(peg$c111); }
}
if (s2 !== peg$FAILED) {
s3 = [];
- if (peg$c107.test(input.charAt(peg$currPos))) {
+ if (peg$c112.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c108); }
+ if (peg$silentFails === 0) { peg$fail(peg$c113); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
- if (peg$c107.test(input.charAt(peg$currPos))) {
+ if (peg$c112.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c108); }
+ if (peg$silentFails === 0) { peg$fail(peg$c113); }
}
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c109();
+ s1 = peg$c114();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2496,34 +2613,34 @@ module.exports = (function() {
s1 = peg$parseQuotedString();
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 126) {
- s2 = peg$c105;
+ s2 = peg$c110;
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c106); }
+ if (peg$silentFails === 0) { peg$fail(peg$c111); }
}
if (s2 !== peg$FAILED) {
s3 = [];
- if (peg$c107.test(input.charAt(peg$currPos))) {
+ if (peg$c112.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c108); }
+ if (peg$silentFails === 0) { peg$fail(peg$c113); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
- if (peg$c107.test(input.charAt(peg$currPos))) {
+ if (peg$c112.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c108); }
+ if (peg$silentFails === 0) { peg$fail(peg$c113); }
}
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c110();
+ s1 = peg$c115();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2548,34 +2665,34 @@ module.exports = (function() {
s1 = peg$parseLuceneLiteral();
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 94) {
- s2 = peg$c111;
+ s2 = peg$c116;
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c112); }
+ if (peg$silentFails === 0) { peg$fail(peg$c117); }
}
if (s2 !== peg$FAILED) {
s3 = [];
- if (peg$c107.test(input.charAt(peg$currPos))) {
+ if (peg$c112.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c108); }
+ if (peg$silentFails === 0) { peg$fail(peg$c113); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
- if (peg$c107.test(input.charAt(peg$currPos))) {
+ if (peg$c112.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c108); }
+ if (peg$silentFails === 0) { peg$fail(peg$c113); }
}
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c113();
+ s1 = peg$c118();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2656,7 +2773,7 @@ module.exports = (function() {
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c45); }
+ if (peg$silentFails === 0) { peg$fail(peg$c50); }
}
if (s3 !== peg$FAILED) {
s1 = [s1, s2, s3];
@@ -2707,17 +2824,17 @@ module.exports = (function() {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 92) {
- s1 = peg$c37;
+ s1 = peg$c42;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c38); }
+ if (peg$silentFails === 0) { peg$fail(peg$c43); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parseLuceneSpecialCharacter();
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c114();
+ s1 = peg$c119();
s0 = s1;
} else {
peg$currPos = s0;
@@ -2735,51 +2852,51 @@ module.exports = (function() {
var s0;
if (input.charCodeAt(peg$currPos) === 43) {
- s0 = peg$c86;
+ s0 = peg$c91;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c87); }
+ if (peg$silentFails === 0) { peg$fail(peg$c92); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 45) {
- s0 = peg$c88;
+ s0 = peg$c93;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c89); }
+ if (peg$silentFails === 0) { peg$fail(peg$c94); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 61) {
- s0 = peg$c115;
+ s0 = peg$c120;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c116); }
+ if (peg$silentFails === 0) { peg$fail(peg$c121); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 62) {
- s0 = peg$c70;
+ s0 = peg$c75;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c71); }
+ if (peg$silentFails === 0) { peg$fail(peg$c76); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 60) {
- s0 = peg$c67;
+ s0 = peg$c72;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c68); }
+ if (peg$silentFails === 0) { peg$fail(peg$c73); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 33) {
- s0 = peg$c91;
+ s0 = peg$c96;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c92); }
+ if (peg$silentFails === 0) { peg$fail(peg$c97); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 40) {
@@ -2799,99 +2916,99 @@ module.exports = (function() {
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 123) {
- s0 = peg$c117;
+ s0 = peg$c12;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c118); }
+ if (peg$silentFails === 0) { peg$fail(peg$c13); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 125) {
- s0 = peg$c119;
+ s0 = peg$c14;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c120); }
+ if (peg$silentFails === 0) { peg$fail(peg$c15); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 91) {
- s0 = peg$c121;
+ s0 = peg$c122;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c122); }
+ if (peg$silentFails === 0) { peg$fail(peg$c123); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 93) {
- s0 = peg$c123;
+ s0 = peg$c124;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c124); }
+ if (peg$silentFails === 0) { peg$fail(peg$c125); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 94) {
- s0 = peg$c111;
+ s0 = peg$c116;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c112); }
+ if (peg$silentFails === 0) { peg$fail(peg$c117); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 34) {
- s0 = peg$c33;
+ s0 = peg$c38;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c34); }
+ if (peg$silentFails === 0) { peg$fail(peg$c39); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 126) {
- s0 = peg$c105;
+ s0 = peg$c110;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c106); }
+ if (peg$silentFails === 0) { peg$fail(peg$c111); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 42) {
- s0 = peg$c46;
+ s0 = peg$c51;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c47); }
+ if (peg$silentFails === 0) { peg$fail(peg$c52); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 63) {
- s0 = peg$c97;
+ s0 = peg$c102;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c98); }
+ if (peg$silentFails === 0) { peg$fail(peg$c103); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 58) {
- s0 = peg$c12;
+ s0 = peg$c10;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c13); }
+ if (peg$silentFails === 0) { peg$fail(peg$c11); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 92) {
- s0 = peg$c37;
+ s0 = peg$c42;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c38); }
+ if (peg$silentFails === 0) { peg$fail(peg$c43); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 47) {
- s0 = peg$c100;
+ s0 = peg$c105;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c101); }
+ if (peg$silentFails === 0) { peg$fail(peg$c106); }
}
}
}
@@ -2931,12 +3048,12 @@ module.exports = (function() {
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
- if (input.substr(peg$currPos, 2) === peg$c125) {
- s2 = peg$c125;
+ if (input.substr(peg$currPos, 2) === peg$c126) {
+ s2 = peg$c126;
peg$currPos += 2;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c126); }
+ if (peg$silentFails === 0) { peg$fail(peg$c127); }
}
if (s2 !== peg$FAILED) {
s3 = [];
@@ -2972,19 +3089,19 @@ module.exports = (function() {
var s0;
if (input.charCodeAt(peg$currPos) === 91) {
- s0 = peg$c121;
+ s0 = peg$c122;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c122); }
+ if (peg$silentFails === 0) { peg$fail(peg$c123); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 123) {
- s0 = peg$c117;
+ s0 = peg$c12;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c118); }
+ if (peg$silentFails === 0) { peg$fail(peg$c13); }
}
}
@@ -2995,19 +3112,19 @@ module.exports = (function() {
var s0;
if (input.charCodeAt(peg$currPos) === 93) {
- s0 = peg$c123;
+ s0 = peg$c124;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c124); }
+ if (peg$silentFails === 0) { peg$fail(peg$c125); }
}
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 125) {
- s0 = peg$c119;
+ s0 = peg$c14;
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c120); }
+ if (peg$silentFails === 0) { peg$fail(peg$c15); }
}
}
diff --git a/packages/kbn-es-query/src/kuery/ast/kuery.peg b/packages/kbn-es-query/src/kuery/ast/kuery.peg
index ec8368d2a921d..389b9a82d2c76 100644
--- a/packages/kbn-es-query/src/kuery/ast/kuery.peg
+++ b/packages/kbn-es-query/src/kuery/ast/kuery.peg
@@ -59,7 +59,26 @@ SubQuery
}
return query;
}
- / Expression
+ / NestedQuery
+
+NestedQuery
+ = field:Field Space* ':' Space* '{' Space* query:OrQuery trailing:OptionalSpace '}' {
+ if (query.type === 'cursor') {
+ return {
+ ...query,
+ nestedPath: query.nestedPath ? `${field.value}.${query.nestedPath}` : field.value,
+ }
+ };
+
+ if (trailing.type === 'cursor') {
+ return {
+ ...trailing,
+ suggestionTypes: ['conjunction']
+ };
+ }
+ return buildFunctionNode('nested', [field, query]);
+ }
+ / Expression
Expression
= FieldRangeExpression
@@ -272,7 +291,7 @@ Keyword
= Or / And / Not
SpecialCharacter
- = [\\():<>"*]
+ = [\\():<>"*{}]
RangeOperator
= '<=' { return 'lte'; }
diff --git a/packages/kbn-es-query/src/kuery/errors/index.test.js b/packages/kbn-es-query/src/kuery/errors/index.test.js
index 91c90b2cce98b..d8040e464b696 100644
--- a/packages/kbn-es-query/src/kuery/errors/index.test.js
+++ b/packages/kbn-es-query/src/kuery/errors/index.test.js
@@ -25,7 +25,7 @@ describe('kql syntax errors', () => {
it('should throw an error for a field query missing a value', () => {
expect(() => {
fromKueryExpression('response:');
- }).toThrow('Expected "(", value, whitespace but end of input found.\n' +
+ }).toThrow('Expected "(", "{", value, whitespace but end of input found.\n' +
'response:\n' +
'---------^');
});
@@ -65,7 +65,7 @@ describe('kql syntax errors', () => {
it('should throw an error for unbalanced quotes', () => {
expect(() => {
fromKueryExpression('foo:"ba ');
- }).toThrow('Expected "(", value, whitespace but "\"" found.\n' +
+ }).toThrow('Expected "(", "{", value, whitespace but """ found.\n' +
'foo:"ba \n' +
'----^');
});
diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js b/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js
index 0eaa69a3243e0..ee4cfab94e614 100644
--- a/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js
+++ b/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js
@@ -72,6 +72,21 @@ describe('kuery functions', function () {
expect(exists.toElasticsearchQuery)
.withArgs(existsNode, indexPattern).to.throwException(/Exists query does not support scripted fields/);
});
+
+ it('should use a provided nested context to create a full field name', function () {
+ const expected = {
+ exists: { field: 'nestedField.response' }
+ };
+
+ const existsNode = nodeTypes.function.buildNode('exists', 'response');
+ const result = exists.toElasticsearchQuery(
+ existsNode,
+ indexPattern,
+ {},
+ { nested: { path: 'nestedField' } }
+ );
+ expect(_.isEqual(expected, result)).to.be(true);
+ });
});
});
});
diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js
index 2f8b784d6f6e8..7afa0fcce1bfe 100644
--- a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js
+++ b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js
@@ -102,6 +102,19 @@ describe('kuery functions', function () {
expect(geoBoundingBox.toElasticsearchQuery)
.withArgs(node, indexPattern).to.throwException(/Geo bounding box query does not support scripted fields/);
});
+
+ it('should use a provided nested context to create a full field name', function () {
+ const node = nodeTypes.function.buildNode('geoBoundingBox', 'geo', params);
+ const result = geoBoundingBox.toElasticsearchQuery(
+ node,
+ indexPattern,
+ {},
+ { nested: { path: 'nestedField' } }
+ );
+ expect(result).to.have.property('geo_bounding_box');
+ expect(result.geo_bounding_box).to.have.property('nestedField.geo');
+ });
+
});
});
});
diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js
index 1c6a2e0e47fde..c1f2fae0bb3e1 100644
--- a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js
+++ b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js
@@ -114,6 +114,18 @@ describe('kuery functions', function () {
expect(geoPolygon.toElasticsearchQuery)
.withArgs(node, indexPattern).to.throwException(/Geo polygon query does not support scripted fields/);
});
+
+ it('should use a provided nested context to create a full field name', function () {
+ const node = nodeTypes.function.buildNode('geoPolygon', 'geo', points);
+ const result = geoPolygon.toElasticsearchQuery(
+ node,
+ indexPattern,
+ {},
+ { nested: { path: 'nestedField' } }
+ );
+ expect(result).to.have.property('geo_polygon');
+ expect(result.geo_polygon).to.have.property('nestedField.geo');
+ });
});
});
});
diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/is.js b/packages/kbn-es-query/src/kuery/functions/__tests__/is.js
index 18652c9faccb8..b2f3d7ec16a65 100644
--- a/packages/kbn-es-query/src/kuery/functions/__tests__/is.js
+++ b/packages/kbn-es-query/src/kuery/functions/__tests__/is.js
@@ -245,6 +245,66 @@ describe('kuery functions', function () {
expect(result).to.eql(expected);
});
+ it('should use a provided nested context to create a full field name', function () {
+ const expected = {
+ bool: {
+ should: [
+ { match: { 'nestedField.extension': 'jpg' } },
+ ],
+ minimum_should_match: 1
+ }
+ };
+
+ const node = nodeTypes.function.buildNode('is', 'extension', 'jpg');
+ const result = is.toElasticsearchQuery(
+ node,
+ indexPattern,
+ {},
+ { nested: { path: 'nestedField' } }
+ );
+ expect(result).to.eql(expected);
+ });
+
+ it('should support wildcard field names', function () {
+ const expected = {
+ bool: {
+ should: [
+ { match: { extension: 'jpg' } },
+ ],
+ minimum_should_match: 1
+ }
+ };
+
+ const node = nodeTypes.function.buildNode('is', 'ext*', 'jpg');
+ const result = is.toElasticsearchQuery(node, indexPattern);
+ expect(result).to.eql(expected);
+ });
+
+ it('should automatically add a nested query when a wildcard field name covers a nested field', () => {
+ const expected = {
+ bool: {
+ should: [
+ {
+ nested: {
+ path: 'nestedField.nestedChild',
+ query: {
+ match: {
+ 'nestedField.nestedChild.doublyNestedChild': 'foo'
+ }
+ },
+ score_mode: 'none'
+ }
+ }
+ ],
+ minimum_should_match: 1
+ }
+ };
+
+
+ const node = nodeTypes.function.buildNode('is', '*doublyNested*', 'foo');
+ const result = is.toElasticsearchQuery(node, indexPattern);
+ expect(result).to.eql(expected);
+ });
});
});
});
diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/nested.js b/packages/kbn-es-query/src/kuery/functions/__tests__/nested.js
new file mode 100644
index 0000000000000..5ba73e485ddf1
--- /dev/null
+++ b/packages/kbn-es-query/src/kuery/functions/__tests__/nested.js
@@ -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 expect from '@kbn/expect';
+import * as nested from '../nested';
+import { nodeTypes } from '../../node_types';
+import * as ast from '../../ast';
+import indexPatternResponse from '../../../__fixtures__/index_pattern_response.json';
+
+let indexPattern;
+
+const childNode = nodeTypes.function.buildNode('is', 'child', 'foo');
+
+describe('kuery functions', function () {
+ describe('nested', function () {
+
+ beforeEach(() => {
+ indexPattern = indexPatternResponse;
+ });
+
+ describe('buildNodeParams', function () {
+
+ it('arguments should contain the unmodified child nodes', function () {
+ const result = nested.buildNodeParams('nestedField', childNode);
+ const { arguments: [ resultPath, resultChildNode ] } = result;
+ expect(ast.toElasticsearchQuery(resultPath)).to.be('nestedField');
+ expect(resultChildNode).to.be(childNode);
+ });
+ });
+
+ describe('toElasticsearchQuery', function () {
+
+ it('should wrap subqueries in an ES nested query', function () {
+ const node = nodeTypes.function.buildNode('nested', 'nestedField', childNode);
+ const result = nested.toElasticsearchQuery(node, indexPattern);
+ expect(result).to.only.have.keys('nested');
+ expect(result.nested.path).to.be('nestedField');
+ expect(result.nested.score_mode).to.be('none');
+ });
+
+ it('should pass the nested path to subqueries so the full field name can be used', function () {
+ const node = nodeTypes.function.buildNode('nested', 'nestedField', childNode);
+ const result = nested.toElasticsearchQuery(node, indexPattern);
+ const expectedSubQuery = ast.toElasticsearchQuery(
+ nodeTypes.function.buildNode('is', 'nestedField.child', 'foo')
+ );
+ expect(result.nested.query).to.eql(expectedSubQuery);
+ });
+
+ });
+ });
+});
diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/range.js b/packages/kbn-es-query/src/kuery/functions/__tests__/range.js
index 4f290206c8bfb..2361e8bb66769 100644
--- a/packages/kbn-es-query/src/kuery/functions/__tests__/range.js
+++ b/packages/kbn-es-query/src/kuery/functions/__tests__/range.js
@@ -181,6 +181,60 @@ describe('kuery functions', function () {
expect(result).to.eql(expected);
});
+ it('should use a provided nested context to create a full field name', function () {
+ const expected = {
+ bool: {
+ should: [
+ {
+ range: {
+ 'nestedField.bytes': {
+ gt: 1000,
+ lt: 8000
+ }
+ }
+ }
+ ],
+ minimum_should_match: 1
+ }
+ };
+
+ const node = nodeTypes.function.buildNode('range', 'bytes', { gt: 1000, lt: 8000 });
+ const result = range.toElasticsearchQuery(
+ node,
+ indexPattern,
+ {},
+ { nested: { path: 'nestedField' } }
+ );
+ expect(result).to.eql(expected);
+ });
+
+ it('should automatically add a nested query when a wildcard field name covers a nested field', function () {
+ const expected = {
+ bool: {
+ should: [
+ {
+ nested: {
+ path: 'nestedField.nestedChild',
+ query: {
+ range: {
+ 'nestedField.nestedChild.doublyNestedChild': {
+ gt: 1000,
+ lt: 8000
+ }
+ }
+ },
+ score_mode: 'none'
+ }
+ }
+ ],
+ minimum_should_match: 1
+ }
+ };
+
+ const node = nodeTypes.function.buildNode('range', '*doublyNested*', { gt: 1000, lt: 8000 });
+ const result = range.toElasticsearchQuery(node, indexPattern);
+ expect(result).to.eql(expected);
+ });
});
});
});
diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/utils/get_full_field_name_node.js b/packages/kbn-es-query/src/kuery/functions/__tests__/utils/get_full_field_name_node.js
new file mode 100644
index 0000000000000..dae15979a161c
--- /dev/null
+++ b/packages/kbn-es-query/src/kuery/functions/__tests__/utils/get_full_field_name_node.js
@@ -0,0 +1,88 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import expect from '@kbn/expect';
+import { nodeTypes } from '../../../node_types';
+import indexPatternResponse from '../../../../__fixtures__/index_pattern_response.json';
+import { getFullFieldNameNode } from '../../utils/get_full_field_name_node';
+
+let indexPattern;
+
+describe('getFullFieldNameNode', function () {
+
+ beforeEach(() => {
+ indexPattern = indexPatternResponse;
+ });
+
+ it('should return unchanged name node if no nested path is passed in', () => {
+ const nameNode = nodeTypes.literal.buildNode('notNested');
+ const result = getFullFieldNameNode(nameNode, indexPattern);
+ expect(result).to.eql(nameNode);
+ });
+
+ it('should add the nested path if it is valid according to the index pattern', () => {
+ const nameNode = nodeTypes.literal.buildNode('child');
+ const result = getFullFieldNameNode(nameNode, indexPattern, 'nestedField');
+ expect(result).to.eql(nodeTypes.literal.buildNode('nestedField.child'));
+ });
+
+ it('should throw an error if a path is provided for a non-nested field', () => {
+ const nameNode = nodeTypes.literal.buildNode('os');
+ expect(getFullFieldNameNode)
+ .withArgs(nameNode, indexPattern, 'machine')
+ .to
+ .throwException(/machine.os is not a nested field but is in nested group "machine" in the KQL expression/);
+ });
+
+ it('should throw an error if a nested field is not passed with a path', () => {
+ const nameNode = nodeTypes.literal.buildNode('nestedField.child');
+ expect(getFullFieldNameNode)
+ .withArgs(nameNode, indexPattern)
+ .to
+ .throwException(/nestedField.child is a nested field, but is not in a nested group in the KQL expression./);
+ });
+
+ it('should throw an error if a nested field is passed with the wrong path', () => {
+ const nameNode = nodeTypes.literal.buildNode('nestedChild.doublyNestedChild');
+ expect(getFullFieldNameNode)
+ .withArgs(nameNode, indexPattern, 'nestedField')
+ .to
+ // eslint-disable-next-line max-len
+ .throwException(/Nested field nestedField.nestedChild.doublyNestedChild is being queried with the incorrect nested path. The correct path is nestedField.nestedChild/);
+ });
+
+ it('should skip error checking for wildcard names', () => {
+ const nameNode = nodeTypes.wildcard.buildNode('nested*');
+ const result = getFullFieldNameNode(nameNode, indexPattern);
+ expect(result).to.eql(nameNode);
+ });
+
+ it('should skip error checking if no index pattern is passed in', () => {
+ const nameNode = nodeTypes.literal.buildNode('os');
+ expect(getFullFieldNameNode)
+ .withArgs(nameNode, null, 'machine')
+ .to
+ .not
+ .throwException();
+
+ const result = getFullFieldNameNode(nameNode, null, 'machine');
+ expect(result).to.eql(nodeTypes.literal.buildNode('machine.os'));
+ });
+
+});
diff --git a/packages/kbn-es-query/src/kuery/functions/and.js b/packages/kbn-es-query/src/kuery/functions/and.js
index 68e125ea4de59..2650e83814b66 100644
--- a/packages/kbn-es-query/src/kuery/functions/and.js
+++ b/packages/kbn-es-query/src/kuery/functions/and.js
@@ -25,13 +25,13 @@ export function buildNodeParams(children) {
};
}
-export function toElasticsearchQuery(node, indexPattern, config) {
+export function toElasticsearchQuery(node, indexPattern, config, context) {
const children = node.arguments || [];
return {
bool: {
filter: children.map((child) => {
- return ast.toElasticsearchQuery(child, indexPattern, config);
+ return ast.toElasticsearchQuery(child, indexPattern, config, context);
})
}
};
diff --git a/packages/kbn-es-query/src/kuery/functions/exists.js b/packages/kbn-es-query/src/kuery/functions/exists.js
index 64810fc2ba796..29940c8c2a425 100644
--- a/packages/kbn-es-query/src/kuery/functions/exists.js
+++ b/packages/kbn-es-query/src/kuery/functions/exists.js
@@ -26,9 +26,10 @@ export function buildNodeParams(fieldName) {
};
}
-export function toElasticsearchQuery(node, indexPattern) {
+export function toElasticsearchQuery(node, indexPattern = null, config, context = {}) {
const { arguments: [ fieldNameArg ] } = node;
- const fieldName = literal.toElasticsearchQuery(fieldNameArg);
+ const fullFieldNameArg = { ...fieldNameArg, value: context.nested ? `${context.nested.path}.${fieldNameArg.value}` : fieldNameArg.value };
+ const fieldName = literal.toElasticsearchQuery(fullFieldNameArg);
const field = get(indexPattern, 'fields', []).find(field => field.name === fieldName);
if (field && field.scripted) {
diff --git a/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.js b/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.js
index eeab146f6f698..fd7e68e52e054 100644
--- a/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.js
+++ b/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.js
@@ -34,9 +34,10 @@ export function buildNodeParams(fieldName, params) {
};
}
-export function toElasticsearchQuery(node, indexPattern) {
+export function toElasticsearchQuery(node, indexPattern, config, context = {}) {
const [ fieldNameArg, ...args ] = node.arguments;
- const fieldName = nodeTypes.literal.toElasticsearchQuery(fieldNameArg);
+ const fullFieldNameArg = { ...fieldNameArg, value: context.nested ? `${context.nested.path}.${fieldNameArg.value}` : fieldNameArg.value };
+ const fieldName = nodeTypes.literal.toElasticsearchQuery(fullFieldNameArg);
const field = _.get(indexPattern, 'fields', []).find(field => field.name === fieldName);
const queryParams = args.reduce((acc, arg) => {
const snakeArgName = _.snakeCase(arg.name);
@@ -57,4 +58,3 @@ export function toElasticsearchQuery(node, indexPattern) {
},
};
}
-
diff --git a/packages/kbn-es-query/src/kuery/functions/geo_polygon.js b/packages/kbn-es-query/src/kuery/functions/geo_polygon.js
index 2e9f10071ea32..7756ae731ce6c 100644
--- a/packages/kbn-es-query/src/kuery/functions/geo_polygon.js
+++ b/packages/kbn-es-query/src/kuery/functions/geo_polygon.js
@@ -33,12 +33,13 @@ export function buildNodeParams(fieldName, points) {
};
}
-export function toElasticsearchQuery(node, indexPattern) {
+export function toElasticsearchQuery(node, indexPattern, config = {}, context = {}) {
const [ fieldNameArg, ...points ] = node.arguments;
- const fieldName = nodeTypes.literal.toElasticsearchQuery(fieldNameArg);
+ const fullFieldNameArg = { ...fieldNameArg, value: context.nested ? `${context.nested.path}.${fieldNameArg.value}` : fieldNameArg.value };
+ const fieldName = nodeTypes.literal.toElasticsearchQuery(fullFieldNameArg);
const field = get(indexPattern, 'fields', []).find(field => field.name === fieldName);
const queryParams = {
- points: points.map(ast.toElasticsearchQuery)
+ points: points.map((point) => { return ast.toElasticsearchQuery(point, indexPattern, config, context); })
};
if (field && field.scripted) {
diff --git a/packages/kbn-es-query/src/kuery/functions/index.js b/packages/kbn-es-query/src/kuery/functions/index.js
index 39b41f5301857..08b30f022f431 100644
--- a/packages/kbn-es-query/src/kuery/functions/index.js
+++ b/packages/kbn-es-query/src/kuery/functions/index.js
@@ -25,6 +25,7 @@ import * as range from './range';
import * as exists from './exists';
import * as geoBoundingBox from './geo_bounding_box';
import * as geoPolygon from './geo_polygon';
+import * as nested from './nested';
export const functions = {
is,
@@ -35,4 +36,5 @@ export const functions = {
exists,
geoBoundingBox,
geoPolygon,
+ nested,
};
diff --git a/packages/kbn-es-query/src/kuery/functions/is.js b/packages/kbn-es-query/src/kuery/functions/is.js
index 690f98b08ba82..63ade9e8793a7 100644
--- a/packages/kbn-es-query/src/kuery/functions/is.js
+++ b/packages/kbn-es-query/src/kuery/functions/is.js
@@ -21,9 +21,10 @@ import _ from 'lodash';
import * as ast from '../ast';
import * as literal from '../node_types/literal';
import * as wildcard from '../node_types/wildcard';
-import { getPhraseScript } from '../../filters';
+import { getPhraseScript } from '../../utils/filters';
import { getFields } from './utils/get_fields';
import { getTimeZoneFromSettings } from '../../utils/get_time_zone_from_settings';
+import { getFullFieldNameNode } from './utils/get_full_field_name_node';
export function buildNodeParams(fieldName, value, isPhrase = false) {
if (_.isUndefined(fieldName)) {
@@ -40,12 +41,13 @@ export function buildNodeParams(fieldName, value, isPhrase = false) {
};
}
-export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
+export function toElasticsearchQuery(node, indexPattern = null, config = {}, context = {}) {
const { arguments: [fieldNameArg, valueArg, isPhraseArg] } = node;
- const fieldName = ast.toElasticsearchQuery(fieldNameArg);
+ const fullFieldNameArg = getFullFieldNameNode(fieldNameArg, indexPattern, context.nested ? context.nested.path : undefined);
+ const fieldName = ast.toElasticsearchQuery(fullFieldNameArg);
const value = !_.isUndefined(valueArg) ? ast.toElasticsearchQuery(valueArg) : valueArg;
const type = isPhraseArg.value ? 'phrase' : 'best_fields';
- if (fieldNameArg.value === null) {
+ if (fullFieldNameArg.value === null) {
if (valueArg.type === 'wildcard') {
return {
query_string: {
@@ -63,7 +65,7 @@ export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
};
}
- const fields = indexPattern ? getFields(fieldNameArg, indexPattern) : [];
+ const fields = indexPattern ? getFields(fullFieldNameArg, indexPattern) : [];
// If no fields are found in the index pattern we send through the given field name as-is. We do this to preserve
// the behaviour of lucene on dashboards where there are panels based on different index patterns that have different
// fields. If a user queries on a field that exists in one pattern but not the other, the index pattern without the
@@ -71,14 +73,14 @@ export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
// keep things familiar for now.
if (fields && fields.length === 0) {
fields.push({
- name: ast.toElasticsearchQuery(fieldNameArg),
+ name: ast.toElasticsearchQuery(fullFieldNameArg),
scripted: false,
});
}
const isExistsQuery = valueArg.type === 'wildcard' && value === '*';
const isAllFieldsQuery =
- (fieldNameArg.type === 'wildcard' && fieldName === '*')
+ (fullFieldNameArg.type === 'wildcard' && fieldName === '*')
|| (fields && indexPattern && fields.length === indexPattern.fields.length);
const isMatchAllQuery = isExistsQuery && isAllFieldsQuery;
@@ -87,6 +89,27 @@ export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
}
const queries = fields.reduce((accumulator, field) => {
+ const wrapWithNestedQuery = (query) => {
+ // Wildcards can easily include nested and non-nested fields. There isn't a good way to let
+ // users handle this themselves so we automatically add nested queries in this scenario.
+ if (
+ !(fullFieldNameArg.type === 'wildcard')
+ || !_.get(field, 'subType.nested')
+ || context.nested
+ ) {
+ return query;
+ }
+ else {
+ return {
+ nested: {
+ path: field.subType.nested.path,
+ query,
+ score_mode: 'none'
+ }
+ };
+ }
+ };
+
if (field.scripted) {
// Exists queries don't make sense for scripted fields
if (!isExistsQuery) {
@@ -98,19 +121,19 @@ export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
}
}
else if (isExistsQuery) {
- return [...accumulator, {
+ return [...accumulator, wrapWithNestedQuery({
exists: {
field: field.name
}
- }];
+ })];
}
else if (valueArg.type === 'wildcard') {
- return [...accumulator, {
+ return [...accumulator, wrapWithNestedQuery({
query_string: {
fields: [field.name],
query: wildcard.toQueryStringQuery(valueArg),
}
- }];
+ })];
}
/*
If we detect that it's a date field and the user wants an exact date, we need to convert the query to both >= and <= the value provided to force a range query. This is because match and match_phrase queries do not accept a timezone parameter.
@@ -118,7 +141,7 @@ export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
*/
else if (field.type === 'date') {
const timeZoneParam = config.dateFormatTZ ? { time_zone: getTimeZoneFromSettings(config.dateFormatTZ) } : {};
- return [...accumulator, {
+ return [...accumulator, wrapWithNestedQuery({
range: {
[field.name]: {
gte: value,
@@ -126,15 +149,15 @@ export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
...timeZoneParam,
},
}
- }];
+ })];
}
else {
const queryType = type === 'phrase' ? 'match_phrase' : 'match';
- return [...accumulator, {
+ return [...accumulator, wrapWithNestedQuery({
[queryType]: {
[field.name]: value
}
- }];
+ })];
}
}, []);
@@ -146,4 +169,3 @@ export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
};
}
-
diff --git a/packages/kbn-es-query/src/kuery/functions/nested.js b/packages/kbn-es-query/src/kuery/functions/nested.js
new file mode 100644
index 0000000000000..6237189e16311
--- /dev/null
+++ b/packages/kbn-es-query/src/kuery/functions/nested.js
@@ -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 * as ast from '../ast';
+import * as literal from '../node_types/literal';
+
+export function buildNodeParams(path, child) {
+ const pathNode = typeof path === 'string' ? ast.fromLiteralExpression(path) : literal.buildNode(path);
+ return {
+ arguments: [pathNode, child],
+ };
+}
+
+export function toElasticsearchQuery(node, indexPattern, config, context = {}) {
+ if (!indexPattern) {
+ throw new Error('Cannot use nested queries without an index pattern');
+ }
+
+ const [path, child] = node.arguments;
+ const stringPath = ast.toElasticsearchQuery(path);
+ const fullPath = context.nested && context.nested.path ? `${context.nested.path}.${stringPath}` : stringPath;
+
+ return {
+ nested: {
+ path: fullPath,
+ query: ast.toElasticsearchQuery(child, indexPattern, config, { ...context, nested: { path: fullPath } }),
+ score_mode: 'none',
+ },
+ };
+}
diff --git a/packages/kbn-es-query/src/kuery/functions/not.js b/packages/kbn-es-query/src/kuery/functions/not.js
index d3ab14df16bcb..8a4b8c6060109 100644
--- a/packages/kbn-es-query/src/kuery/functions/not.js
+++ b/packages/kbn-es-query/src/kuery/functions/not.js
@@ -25,13 +25,12 @@ export function buildNodeParams(child) {
};
}
-export function toElasticsearchQuery(node, indexPattern, config) {
+export function toElasticsearchQuery(node, indexPattern, config, context) {
const [ argument ] = node.arguments;
return {
bool: {
- must_not: ast.toElasticsearchQuery(argument, indexPattern, config)
+ must_not: ast.toElasticsearchQuery(argument, indexPattern, config, context)
}
};
}
-
diff --git a/packages/kbn-es-query/src/kuery/functions/or.js b/packages/kbn-es-query/src/kuery/functions/or.js
index 918d46a6691de..9b27ac9151801 100644
--- a/packages/kbn-es-query/src/kuery/functions/or.js
+++ b/packages/kbn-es-query/src/kuery/functions/or.js
@@ -25,13 +25,13 @@ export function buildNodeParams(children) {
};
}
-export function toElasticsearchQuery(node, indexPattern, config) {
+export function toElasticsearchQuery(node, indexPattern, config, context) {
const children = node.arguments || [];
return {
bool: {
should: children.map((child) => {
- return ast.toElasticsearchQuery(child, indexPattern, config);
+ return ast.toElasticsearchQuery(child, indexPattern, config, context);
}),
minimum_should_match: 1,
},
diff --git a/packages/kbn-es-query/src/kuery/functions/range.js b/packages/kbn-es-query/src/kuery/functions/range.js
index df77baf4b0208..f7719998ad524 100644
--- a/packages/kbn-es-query/src/kuery/functions/range.js
+++ b/packages/kbn-es-query/src/kuery/functions/range.js
@@ -20,9 +20,10 @@
import _ from 'lodash';
import { nodeTypes } from '../node_types';
import * as ast from '../ast';
-import { getRangeScript } from '../../filters';
+import { getRangeScript } from '../../utils/filters';
import { getFields } from './utils/get_fields';
import { getTimeZoneFromSettings } from '../../utils/get_time_zone_from_settings';
+import { getFullFieldNameNode } from './utils/get_full_field_name_node';
export function buildNodeParams(fieldName, params) {
params = _.pick(params, 'gt', 'lt', 'gte', 'lte', 'format');
@@ -36,9 +37,10 @@ export function buildNodeParams(fieldName, params) {
};
}
-export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
+export function toElasticsearchQuery(node, indexPattern = null, config = {}, context = {}) {
const [ fieldNameArg, ...args ] = node.arguments;
- const fields = indexPattern ? getFields(fieldNameArg, indexPattern) : [];
+ const fullFieldNameArg = getFullFieldNameNode(fieldNameArg, indexPattern, context.nested ? context.nested.path : undefined);
+ const fields = indexPattern ? getFields(fullFieldNameArg, indexPattern) : [];
const namedArgs = extractArguments(args);
const queryParams = _.mapValues(namedArgs, ast.toElasticsearchQuery);
@@ -49,13 +51,34 @@ export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
// keep things familiar for now.
if (fields && fields.length === 0) {
fields.push({
- name: ast.toElasticsearchQuery(fieldNameArg),
+ name: ast.toElasticsearchQuery(fullFieldNameArg),
scripted: false,
});
}
const queries = fields.map((field) => {
+ const wrapWithNestedQuery = (query) => {
+ // Wildcards can easily include nested and non-nested fields. There isn't a good way to let
+ // users handle this themselves so we automatically add nested queries in this scenario.
+ if (
+ !fullFieldNameArg.type === 'wildcard'
+ || !_.get(field, 'subType.nested')
+ || context.nested
+ ) {
+ return query;
+ }
+ else {
+ return {
+ nested: {
+ path: field.subType.nested.path,
+ query,
+ score_mode: 'none'
+ }
+ };
+ }
+ };
+
if (field.scripted) {
return {
script: getRangeScript(field, queryParams),
@@ -63,20 +86,20 @@ export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
}
else if (field.type === 'date') {
const timeZoneParam = config.dateFormatTZ ? { time_zone: getTimeZoneFromSettings(config.dateFormatTZ) } : {};
- return {
+ return wrapWithNestedQuery({
range: {
[field.name]: {
...queryParams,
...timeZoneParam,
}
}
- };
+ });
}
- return {
+ return wrapWithNestedQuery({
range: {
[field.name]: queryParams
}
- };
+ });
});
return {
diff --git a/packages/kbn-es-query/src/kuery/functions/utils/get_full_field_name_node.js b/packages/kbn-es-query/src/kuery/functions/utils/get_full_field_name_node.js
new file mode 100644
index 0000000000000..07540344b7955
--- /dev/null
+++ b/packages/kbn-es-query/src/kuery/functions/utils/get_full_field_name_node.js
@@ -0,0 +1,63 @@
+/*
+ * 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 { getFields } from './get_fields';
+
+export function getFullFieldNameNode(rootNameNode, indexPattern, nestedPath) {
+ const fullFieldNameNode = {
+ ...rootNameNode,
+ value: nestedPath ? `${nestedPath}.${rootNameNode.value}` : rootNameNode.value
+ };
+
+ // Wildcards can easily include nested and non-nested fields. There isn't a good way to let
+ // users handle this themselves so we automatically add nested queries in this scenario and skip the
+ // error checking below.
+ if (!indexPattern || (fullFieldNameNode.type === 'wildcard' && !nestedPath)) {
+ return fullFieldNameNode;
+ }
+ const fields = getFields(fullFieldNameNode, indexPattern);
+
+ const errors = fields.reduce((acc, field) => {
+ const nestedPathFromField = field.subType && field.subType.nested ? field.subType.nested.path : undefined;
+
+ if (nestedPath && !nestedPathFromField) {
+ return [...acc, `${field.name} is not a nested field but is in nested group "${nestedPath}" in the KQL expression.`];
+ }
+
+ if (nestedPathFromField && !nestedPath) {
+ return [...acc, `${field.name} is a nested field, but is not in a nested group in the KQL expression.`];
+ }
+
+ if (nestedPathFromField !== nestedPath) {
+ return [
+ ...acc,
+ `Nested field ${field.name} is being queried with the incorrect nested path. The correct path is ${field.subType.nested.path}.`
+ ];
+ }
+
+ return acc;
+ }, []);
+
+ if (errors.length > 0) {
+ throw new Error(errors.join('\n'));
+ }
+
+ return fullFieldNameNode;
+}
diff --git a/packages/kbn-es-query/src/kuery/node_types/function.js b/packages/kbn-es-query/src/kuery/node_types/function.js
index 6b10bb1f704c8..d54b7de6cd8ea 100644
--- a/packages/kbn-es-query/src/kuery/node_types/function.js
+++ b/packages/kbn-es-query/src/kuery/node_types/function.js
@@ -47,8 +47,7 @@ export function buildNodeWithArgumentNodes(functionName, argumentNodes) {
};
}
-export function toElasticsearchQuery(node, indexPattern, config = {}) {
+export function toElasticsearchQuery(node, indexPattern, config = {}, context = {}) {
const kueryFunction = functions[node.function];
- return kueryFunction.toElasticsearchQuery(node, indexPattern, config);
+ return kueryFunction.toElasticsearchQuery(node, indexPattern, config, context);
}
-
diff --git a/packages/kbn-es-query/src/kuery/node_types/index.d.ts b/packages/kbn-es-query/src/kuery/node_types/index.d.ts
index 0d1f2c28e39f0..daf8032f9fe0e 100644
--- a/packages/kbn-es-query/src/kuery/node_types/index.d.ts
+++ b/packages/kbn-es-query/src/kuery/node_types/index.d.ts
@@ -31,7 +31,8 @@ type FunctionName =
| 'range'
| 'exists'
| 'geoBoundingBox'
- | 'geoPolygon';
+ | 'geoPolygon'
+ | 'nested';
interface FunctionTypeBuildNode {
type: 'function';
diff --git a/packages/kbn-es-query/src/utils/filters.js b/packages/kbn-es-query/src/utils/filters.js
new file mode 100644
index 0000000000000..6e4f5c342688c
--- /dev/null
+++ b/packages/kbn-es-query/src/utils/filters.js
@@ -0,0 +1,133 @@
+/*
+ * 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 { pick, get, reduce, map } from 'lodash';
+
+/** @deprecated
+ * @see src/plugins/data/public/es_query/filters/phrase_filter.ts
+ * Code was already moved into src/plugins/data/public.
+ * This method will be removed after moving 'es_query' into new platform
+ * */
+export const getConvertedValueForField = (field, value) => {
+ if (typeof value !== 'boolean' && field.type === 'boolean') {
+ if ([1, 'true'].includes(value)) {
+ return true;
+ } else if ([0, 'false'].includes(value)) {
+ return false;
+ } else {
+ throw new Error(`${value} is not a valid boolean value for boolean field ${field.name}`);
+ }
+ }
+ return value;
+};
+
+/** @deprecated
+ * @see src/plugins/data/public/es_query/filters/phrase_filter.ts
+ * Code was already moved into src/plugins/data/public.
+ * This method will be removed after moving 'es_query' into new platform
+ * */
+export const buildInlineScriptForPhraseFilter = (scriptedField) => {
+ // We must wrap painless scripts in a lambda in case they're more than a simple expression
+ if (scriptedField.lang === 'painless') {
+ return (
+ `boolean compare(Supplier s, def v) {return s.get() == v;}` +
+ `compare(() -> { ${scriptedField.script} }, params.value);`
+ );
+ } else {
+ return `(${scriptedField.script}) == value`;
+ }
+};
+
+/** @deprecated
+ * @see src/plugins/data/public/es_query/filters/phrase_filter.ts
+ * Code was already moved into src/plugins/data/public.
+ * This method will be removed after moving 'es_query' into new platform
+ * */
+export function getPhraseScript(field, value) {
+ const convertedValue = getConvertedValueForField(field, value);
+ const script = buildInlineScriptForPhraseFilter(field);
+
+ return {
+ script: {
+ source: script,
+ lang: field.lang,
+ params: {
+ value: convertedValue,
+ },
+ },
+ };
+}
+
+/** @deprecated
+ * @see src/plugins/data/public/es_query/filters/range_filter.ts
+ * Code was already moved into src/plugins/data/public.
+ * This method will be removed after moving 'kuery' into new platform
+ * */
+export function getRangeScript(field, params) {
+ const operators = {
+ gt: '>',
+ gte: '>=',
+ lte: '<=',
+ lt: '<',
+ };
+ const comparators = {
+ gt: 'boolean gt(Supplier s, def v) {return s.get() > v}',
+ gte: 'boolean gte(Supplier s, def v) {return s.get() >= v}',
+ lte: 'boolean lte(Supplier s, def v) {return s.get() <= v}',
+ lt: 'boolean lt(Supplier s, def v) {return s.get() < v}',
+ };
+
+ const dateComparators = {
+ gt: 'boolean gt(Supplier s, def v) {return s.get().toInstant().isAfter(Instant.parse(v))}',
+ gte: 'boolean gte(Supplier s, def v) {return !s.get().toInstant().isBefore(Instant.parse(v))}',
+ lte: 'boolean lte(Supplier s, def v) {return !s.get().toInstant().isAfter(Instant.parse(v))}',
+ lt: 'boolean lt(Supplier s, def v) {return s.get().toInstant().isBefore(Instant.parse(v))}',
+ };
+
+ const knownParams = pick(params, (val, key) => {
+ return key in operators;
+ });
+ let script = map(knownParams, (val, key) => {
+ return '(' + field.script + ')' + get(operators, key) + key;
+ }).join(' && ');
+
+ // We must wrap painless scripts in a lambda in case they're more than a simple expression
+ if (field.lang === 'painless') {
+ const comp = field.type === 'date' ? dateComparators : comparators;
+ const currentComparators = reduce(
+ knownParams,
+ (acc, val, key) => acc.concat(get(comp, key)),
+ []
+ ).join(' ');
+
+ const comparisons = map(knownParams, (val, key) => {
+ return `${key}(() -> { ${field.script} }, params.${key})`;
+ }).join(' && ');
+
+ script = `${currentComparators}${comparisons}`;
+ }
+
+ return {
+ script: {
+ source: script,
+ params: knownParams,
+ lang: field.lang,
+ },
+ };
+}
diff --git a/packages/kbn-eslint-plugin-eslint/rules/__tests__/files/no_restricted_paths/server/index_patterns/index.js b/packages/kbn-eslint-plugin-eslint/rules/__tests__/files/no_restricted_paths/server/index_patterns/index.js
new file mode 100644
index 0000000000000..d15de7d98a9e0
--- /dev/null
+++ b/packages/kbn-eslint-plugin-eslint/rules/__tests__/files/no_restricted_paths/server/index_patterns/index.js
@@ -0,0 +1 @@
+/* eslint-disable */
diff --git a/packages/kbn-eslint-plugin-eslint/rules/__tests__/no_restricted_paths.js b/packages/kbn-eslint-plugin-eslint/rules/__tests__/no_restricted_paths.js
index f393a867d95e0..577be820ccc7b 100644
--- a/packages/kbn-eslint-plugin-eslint/rules/__tests__/no_restricted_paths.js
+++ b/packages/kbn-eslint-plugin-eslint/rules/__tests__/no_restricted_paths.js
@@ -172,6 +172,27 @@ ruleTester.run('@kbn/eslint/no-restricted-paths', rule, {
},
],
},
+
+ {
+ // Check if dirs that start with 'index' work correctly.
+ code: 'import { X } from "./index_patterns"',
+ filename: path.join(__dirname, './files/no_restricted_paths/server/b.js'),
+ options: [
+ {
+ basePath: __dirname,
+ zones: [
+ {
+ target: ['files/no_restricted_paths/(public|server)/**/*'],
+ from: [
+ 'files/no_restricted_paths/server/**/*',
+ '!files/no_restricted_paths/server/index.{ts,tsx}',
+ ],
+ allowSameFolder: true,
+ },
+ ],
+ },
+ ],
+ },
],
invalid: [
@@ -369,5 +390,34 @@ ruleTester.run('@kbn/eslint/no-restricted-paths', rule, {
},
],
},
+
+ {
+ // Don't use index*.
+ // It won't work with dirs that start with 'index'.
+ code: 'import { X } from "./index_patterns"',
+ filename: path.join(__dirname, './files/no_restricted_paths/server/b.js'),
+ options: [
+ {
+ basePath: __dirname,
+ zones: [
+ {
+ target: ['files/no_restricted_paths/(public|server)/**/*'],
+ from: [
+ 'files/no_restricted_paths/server/**/*',
+ '!files/no_restricted_paths/server/index*',
+ ],
+ allowSameFolder: true,
+ },
+ ],
+ },
+ ],
+ errors: [
+ {
+ message: 'Unexpected path "./index_patterns" imported in restricted zone.',
+ line: 1,
+ column: 19,
+ },
+ ],
+ },
],
});
diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js
index 2a8c22ed29a79..bbe12a93c241f 100644
--- a/packages/kbn-pm/dist/index.js
+++ b/packages/kbn-pm/dist/index.js
@@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; });
-/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(483);
+/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(484);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; });
@@ -152,7 +152,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17);
-/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(474);
+/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(475);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
@@ -33210,7 +33210,7 @@ const WatchCommand = {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "waitUntilWatchIsReady", function() { return waitUntilWatchIsReady; });
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(275);
-/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(374);
+/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(377);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -33285,45 +33285,45 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return _internal_Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"]; });
-/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
+/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(293);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__["ConnectableObservable"]; });
-/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(299);
+/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(298);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GroupedObservable", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__["GroupedObservable"]; });
-/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(291);
+/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(290);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observable", function() { return _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__["observable"]; });
-/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(295);
+/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(294);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subject", function() { return _internal_Subject__WEBPACK_IMPORTED_MODULE_4__["Subject"]; });
-/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(300);
+/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(299);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__["BehaviorSubject"]; });
-/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(301);
+/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(300);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__["ReplaySubject"]; });
-/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(318);
+/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(317);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__["AsyncSubject"]; });
-/* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(319);
+/* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(318);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asapScheduler", function() { return _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__["asap"]; });
-/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(323);
+/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(322);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asyncScheduler", function() { return _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__["async"]; });
-/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(302);
+/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(301);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queue"]; });
-/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(324);
+/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(323);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrame"]; });
-/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(327);
+/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(326);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualTimeScheduler"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualAction"]; });
-/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(308);
+/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(307);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Scheduler", function() { return _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__["Scheduler"]; });
/* harmony import */ var _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(284);
@@ -33332,58 +33332,60 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(278);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__["Subscriber"]; });
-/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(310);
+/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(309);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return _internal_Notification__WEBPACK_IMPORTED_MODULE_16__["Notification"]; });
-/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(292);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "NotificationKind", function() { return _internal_Notification__WEBPACK_IMPORTED_MODULE_16__["NotificationKind"]; });
+
+/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(291);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__["pipe"]; });
-/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(293);
+/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(292);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "noop", function() { return _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__["noop"]; });
-/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(328);
+/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(327);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "identity", function() { return _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__["identity"]; });
-/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(329);
+/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(328);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__["isObservable"]; });
-/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(330);
+/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(329);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ArgumentOutOfRangeError", function() { return _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__["ArgumentOutOfRangeError"]; });
-/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(331);
+/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(330);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EmptyError", function() { return _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__["EmptyError"]; });
-/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(296);
+/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(295);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ObjectUnsubscribedError", function() { return _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__["ObjectUnsubscribedError"]; });
-/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(289);
+/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(287);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__["UnsubscriptionError"]; });
-/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(332);
+/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(331);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__["TimeoutError"]; });
-/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(333);
+/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(332);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__["bindCallback"]; });
-/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(335);
+/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(334);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__["bindNodeCallback"]; });
-/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(336);
+/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(335);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__["combineLatest"]; });
-/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(347);
+/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(346);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__["concat"]; });
/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(357);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__["defer"]; });
-/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(311);
+/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(310);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["empty"]; });
/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(358);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__["forkJoin"]; });
-/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(348);
+/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(350);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "from", function() { return _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__["from"]; });
/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(359);
@@ -33407,7 +33409,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(366);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "never", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["never"]; });
-/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(312);
+/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(311);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "of", function() { return _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__["of"]; });
/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(367);
@@ -33416,30 +33418,36 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(368);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__["pairs"]; });
-/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(369);
-/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__["race"]; });
+/* harmony import */ var _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(369);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__["partition"]; });
+
+/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(372);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__["race"]; });
+
+/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(373);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "range", function() { return _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__["range"]; });
-/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(370);
-/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "range", function() { return _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__["range"]; });
+/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(316);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_47__["throwError"]; });
-/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(317);
-/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__["throwError"]; });
+/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(374);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__["timer"]; });
-/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(371);
-/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__["timer"]; });
+/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(375);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "using", function() { return _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__["using"]; });
-/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(372);
-/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "using", function() { return _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__["using"]; });
+/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(376);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_observable_zip__WEBPACK_IMPORTED_MODULE_50__["zip"]; });
-/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(373);
-/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__["zip"]; });
+/* harmony import */ var _internal_scheduled_scheduled__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(351);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scheduled", function() { return _internal_scheduled_scheduled__WEBPACK_IMPORTED_MODULE_51__["scheduled"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["EMPTY"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["NEVER"]; });
-/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(282);
-/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "config", function() { return _internal_config__WEBPACK_IMPORTED_MODULE_50__["config"]; });
+/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(282);
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "config", function() { return _internal_config__WEBPACK_IMPORTED_MODULE_52__["config"]; });
/** PURE_IMPORTS_START PURE_IMPORTS_END */
@@ -33492,6 +33500,8 @@ __webpack_require__.r(__webpack_exports__);
+
+
@@ -33505,11 +33515,13 @@ __webpack_require__.r(__webpack_exports__);
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return Observable; });
-/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(277);
-/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(291);
-/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(292);
-/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(282);
-/** PURE_IMPORTS_START _util_toSubscriber,_internal_symbol_observable,_util_pipe,_config PURE_IMPORTS_END */
+/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(277);
+/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(289);
+/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(290);
+/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(291);
+/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(282);
+/** PURE_IMPORTS_START _util_canReportError,_util_toSubscriber,_symbol_observable,_util_pipe,_config PURE_IMPORTS_END */
+
@@ -33529,16 +33541,16 @@ var Observable = /*@__PURE__*/ (function () {
};
Observable.prototype.subscribe = function (observerOrNext, error, complete) {
var operator = this.operator;
- var sink = Object(_util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__["toSubscriber"])(observerOrNext, error, complete);
+ var sink = Object(_util_toSubscriber__WEBPACK_IMPORTED_MODULE_1__["toSubscriber"])(observerOrNext, error, complete);
if (operator) {
- operator.call(sink, this.source);
+ sink.add(operator.call(sink, this.source));
}
else {
- sink.add(this.source || (_config__WEBPACK_IMPORTED_MODULE_3__["config"].useDeprecatedSynchronousErrorHandling && !sink.syncErrorThrowable) ?
+ sink.add(this.source || (_config__WEBPACK_IMPORTED_MODULE_4__["config"].useDeprecatedSynchronousErrorHandling && !sink.syncErrorThrowable) ?
this._subscribe(sink) :
this._trySubscribe(sink));
}
- if (_config__WEBPACK_IMPORTED_MODULE_3__["config"].useDeprecatedSynchronousErrorHandling) {
+ if (_config__WEBPACK_IMPORTED_MODULE_4__["config"].useDeprecatedSynchronousErrorHandling) {
if (sink.syncErrorThrowable) {
sink.syncErrorThrowable = false;
if (sink.syncErrorThrown) {
@@ -33553,11 +33565,16 @@ var Observable = /*@__PURE__*/ (function () {
return this._subscribe(sink);
}
catch (err) {
- if (_config__WEBPACK_IMPORTED_MODULE_3__["config"].useDeprecatedSynchronousErrorHandling) {
+ if (_config__WEBPACK_IMPORTED_MODULE_4__["config"].useDeprecatedSynchronousErrorHandling) {
sink.syncErrorThrown = true;
sink.syncErrorValue = err;
}
- sink.error(err);
+ if (Object(_util_canReportError__WEBPACK_IMPORTED_MODULE_0__["canReportError"])(sink)) {
+ sink.error(err);
+ }
+ else {
+ console.warn(err);
+ }
}
};
Observable.prototype.forEach = function (next, promiseCtor) {
@@ -33582,7 +33599,7 @@ var Observable = /*@__PURE__*/ (function () {
var source = this.source;
return source && source.subscribe(subscriber);
};
- Observable.prototype[_internal_symbol_observable__WEBPACK_IMPORTED_MODULE_1__["observable"]] = function () {
+ Observable.prototype[_symbol_observable__WEBPACK_IMPORTED_MODULE_2__["observable"]] = function () {
return this;
};
Observable.prototype.pipe = function () {
@@ -33593,7 +33610,7 @@ var Observable = /*@__PURE__*/ (function () {
if (operations.length === 0) {
return this;
}
- return Object(_util_pipe__WEBPACK_IMPORTED_MODULE_2__["pipeFromArray"])(operations)(this);
+ return Object(_util_pipe__WEBPACK_IMPORTED_MODULE_3__["pipeFromArray"])(operations)(this);
};
Observable.prototype.toPromise = function (promiseCtor) {
var _this = this;
@@ -33611,7 +33628,7 @@ var Observable = /*@__PURE__*/ (function () {
function getPromiseCtor(promiseCtor) {
if (!promiseCtor) {
- promiseCtor = _config__WEBPACK_IMPORTED_MODULE_3__["config"].Promise || Promise;
+ promiseCtor = _config__WEBPACK_IMPORTED_MODULE_4__["config"].Promise || Promise;
}
if (!promiseCtor) {
throw new Error('no Promise impl found');
@@ -33627,29 +33644,26 @@ function getPromiseCtor(promiseCtor) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toSubscriber", function() { return toSubscriber; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "canReportError", function() { return canReportError; });
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(278);
-/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(290);
-/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(281);
-/** PURE_IMPORTS_START _Subscriber,_symbol_rxSubscriber,_Observer PURE_IMPORTS_END */
-
+/** PURE_IMPORTS_START _Subscriber PURE_IMPORTS_END */
-
-function toSubscriber(nextOrObserver, error, complete) {
- if (nextOrObserver) {
- if (nextOrObserver instanceof _Subscriber__WEBPACK_IMPORTED_MODULE_0__["Subscriber"]) {
- return nextOrObserver;
+function canReportError(observer) {
+ while (observer) {
+ var _a = observer, closed_1 = _a.closed, destination = _a.destination, isStopped = _a.isStopped;
+ if (closed_1 || isStopped) {
+ return false;
}
- if (nextOrObserver[_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__["rxSubscriber"]]) {
- return nextOrObserver[_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__["rxSubscriber"]]();
+ else if (destination && destination instanceof _Subscriber__WEBPACK_IMPORTED_MODULE_0__["Subscriber"]) {
+ observer = destination;
+ }
+ else {
+ observer = null;
}
}
- if (!nextOrObserver && !error && !complete) {
- return new _Subscriber__WEBPACK_IMPORTED_MODULE_0__["Subscriber"](_Observer__WEBPACK_IMPORTED_MODULE_2__["empty"]);
- }
- return new _Subscriber__WEBPACK_IMPORTED_MODULE_0__["Subscriber"](nextOrObserver, error, complete);
+ return true;
}
-//# sourceMappingURL=toSubscriber.js.map
+//# sourceMappingURL=canReportError.js.map
/***/ }),
@@ -33659,11 +33673,12 @@ function toSubscriber(nextOrObserver, error, complete) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return Subscriber; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SafeSubscriber", function() { return SafeSubscriber; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(280);
/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(281);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(284);
-/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(290);
+/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(288);
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(282);
/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(283);
/** PURE_IMPORTS_START tslib,_util_isFunction,_Observer,_Subscription,_internal_symbol_rxSubscriber,_config,_util_hostReportError PURE_IMPORTS_END */
@@ -33692,11 +33707,10 @@ var Subscriber = /*@__PURE__*/ (function (_super) {
break;
}
if (typeof destinationOrNext === 'object') {
- if (isTrustedSubscriber(destinationOrNext)) {
- var trustedSubscriber = destinationOrNext[_internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__["rxSubscriber"]]();
- _this.syncErrorThrowable = trustedSubscriber.syncErrorThrowable;
- _this.destination = trustedSubscriber;
- trustedSubscriber.add(_this);
+ if (destinationOrNext instanceof Subscriber) {
+ _this.syncErrorThrowable = destinationOrNext.syncErrorThrowable;
+ _this.destination = destinationOrNext;
+ destinationOrNext.add(_this);
}
else {
_this.syncErrorThrowable = true;
@@ -33753,14 +33767,12 @@ var Subscriber = /*@__PURE__*/ (function (_super) {
this.unsubscribe();
};
Subscriber.prototype._unsubscribeAndRecycle = function () {
- var _a = this, _parent = _a._parent, _parents = _a._parents;
- this._parent = null;
- this._parents = null;
+ var _parentOrParents = this._parentOrParents;
+ this._parentOrParents = null;
this.unsubscribe();
this.closed = false;
this.isStopped = false;
- this._parent = _parent;
- this._parents = _parents;
+ this._parentOrParents = _parentOrParents;
return this;
};
return Subscriber;
@@ -33900,9 +33912,7 @@ var SafeSubscriber = /*@__PURE__*/ (function (_super) {
};
return SafeSubscriber;
}(Subscriber));
-function isTrustedSubscriber(obj) {
- return obj instanceof Subscriber || ('syncErrorThrowable' in obj && obj[_internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__["rxSubscriber"]]);
-}
+
//# sourceMappingURL=Subscriber.js.map
@@ -34198,7 +34208,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hostReportError", function() { return hostReportError; });
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function hostReportError(err) {
- setTimeout(function () { throw err; });
+ setTimeout(function () { throw err; }, 0);
}
//# sourceMappingURL=hostReportError.js.map
@@ -34213,12 +34223,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285);
/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(286);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(280);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(288);
-/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(289);
-/** PURE_IMPORTS_START _util_isArray,_util_isObject,_util_isFunction,_util_tryCatch,_util_errorObject,_util_UnsubscriptionError PURE_IMPORTS_END */
-
-
+/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(287);
+/** PURE_IMPORTS_START _util_isArray,_util_isObject,_util_isFunction,_util_UnsubscriptionError PURE_IMPORTS_END */
@@ -34226,94 +34232,112 @@ __webpack_require__.r(__webpack_exports__);
var Subscription = /*@__PURE__*/ (function () {
function Subscription(unsubscribe) {
this.closed = false;
- this._parent = null;
- this._parents = null;
+ this._parentOrParents = null;
this._subscriptions = null;
if (unsubscribe) {
this._unsubscribe = unsubscribe;
}
}
Subscription.prototype.unsubscribe = function () {
- var hasErrors = false;
var errors;
if (this.closed) {
return;
}
- var _a = this, _parent = _a._parent, _parents = _a._parents, _unsubscribe = _a._unsubscribe, _subscriptions = _a._subscriptions;
+ var _a = this, _parentOrParents = _a._parentOrParents, _unsubscribe = _a._unsubscribe, _subscriptions = _a._subscriptions;
this.closed = true;
- this._parent = null;
- this._parents = null;
+ this._parentOrParents = null;
this._subscriptions = null;
- var index = -1;
- var len = _parents ? _parents.length : 0;
- while (_parent) {
- _parent.remove(this);
- _parent = ++index < len && _parents[index] || null;
+ if (_parentOrParents instanceof Subscription) {
+ _parentOrParents.remove(this);
+ }
+ else if (_parentOrParents !== null) {
+ for (var index = 0; index < _parentOrParents.length; ++index) {
+ var parent_1 = _parentOrParents[index];
+ parent_1.remove(this);
+ }
}
if (Object(_util_isFunction__WEBPACK_IMPORTED_MODULE_2__["isFunction"])(_unsubscribe)) {
- var trial = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_3__["tryCatch"])(_unsubscribe).call(this);
- if (trial === _util_errorObject__WEBPACK_IMPORTED_MODULE_4__["errorObject"]) {
- hasErrors = true;
- errors = errors || (_util_errorObject__WEBPACK_IMPORTED_MODULE_4__["errorObject"].e instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__["UnsubscriptionError"] ?
- flattenUnsubscriptionErrors(_util_errorObject__WEBPACK_IMPORTED_MODULE_4__["errorObject"].e.errors) : [_util_errorObject__WEBPACK_IMPORTED_MODULE_4__["errorObject"].e]);
+ try {
+ _unsubscribe.call(this);
+ }
+ catch (e) {
+ errors = e instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_3__["UnsubscriptionError"] ? flattenUnsubscriptionErrors(e.errors) : [e];
}
}
if (Object(_util_isArray__WEBPACK_IMPORTED_MODULE_0__["isArray"])(_subscriptions)) {
- index = -1;
- len = _subscriptions.length;
+ var index = -1;
+ var len = _subscriptions.length;
while (++index < len) {
var sub = _subscriptions[index];
if (Object(_util_isObject__WEBPACK_IMPORTED_MODULE_1__["isObject"])(sub)) {
- var trial = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_3__["tryCatch"])(sub.unsubscribe).call(sub);
- if (trial === _util_errorObject__WEBPACK_IMPORTED_MODULE_4__["errorObject"]) {
- hasErrors = true;
+ try {
+ sub.unsubscribe();
+ }
+ catch (e) {
errors = errors || [];
- var err = _util_errorObject__WEBPACK_IMPORTED_MODULE_4__["errorObject"].e;
- if (err instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__["UnsubscriptionError"]) {
- errors = errors.concat(flattenUnsubscriptionErrors(err.errors));
+ if (e instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_3__["UnsubscriptionError"]) {
+ errors = errors.concat(flattenUnsubscriptionErrors(e.errors));
}
else {
- errors.push(err);
+ errors.push(e);
}
}
}
}
}
- if (hasErrors) {
- throw new _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__["UnsubscriptionError"](errors);
+ if (errors) {
+ throw new _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_3__["UnsubscriptionError"](errors);
}
};
Subscription.prototype.add = function (teardown) {
- if (!teardown || (teardown === Subscription.EMPTY)) {
+ var subscription = teardown;
+ if (!teardown) {
return Subscription.EMPTY;
}
- if (teardown === this) {
- return this;
- }
- var subscription = teardown;
switch (typeof teardown) {
case 'function':
subscription = new Subscription(teardown);
case 'object':
- if (subscription.closed || typeof subscription.unsubscribe !== 'function') {
+ if (subscription === this || subscription.closed || typeof subscription.unsubscribe !== 'function') {
return subscription;
}
else if (this.closed) {
subscription.unsubscribe();
return subscription;
}
- else if (typeof subscription._addParent !== 'function') {
+ else if (!(subscription instanceof Subscription)) {
var tmp = subscription;
subscription = new Subscription();
subscription._subscriptions = [tmp];
}
break;
- default:
+ default: {
throw new Error('unrecognized teardown ' + teardown + ' added to Subscription.');
+ }
+ }
+ var _parentOrParents = subscription._parentOrParents;
+ if (_parentOrParents === null) {
+ subscription._parentOrParents = this;
+ }
+ else if (_parentOrParents instanceof Subscription) {
+ if (_parentOrParents === this) {
+ return subscription;
+ }
+ subscription._parentOrParents = [_parentOrParents, this];
+ }
+ else if (_parentOrParents.indexOf(this) === -1) {
+ _parentOrParents.push(this);
+ }
+ else {
+ return subscription;
+ }
+ var subscriptions = this._subscriptions;
+ if (subscriptions === null) {
+ this._subscriptions = [subscription];
+ }
+ else {
+ subscriptions.push(subscription);
}
- var subscriptions = this._subscriptions || (this._subscriptions = []);
- subscriptions.push(subscription);
- subscription._addParent(this);
return subscription;
};
Subscription.prototype.remove = function (subscription) {
@@ -34325,18 +34349,6 @@ var Subscription = /*@__PURE__*/ (function () {
}
}
};
- Subscription.prototype._addParent = function (parent) {
- var _a = this, _parent = _a._parent, _parents = _a._parents;
- if (!_parent || _parent === parent) {
- this._parent = parent;
- }
- else if (!_parents) {
- this._parents = [parent];
- }
- else if (_parents.indexOf(parent) === -1) {
- _parents.push(parent);
- }
- };
Subscription.EMPTY = (function (empty) {
empty.closed = true;
return empty;
@@ -34345,7 +34357,7 @@ var Subscription = /*@__PURE__*/ (function () {
}());
function flattenUnsubscriptionErrors(errors) {
- return errors.reduce(function (errs, err) { return errs.concat((err instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__["UnsubscriptionError"]) ? err.errors : err); }, []);
+ return errors.reduce(function (errs, err) { return errs.concat((err instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_3__["UnsubscriptionError"]) ? err.errors : err); }, []);
}
//# sourceMappingURL=Subscription.js.map
@@ -34358,7 +34370,7 @@ function flattenUnsubscriptionErrors(errors) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isArray", function() { return isArray; });
/** PURE_IMPORTS_START PURE_IMPORTS_END */
-var isArray = Array.isArray || (function (x) { return x && typeof x.length === 'number'; });
+var isArray = /*@__PURE__*/ (function () { return Array.isArray || (function (x) { return x && typeof x.length === 'number'; }); })();
//# sourceMappingURL=isArray.js.map
@@ -34371,7 +34383,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isObject", function() { return isObject; });
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function isObject(x) {
- return x != null && typeof x === 'object';
+ return x !== null && typeof x === 'object';
}
//# sourceMappingURL=isObject.js.map
@@ -34382,25 +34394,22 @@ function isObject(x) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tryCatch", function() { return tryCatch; });
-/* harmony import */ var _errorObject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(288);
-/** PURE_IMPORTS_START _errorObject PURE_IMPORTS_END */
-
-var tryCatchTarget;
-function tryCatcher() {
- try {
- return tryCatchTarget.apply(this, arguments);
- }
- catch (e) {
- _errorObject__WEBPACK_IMPORTED_MODULE_0__["errorObject"].e = e;
- return _errorObject__WEBPACK_IMPORTED_MODULE_0__["errorObject"];
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return UnsubscriptionError; });
+/** PURE_IMPORTS_START PURE_IMPORTS_END */
+var UnsubscriptionErrorImpl = /*@__PURE__*/ (function () {
+ function UnsubscriptionErrorImpl(errors) {
+ Error.call(this);
+ this.message = errors ?
+ errors.length + " errors occurred during unsubscription:\n" + errors.map(function (err, i) { return i + 1 + ") " + err.toString(); }).join('\n ') : '';
+ this.name = 'UnsubscriptionError';
+ this.errors = errors;
+ return this;
}
-}
-function tryCatch(fn) {
- tryCatchTarget = fn;
- return tryCatcher;
-}
-//# sourceMappingURL=tryCatch.js.map
+ UnsubscriptionErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
+ return UnsubscriptionErrorImpl;
+})();
+var UnsubscriptionError = UnsubscriptionErrorImpl;
+//# sourceMappingURL=UnsubscriptionError.js.map
/***/ }),
@@ -34409,10 +34418,16 @@ function tryCatch(fn) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "errorObject", function() { return errorObject; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "rxSubscriber", function() { return rxSubscriber; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "$$rxSubscriber", function() { return $$rxSubscriber; });
/** PURE_IMPORTS_START PURE_IMPORTS_END */
-var errorObject = { e: {} };
-//# sourceMappingURL=errorObject.js.map
+var rxSubscriber = /*@__PURE__*/ (function () {
+ return typeof Symbol === 'function'
+ ? /*@__PURE__*/ Symbol('rxSubscriber')
+ : '@@rxSubscriber_' + /*@__PURE__*/ Math.random();
+})();
+var $$rxSubscriber = rxSubscriber;
+//# sourceMappingURL=rxSubscriber.js.map
/***/ }),
@@ -34421,63 +34436,52 @@ var errorObject = { e: {} };
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return UnsubscriptionError; });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/** PURE_IMPORTS_START tslib PURE_IMPORTS_END */
-
-var UnsubscriptionError = /*@__PURE__*/ (function (_super) {
- tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](UnsubscriptionError, _super);
- function UnsubscriptionError(errors) {
- var _this = _super.call(this, errors ?
- errors.length + " errors occurred during unsubscription:\n " + errors.map(function (err, i) { return i + 1 + ") " + err.toString(); }).join('\n ') : '') || this;
- _this.errors = errors;
- _this.name = 'UnsubscriptionError';
- Object.setPrototypeOf(_this, UnsubscriptionError.prototype);
- return _this;
- }
- return UnsubscriptionError;
-}(Error));
-
-//# sourceMappingURL=UnsubscriptionError.js.map
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toSubscriber", function() { return toSubscriber; });
+/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(278);
+/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(288);
+/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(281);
+/** PURE_IMPORTS_START _Subscriber,_symbol_rxSubscriber,_Observer PURE_IMPORTS_END */
-/***/ }),
-/* 290 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "rxSubscriber", function() { return rxSubscriber; });
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "$$rxSubscriber", function() { return $$rxSubscriber; });
-/** PURE_IMPORTS_START PURE_IMPORTS_END */
-var rxSubscriber = (typeof Symbol === 'function' && typeof Symbol.for === 'function')
- ? /*@__PURE__*/ Symbol.for('rxSubscriber')
- : '@@rxSubscriber';
-var $$rxSubscriber = rxSubscriber;
-//# sourceMappingURL=rxSubscriber.js.map
+function toSubscriber(nextOrObserver, error, complete) {
+ if (nextOrObserver) {
+ if (nextOrObserver instanceof _Subscriber__WEBPACK_IMPORTED_MODULE_0__["Subscriber"]) {
+ return nextOrObserver;
+ }
+ if (nextOrObserver[_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__["rxSubscriber"]]) {
+ return nextOrObserver[_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__["rxSubscriber"]]();
+ }
+ }
+ if (!nextOrObserver && !error && !complete) {
+ return new _Subscriber__WEBPACK_IMPORTED_MODULE_0__["Subscriber"](_Observer__WEBPACK_IMPORTED_MODULE_2__["empty"]);
+ }
+ return new _Subscriber__WEBPACK_IMPORTED_MODULE_0__["Subscriber"](nextOrObserver, error, complete);
+}
+//# sourceMappingURL=toSubscriber.js.map
/***/ }),
-/* 291 */
+/* 290 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "observable", function() { return observable; });
/** PURE_IMPORTS_START PURE_IMPORTS_END */
-var observable = typeof Symbol === 'function' && Symbol.observable || '@@observable';
+var observable = /*@__PURE__*/ (function () { return typeof Symbol === 'function' && Symbol.observable || '@@observable'; })();
//# sourceMappingURL=observable.js.map
/***/ }),
-/* 292 */
+/* 291 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return pipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipeFromArray", function() { return pipeFromArray; });
-/* harmony import */ var _noop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(293);
+/* harmony import */ var _noop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);
/** PURE_IMPORTS_START _noop PURE_IMPORTS_END */
function pipe() {
@@ -34502,7 +34506,7 @@ function pipeFromArray(fns) {
/***/ }),
-/* 293 */
+/* 292 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -34514,7 +34518,7 @@ function noop() { }
/***/ }),
-/* 294 */
+/* 293 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -34522,11 +34526,11 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return ConnectableObservable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "connectableObservableDescriptor", function() { return connectableObservableDescriptor; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(284);
-/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(298);
+/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(297);
/** PURE_IMPORTS_START tslib,_Subject,_Observable,_Subscriber,_Subscription,_operators_refCount PURE_IMPORTS_END */
@@ -34565,9 +34569,6 @@ var ConnectableObservable = /*@__PURE__*/ (function (_super) {
this._connection = null;
connection = _Subscription__WEBPACK_IMPORTED_MODULE_4__["Subscription"].EMPTY;
}
- else {
- this._connection = connection;
- }
}
return connection;
};
@@ -34577,18 +34578,20 @@ var ConnectableObservable = /*@__PURE__*/ (function (_super) {
return ConnectableObservable;
}(_Observable__WEBPACK_IMPORTED_MODULE_2__["Observable"]));
-var connectableProto = ConnectableObservable.prototype;
-var connectableObservableDescriptor = {
- operator: { value: null },
- _refCount: { value: 0, writable: true },
- _subject: { value: null, writable: true },
- _connection: { value: null, writable: true },
- _subscribe: { value: connectableProto._subscribe },
- _isComplete: { value: connectableProto._isComplete, writable: true },
- getSubject: { value: connectableProto.getSubject },
- connect: { value: connectableProto.connect },
- refCount: { value: connectableProto.refCount }
-};
+var connectableObservableDescriptor = /*@__PURE__*/ (function () {
+ var connectableProto = ConnectableObservable.prototype;
+ return {
+ operator: { value: null },
+ _refCount: { value: 0, writable: true },
+ _subject: { value: null, writable: true },
+ _connection: { value: null, writable: true },
+ _subscribe: { value: connectableProto._subscribe },
+ _isComplete: { value: connectableProto._isComplete, writable: true },
+ getSubject: { value: connectableProto.getSubject },
+ connect: { value: connectableProto.connect },
+ refCount: { value: connectableProto.refCount }
+ };
+})();
var ConnectableSubscriber = /*@__PURE__*/ (function (_super) {
tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](ConnectableSubscriber, _super);
function ConnectableSubscriber(destination, connectable) {
@@ -34673,7 +34676,7 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 295 */
+/* 294 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -34685,9 +34688,9 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(278);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(284);
-/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(296);
-/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(297);
-/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(290);
+/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(295);
+/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(296);
+/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(288);
/** PURE_IMPORTS_START tslib,_Observable,_Subscriber,_Subscription,_util_ObjectUnsubscribedError,_SubjectSubscription,_internal_symbol_rxSubscriber PURE_IMPORTS_END */
@@ -34849,31 +34852,29 @@ var AnonymousSubject = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 296 */
+/* 295 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObjectUnsubscribedError", function() { return ObjectUnsubscribedError; });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/** PURE_IMPORTS_START tslib PURE_IMPORTS_END */
-
-var ObjectUnsubscribedError = /*@__PURE__*/ (function (_super) {
- tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](ObjectUnsubscribedError, _super);
- function ObjectUnsubscribedError() {
- var _this = _super.call(this, 'object unsubscribed') || this;
- _this.name = 'ObjectUnsubscribedError';
- Object.setPrototypeOf(_this, ObjectUnsubscribedError.prototype);
- return _this;
+/** PURE_IMPORTS_START PURE_IMPORTS_END */
+var ObjectUnsubscribedErrorImpl = /*@__PURE__*/ (function () {
+ function ObjectUnsubscribedErrorImpl() {
+ Error.call(this);
+ this.message = 'object unsubscribed';
+ this.name = 'ObjectUnsubscribedError';
+ return this;
}
- return ObjectUnsubscribedError;
-}(Error));
-
+ ObjectUnsubscribedErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
+ return ObjectUnsubscribedErrorImpl;
+})();
+var ObjectUnsubscribedError = ObjectUnsubscribedErrorImpl;
//# sourceMappingURL=ObjectUnsubscribedError.js.map
/***/ }),
-/* 297 */
+/* 296 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -34916,7 +34917,7 @@ var SubjectSubscription = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 298 */
+/* 297 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -34985,7 +34986,7 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 299 */
+/* 298 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -34996,7 +34997,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(284);
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(276);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(295);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(294);
/** PURE_IMPORTS_START tslib,_Subscriber,_Subscription,_Observable,_Subject PURE_IMPORTS_END */
@@ -35182,15 +35183,15 @@ var InnerRefCountSubscription = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 300 */
+/* 299 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return BehaviorSubject; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
-/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(296);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
+/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(295);
/** PURE_IMPORTS_START tslib,_Subject,_util_ObjectUnsubscribedError PURE_IMPORTS_END */
@@ -35237,19 +35238,19 @@ var BehaviorSubject = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 301 */
+/* 300 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return ReplaySubject; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
-/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(302);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
+/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(301);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(284);
-/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(309);
-/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(296);
-/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(297);
+/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(308);
+/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(295);
+/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(296);
/** PURE_IMPORTS_START tslib,_Subject,_scheduler_queue,_Subscription,_operators_observeOn,_util_ObjectUnsubscribedError,_SubjectSubscription PURE_IMPORTS_END */
@@ -35370,14 +35371,14 @@ var ReplayEvent = /*@__PURE__*/ (function () {
/***/ }),
-/* 302 */
+/* 301 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "queue", function() { return queue; });
-/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(303);
-/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(306);
+/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(302);
+/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(305);
/** PURE_IMPORTS_START _QueueAction,_QueueScheduler PURE_IMPORTS_END */
@@ -35386,14 +35387,14 @@ var queue = /*@__PURE__*/ new _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__["Queu
/***/ }),
-/* 303 */
+/* 302 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueAction", function() { return QueueAction; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(304);
+/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(303);
/** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */
@@ -35438,14 +35439,14 @@ var QueueAction = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 304 */
+/* 303 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncAction", function() { return AsyncAction; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(305);
+/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(304);
/** PURE_IMPORTS_START tslib,_Action PURE_IMPORTS_END */
@@ -35489,7 +35490,8 @@ var AsyncAction = /*@__PURE__*/ (function (_super) {
if (delay !== null && this.delay === delay && this.pending === false) {
return id;
}
- return clearInterval(id) && undefined || undefined;
+ clearInterval(id);
+ return undefined;
};
AsyncAction.prototype.execute = function (state, delay) {
if (this.closed) {
@@ -35543,7 +35545,7 @@ var AsyncAction = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 305 */
+/* 304 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35572,14 +35574,14 @@ var Action = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 306 */
+/* 305 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueScheduler", function() { return QueueScheduler; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(307);
+/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(306);
/** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */
@@ -35595,14 +35597,14 @@ var QueueScheduler = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 307 */
+/* 306 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncScheduler", function() { return AsyncScheduler; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(308);
+/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(307);
/** PURE_IMPORTS_START tslib,_Scheduler PURE_IMPORTS_END */
@@ -35664,7 +35666,7 @@ var AsyncScheduler = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 308 */
+/* 307 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35684,7 +35686,7 @@ var Scheduler = /*@__PURE__*/ (function () {
}
return new this.SchedulerAction(this, work).schedule(state, delay);
};
- Scheduler.now = Date.now ? Date.now : function () { return +new Date(); };
+ Scheduler.now = function () { return Date.now(); };
return Scheduler;
}());
@@ -35692,7 +35694,7 @@ var Scheduler = /*@__PURE__*/ (function () {
/***/ }),
-/* 309 */
+/* 308 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35703,7 +35705,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnMessage", function() { return ObserveOnMessage; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(310);
+/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(309);
/** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */
@@ -35747,16 +35749,19 @@ var ObserveOnSubscriber = /*@__PURE__*/ (function (_super) {
this.unsubscribe();
};
ObserveOnSubscriber.prototype.scheduleMessage = function (notification) {
- this.add(this.scheduler.schedule(ObserveOnSubscriber.dispatch, this.delay, new ObserveOnMessage(notification, this.destination)));
+ var destination = this.destination;
+ destination.add(this.scheduler.schedule(ObserveOnSubscriber.dispatch, this.delay, new ObserveOnMessage(notification, this.destination)));
};
ObserveOnSubscriber.prototype._next = function (value) {
this.scheduleMessage(_Notification__WEBPACK_IMPORTED_MODULE_2__["Notification"].createNext(value));
};
ObserveOnSubscriber.prototype._error = function (err) {
this.scheduleMessage(_Notification__WEBPACK_IMPORTED_MODULE_2__["Notification"].createError(err));
+ this.unsubscribe();
};
ObserveOnSubscriber.prototype._complete = function () {
this.scheduleMessage(_Notification__WEBPACK_IMPORTED_MODULE_2__["Notification"].createComplete());
+ this.unsubscribe();
};
return ObserveOnSubscriber;
}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"]));
@@ -35773,19 +35778,26 @@ var ObserveOnMessage = /*@__PURE__*/ (function () {
/***/ }),
-/* 310 */
+/* 309 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NotificationKind", function() { return NotificationKind; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return Notification; });
-/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(311);
-/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(312);
-/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(317);
+/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(310);
+/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(311);
+/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(316);
/** PURE_IMPORTS_START _observable_empty,_observable_of,_observable_throwError PURE_IMPORTS_END */
+var NotificationKind;
+/*@__PURE__*/ (function (NotificationKind) {
+ NotificationKind["NEXT"] = "N";
+ NotificationKind["ERROR"] = "E";
+ NotificationKind["COMPLETE"] = "C";
+})(NotificationKind || (NotificationKind = {}));
var Notification = /*@__PURE__*/ (function () {
function Notification(kind, value, error) {
this.kind = kind;
@@ -35855,14 +35867,13 @@ var Notification = /*@__PURE__*/ (function () {
/***/ }),
-/* 311 */
+/* 310 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return EMPTY; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return empty; });
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "emptyScheduled", function() { return emptyScheduled; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
/** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */
@@ -35877,18 +35888,16 @@ function emptyScheduled(scheduler) {
/***/ }),
-/* 312 */
+/* 311 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "of", function() { return of; });
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(313);
-/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(314);
-/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311);
-/* harmony import */ var _scalar__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(316);
-/** PURE_IMPORTS_START _util_isScheduler,_fromArray,_empty,_scalar PURE_IMPORTS_END */
-
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(312);
+/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313);
+/* harmony import */ var _scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(315);
+/** PURE_IMPORTS_START _util_isScheduler,_fromArray,_scheduled_scheduleArray PURE_IMPORTS_END */
@@ -35900,24 +35909,17 @@ function of() {
var scheduler = args[args.length - 1];
if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_0__["isScheduler"])(scheduler)) {
args.pop();
+ return Object(_scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__["scheduleArray"])(args, scheduler);
}
else {
- scheduler = undefined;
- }
- switch (args.length) {
- case 0:
- return Object(_empty__WEBPACK_IMPORTED_MODULE_2__["empty"])(scheduler);
- case 1:
- return scheduler ? Object(_fromArray__WEBPACK_IMPORTED_MODULE_1__["fromArray"])(args, scheduler) : Object(_scalar__WEBPACK_IMPORTED_MODULE_3__["scalar"])(args[0]);
- default:
- return Object(_fromArray__WEBPACK_IMPORTED_MODULE_1__["fromArray"])(args, scheduler);
+ return Object(_fromArray__WEBPACK_IMPORTED_MODULE_1__["fromArray"])(args);
}
}
//# sourceMappingURL=of.js.map
/***/ }),
-/* 313 */
+/* 312 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35931,46 +35933,32 @@ function isScheduler(value) {
/***/ }),
-/* 314 */
+/* 313 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromArray", function() { return fromArray; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
-/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(315);
-/** PURE_IMPORTS_START _Observable,_Subscription,_util_subscribeToArray PURE_IMPORTS_END */
+/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(314);
+/* harmony import */ var _scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(315);
+/** PURE_IMPORTS_START _Observable,_util_subscribeToArray,_scheduled_scheduleArray PURE_IMPORTS_END */
function fromArray(input, scheduler) {
if (!scheduler) {
- return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](Object(_util_subscribeToArray__WEBPACK_IMPORTED_MODULE_2__["subscribeToArray"])(input));
+ return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](Object(_util_subscribeToArray__WEBPACK_IMPORTED_MODULE_1__["subscribeToArray"])(input));
}
else {
- return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
- var sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
- var i = 0;
- sub.add(scheduler.schedule(function () {
- if (i === input.length) {
- subscriber.complete();
- return;
- }
- subscriber.next(input[i++]);
- if (!subscriber.closed) {
- sub.add(this.schedule());
- }
- }));
- return sub;
- });
+ return Object(_scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__["scheduleArray"])(input, scheduler);
}
}
//# sourceMappingURL=fromArray.js.map
/***/ }),
-/* 315 */
+/* 314 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35982,38 +35970,46 @@ var subscribeToArray = function (array) {
for (var i = 0, len = array.length; i < len && !subscriber.closed; i++) {
subscriber.next(array[i]);
}
- if (!subscriber.closed) {
- subscriber.complete();
- }
+ subscriber.complete();
};
};
//# sourceMappingURL=subscribeToArray.js.map
/***/ }),
-/* 316 */
+/* 315 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scalar", function() { return scalar; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scheduleArray", function() { return scheduleArray; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */
+/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
+/** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */
-function scalar(value) {
- var result = new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
- subscriber.next(value);
- subscriber.complete();
+
+function scheduleArray(input, scheduler) {
+ return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
+ var sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
+ var i = 0;
+ sub.add(scheduler.schedule(function () {
+ if (i === input.length) {
+ subscriber.complete();
+ return;
+ }
+ subscriber.next(input[i++]);
+ if (!subscriber.closed) {
+ sub.add(this.schedule());
+ }
+ }));
+ return sub;
});
- result._isScalar = true;
- result.value = value;
- return result;
}
-//# sourceMappingURL=scalar.js.map
+//# sourceMappingURL=scheduleArray.js.map
/***/ }),
-/* 317 */
+/* 316 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36038,14 +36034,14 @@ function dispatch(_a) {
/***/ }),
-/* 318 */
+/* 317 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return AsyncSubject; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(284);
/** PURE_IMPORTS_START tslib,_Subject,_Subscription PURE_IMPORTS_END */
@@ -36097,14 +36093,14 @@ var AsyncSubject = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 319 */
+/* 318 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asap", function() { return asap; });
-/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(320);
-/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(322);
+/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(319);
+/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(321);
/** PURE_IMPORTS_START _AsapAction,_AsapScheduler PURE_IMPORTS_END */
@@ -36113,15 +36109,15 @@ var asap = /*@__PURE__*/ new _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__["AsapSc
/***/ }),
-/* 320 */
+/* 319 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapAction", function() { return AsapAction; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(321);
-/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(304);
+/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(320);
+/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(303);
/** PURE_IMPORTS_START tslib,_util_Immediate,_AsyncAction PURE_IMPORTS_END */
@@ -36164,7 +36160,7 @@ var AsapAction = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 321 */
+/* 320 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36194,14 +36190,14 @@ var Immediate = {
/***/ }),
-/* 322 */
+/* 321 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapScheduler", function() { return AsapScheduler; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(307);
+/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(306);
/** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */
@@ -36238,14 +36234,14 @@ var AsapScheduler = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 323 */
+/* 322 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "async", function() { return async; });
-/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(304);
-/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(307);
+/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(303);
+/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(306);
/** PURE_IMPORTS_START _AsyncAction,_AsyncScheduler PURE_IMPORTS_END */
@@ -36254,14 +36250,14 @@ var async = /*@__PURE__*/ new _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__["Asyn
/***/ }),
-/* 324 */
+/* 323 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "animationFrame", function() { return animationFrame; });
-/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(325);
-/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(326);
+/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(324);
+/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(325);
/** PURE_IMPORTS_START _AnimationFrameAction,_AnimationFrameScheduler PURE_IMPORTS_END */
@@ -36270,14 +36266,14 @@ var animationFrame = /*@__PURE__*/ new _AnimationFrameScheduler__WEBPACK_IMPORTE
/***/ }),
-/* 325 */
+/* 324 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameAction", function() { return AnimationFrameAction; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(304);
+/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(303);
/** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */
@@ -36319,14 +36315,14 @@ var AnimationFrameAction = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 326 */
+/* 325 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameScheduler", function() { return AnimationFrameScheduler; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(307);
+/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(306);
/** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */
@@ -36363,7 +36359,7 @@ var AnimationFrameScheduler = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 327 */
+/* 326 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36371,8 +36367,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return VirtualTimeScheduler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return VirtualAction; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(304);
-/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(307);
+/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(303);
+/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(306);
/** PURE_IMPORTS_START tslib,_AsyncAction,_AsyncScheduler PURE_IMPORTS_END */
@@ -36395,7 +36391,9 @@ var VirtualTimeScheduler = /*@__PURE__*/ (function (_super) {
VirtualTimeScheduler.prototype.flush = function () {
var _a = this, actions = _a.actions, maxFrames = _a.maxFrames;
var error, action;
- while ((action = actions.shift()) && (this.frame = action.delay) <= maxFrames) {
+ while ((action = actions[0]) && action.delay <= maxFrames) {
+ actions.shift();
+ this.frame = action.delay;
if (error = action.execute(action.state, action.delay)) {
break;
}
@@ -36484,7 +36482,7 @@ var VirtualAction = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 328 */
+/* 327 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36498,7 +36496,7 @@ function identity(x) {
/***/ }),
-/* 329 */
+/* 328 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36514,90 +36512,86 @@ function isObservable(obj) {
/***/ }),
-/* 330 */
+/* 329 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArgumentOutOfRangeError", function() { return ArgumentOutOfRangeError; });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/** PURE_IMPORTS_START tslib PURE_IMPORTS_END */
-
-var ArgumentOutOfRangeError = /*@__PURE__*/ (function (_super) {
- tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](ArgumentOutOfRangeError, _super);
- function ArgumentOutOfRangeError() {
- var _this = _super.call(this, 'argument out of range') || this;
- _this.name = 'ArgumentOutOfRangeError';
- Object.setPrototypeOf(_this, ArgumentOutOfRangeError.prototype);
- return _this;
+/** PURE_IMPORTS_START PURE_IMPORTS_END */
+var ArgumentOutOfRangeErrorImpl = /*@__PURE__*/ (function () {
+ function ArgumentOutOfRangeErrorImpl() {
+ Error.call(this);
+ this.message = 'argument out of range';
+ this.name = 'ArgumentOutOfRangeError';
+ return this;
}
- return ArgumentOutOfRangeError;
-}(Error));
-
+ ArgumentOutOfRangeErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
+ return ArgumentOutOfRangeErrorImpl;
+})();
+var ArgumentOutOfRangeError = ArgumentOutOfRangeErrorImpl;
//# sourceMappingURL=ArgumentOutOfRangeError.js.map
/***/ }),
-/* 331 */
+/* 330 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmptyError", function() { return EmptyError; });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/** PURE_IMPORTS_START tslib PURE_IMPORTS_END */
-
-var EmptyError = /*@__PURE__*/ (function (_super) {
- tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](EmptyError, _super);
- function EmptyError() {
- var _this = _super.call(this, 'no elements in sequence') || this;
- _this.name = 'EmptyError';
- Object.setPrototypeOf(_this, EmptyError.prototype);
- return _this;
+/** PURE_IMPORTS_START PURE_IMPORTS_END */
+var EmptyErrorImpl = /*@__PURE__*/ (function () {
+ function EmptyErrorImpl() {
+ Error.call(this);
+ this.message = 'no elements in sequence';
+ this.name = 'EmptyError';
+ return this;
}
- return EmptyError;
-}(Error));
-
+ EmptyErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
+ return EmptyErrorImpl;
+})();
+var EmptyError = EmptyErrorImpl;
//# sourceMappingURL=EmptyError.js.map
/***/ }),
-/* 332 */
+/* 331 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return TimeoutError; });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/** PURE_IMPORTS_START tslib PURE_IMPORTS_END */
-
-var TimeoutError = /*@__PURE__*/ (function (_super) {
- tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](TimeoutError, _super);
- function TimeoutError() {
- var _this = _super.call(this, 'Timeout has occurred') || this;
- _this.name = 'TimeoutError';
- Object.setPrototypeOf(_this, TimeoutError.prototype);
- return _this;
+/** PURE_IMPORTS_START PURE_IMPORTS_END */
+var TimeoutErrorImpl = /*@__PURE__*/ (function () {
+ function TimeoutErrorImpl() {
+ Error.call(this);
+ this.message = 'Timeout has occurred';
+ this.name = 'TimeoutError';
+ return this;
}
- return TimeoutError;
-}(Error));
-
+ TimeoutErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
+ return TimeoutErrorImpl;
+})();
+var TimeoutError = TimeoutErrorImpl;
//# sourceMappingURL=TimeoutError.js.map
/***/ }),
-/* 333 */
+/* 332 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return bindCallback; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(318);
-/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(334);
-/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(285);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(313);
-/** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_isArray,_util_isScheduler PURE_IMPORTS_END */
+/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(317);
+/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(333);
+/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(277);
+/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(285);
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(312);
+/** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_canReportError,_util_isArray,_util_isScheduler PURE_IMPORTS_END */
+
@@ -36605,7 +36599,7 @@ __webpack_require__.r(__webpack_exports__);
function bindCallback(callbackFunc, resultSelector, scheduler) {
if (resultSelector) {
- if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_4__["isScheduler"])(resultSelector)) {
+ if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_5__["isScheduler"])(resultSelector)) {
scheduler = resultSelector;
}
else {
@@ -36614,7 +36608,7 @@ function bindCallback(callbackFunc, resultSelector, scheduler) {
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
- return bindCallback(callbackFunc, scheduler).apply(void 0, args).pipe(Object(_operators_map__WEBPACK_IMPORTED_MODULE_2__["map"])(function (args) { return Object(_util_isArray__WEBPACK_IMPORTED_MODULE_3__["isArray"])(args) ? resultSelector.apply(void 0, args) : resultSelector(args); }));
+ return bindCallback(callbackFunc, scheduler).apply(void 0, args).pipe(Object(_operators_map__WEBPACK_IMPORTED_MODULE_2__["map"])(function (args) { return Object(_util_isArray__WEBPACK_IMPORTED_MODULE_4__["isArray"])(args) ? resultSelector.apply(void 0, args) : resultSelector(args); }));
};
}
}
@@ -36647,7 +36641,12 @@ function bindCallback(callbackFunc, resultSelector, scheduler) {
callbackFunc.apply(context, args.concat([handler]));
}
catch (err) {
- subject.error(err);
+ if (Object(_util_canReportError__WEBPACK_IMPORTED_MODULE_3__["canReportError"])(subject)) {
+ subject.error(err);
+ }
+ else {
+ console.warn(err);
+ }
}
}
return subject.subscribe(subscriber);
@@ -36699,7 +36698,7 @@ function dispatchError(state) {
/***/ }),
-/* 334 */
+/* 333 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36756,18 +36755,20 @@ var MapSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 335 */
+/* 334 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return bindNodeCallback; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(318);
-/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(334);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(313);
-/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(285);
-/** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_isScheduler,_util_isArray PURE_IMPORTS_END */
+/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(317);
+/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(333);
+/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(277);
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(312);
+/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(285);
+/** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_canReportError,_util_isScheduler,_util_isArray PURE_IMPORTS_END */
+
@@ -36775,7 +36776,7 @@ __webpack_require__.r(__webpack_exports__);
function bindNodeCallback(callbackFunc, resultSelector, scheduler) {
if (resultSelector) {
- if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_3__["isScheduler"])(resultSelector)) {
+ if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_4__["isScheduler"])(resultSelector)) {
scheduler = resultSelector;
}
else {
@@ -36784,7 +36785,7 @@ function bindNodeCallback(callbackFunc, resultSelector, scheduler) {
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
- return bindNodeCallback(callbackFunc, scheduler).apply(void 0, args).pipe(Object(_operators_map__WEBPACK_IMPORTED_MODULE_2__["map"])(function (args) { return Object(_util_isArray__WEBPACK_IMPORTED_MODULE_4__["isArray"])(args) ? resultSelector.apply(void 0, args) : resultSelector(args); }));
+ return bindNodeCallback(callbackFunc, scheduler).apply(void 0, args).pipe(Object(_operators_map__WEBPACK_IMPORTED_MODULE_2__["map"])(function (args) { return Object(_util_isArray__WEBPACK_IMPORTED_MODULE_5__["isArray"])(args) ? resultSelector.apply(void 0, args) : resultSelector(args); }));
};
}
}
@@ -36823,7 +36824,12 @@ function bindNodeCallback(callbackFunc, resultSelector, scheduler) {
callbackFunc.apply(context, args.concat([handler]));
}
catch (err) {
- subject.error(err);
+ if (Object(_util_canReportError__WEBPACK_IMPORTED_MODULE_3__["canReportError"])(subject)) {
+ subject.error(err);
+ }
+ else {
+ console.warn(err);
+ }
}
}
return subject.subscribe(subscriber);
@@ -36877,7 +36883,7 @@ function dispatchError(arg) {
/***/ }),
-/* 336 */
+/* 335 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36886,11 +36892,11 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestOperator", function() { return CombineLatestOperator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestSubscriber", function() { return CombineLatestSubscriber; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313);
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(312);
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338);
-/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(314);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
+/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(313);
/** PURE_IMPORTS_START tslib,_util_isScheduler,_util_isArray,_OuterSubscriber,_util_subscribeToResult,_fromArray PURE_IMPORTS_END */
@@ -36995,7 +37001,7 @@ var CombineLatestSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 337 */
+/* 336 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -37027,26 +37033,36 @@ var OuterSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 338 */
+/* 337 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToResult", function() { return subscribeToResult; });
-/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(339);
-/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(340);
-/** PURE_IMPORTS_START _InnerSubscriber,_subscribeTo PURE_IMPORTS_END */
+/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(338);
+/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(339);
+/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276);
+/** PURE_IMPORTS_START _InnerSubscriber,_subscribeTo,_Observable PURE_IMPORTS_END */
+
-function subscribeToResult(outerSubscriber, result, outerValue, outerIndex) {
- var destination = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__["InnerSubscriber"](outerSubscriber, outerValue, outerIndex);
+function subscribeToResult(outerSubscriber, result, outerValue, outerIndex, destination) {
+ if (destination === void 0) {
+ destination = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__["InnerSubscriber"](outerSubscriber, outerValue, outerIndex);
+ }
+ if (destination.closed) {
+ return undefined;
+ }
+ if (result instanceof _Observable__WEBPACK_IMPORTED_MODULE_2__["Observable"]) {
+ return result.subscribe(destination);
+ }
return Object(_subscribeTo__WEBPACK_IMPORTED_MODULE_1__["subscribeTo"])(result)(destination);
}
//# sourceMappingURL=subscribeToResult.js.map
/***/ }),
-/* 339 */
+/* 338 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -37085,24 +37101,22 @@ var InnerSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 340 */
+/* 339 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeTo", function() { return subscribeTo; });
-/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(315);
-/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(341);
-/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(342);
-/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(344);
-/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(345);
-/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(346);
-/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(286);
-/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(343);
-/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(291);
-/** PURE_IMPORTS_START _Observable,_subscribeToArray,_subscribeToPromise,_subscribeToIterable,_subscribeToObservable,_isArrayLike,_isPromise,_isObject,_symbol_iterator,_symbol_observable PURE_IMPORTS_END */
-
+/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(314);
+/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(340);
+/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(341);
+/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(343);
+/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(344);
+/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(345);
+/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(286);
+/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(342);
+/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(290);
+/** PURE_IMPORTS_START _subscribeToArray,_subscribeToPromise,_subscribeToIterable,_subscribeToObservable,_isArrayLike,_isPromise,_isObject,_symbol_iterator,_symbol_observable PURE_IMPORTS_END */
@@ -37113,32 +37127,20 @@ __webpack_require__.r(__webpack_exports__);
var subscribeTo = function (result) {
- if (result instanceof _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"]) {
- return function (subscriber) {
- if (result._isScalar) {
- subscriber.next(result.value);
- subscriber.complete();
- return undefined;
- }
- else {
- return result.subscribe(subscriber);
- }
- };
+ if (!!result && typeof result[_symbol_observable__WEBPACK_IMPORTED_MODULE_8__["observable"]] === 'function') {
+ return Object(_subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__["subscribeToObservable"])(result);
}
- else if (result && typeof result[_symbol_observable__WEBPACK_IMPORTED_MODULE_9__["observable"]] === 'function') {
- return Object(_subscribeToObservable__WEBPACK_IMPORTED_MODULE_4__["subscribeToObservable"])(result);
+ else if (Object(_isArrayLike__WEBPACK_IMPORTED_MODULE_4__["isArrayLike"])(result)) {
+ return Object(_subscribeToArray__WEBPACK_IMPORTED_MODULE_0__["subscribeToArray"])(result);
}
- else if (Object(_isArrayLike__WEBPACK_IMPORTED_MODULE_5__["isArrayLike"])(result)) {
- return Object(_subscribeToArray__WEBPACK_IMPORTED_MODULE_1__["subscribeToArray"])(result);
+ else if (Object(_isPromise__WEBPACK_IMPORTED_MODULE_5__["isPromise"])(result)) {
+ return Object(_subscribeToPromise__WEBPACK_IMPORTED_MODULE_1__["subscribeToPromise"])(result);
}
- else if (Object(_isPromise__WEBPACK_IMPORTED_MODULE_6__["isPromise"])(result)) {
- return Object(_subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__["subscribeToPromise"])(result);
- }
- else if (result && typeof result[_symbol_iterator__WEBPACK_IMPORTED_MODULE_8__["iterator"]] === 'function') {
- return Object(_subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__["subscribeToIterable"])(result);
+ else if (!!result && typeof result[_symbol_iterator__WEBPACK_IMPORTED_MODULE_7__["iterator"]] === 'function') {
+ return Object(_subscribeToIterable__WEBPACK_IMPORTED_MODULE_2__["subscribeToIterable"])(result);
}
else {
- var value = Object(_isObject__WEBPACK_IMPORTED_MODULE_7__["isObject"])(result) ? 'an invalid object' : "'" + result + "'";
+ var value = Object(_isObject__WEBPACK_IMPORTED_MODULE_6__["isObject"])(result) ? 'an invalid object' : "'" + result + "'";
var msg = "You provided " + value + " where a stream was expected."
+ ' You can provide an Observable, Promise, Array, or Iterable.';
throw new TypeError(msg);
@@ -37148,7 +37150,7 @@ var subscribeTo = function (result) {
/***/ }),
-/* 341 */
+/* 340 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -37173,13 +37175,13 @@ var subscribeToPromise = function (promise) {
/***/ }),
-/* 342 */
+/* 341 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToIterable", function() { return subscribeToIterable; });
-/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(343);
+/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(342);
/** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */
var subscribeToIterable = function (iterable) {
@@ -37210,7 +37212,7 @@ var subscribeToIterable = function (iterable) {
/***/ }),
-/* 343 */
+/* 342 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -37231,13 +37233,13 @@ var $$iterator = iterator;
/***/ }),
-/* 344 */
+/* 343 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToObservable", function() { return subscribeToObservable; });
-/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(291);
+/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(290);
/** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */
var subscribeToObservable = function (obj) {
@@ -37255,7 +37257,7 @@ var subscribeToObservable = function (obj) {
/***/ }),
-/* 345 */
+/* 344 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -37267,7 +37269,7 @@ var isArrayLike = (function (x) { return x && typeof x.length === 'number' && ty
/***/ }),
-/* 346 */
+/* 345 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -37275,25 +37277,21 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPromise", function() { return isPromise; });
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function isPromise(value) {
- return value && typeof value.subscribe !== 'function' && typeof value.then === 'function';
+ return !!value && typeof value.subscribe !== 'function' && typeof value.then === 'function';
}
//# sourceMappingURL=isPromise.js.map
/***/ }),
-/* 347 */
+/* 346 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; });
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(313);
-/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(312);
-/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(348);
-/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(354);
-/** PURE_IMPORTS_START _util_isScheduler,_of,_from,_operators_concatAll PURE_IMPORTS_END */
-
-
+/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(311);
+/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(347);
+/** PURE_IMPORTS_START _of,_operators_concatAll PURE_IMPORTS_END */
function concat() {
@@ -37301,249 +37299,19 @@ function concat() {
for (var _i = 0; _i < arguments.length; _i++) {
observables[_i] = arguments[_i];
}
- if (observables.length === 1 || (observables.length === 2 && Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_0__["isScheduler"])(observables[1]))) {
- return Object(_from__WEBPACK_IMPORTED_MODULE_2__["from"])(observables[0]);
- }
- return Object(_operators_concatAll__WEBPACK_IMPORTED_MODULE_3__["concatAll"])()(_of__WEBPACK_IMPORTED_MODULE_1__["of"].apply(void 0, observables));
+ return Object(_operators_concatAll__WEBPACK_IMPORTED_MODULE_1__["concatAll"])()(_of__WEBPACK_IMPORTED_MODULE_0__["of"].apply(void 0, observables));
}
//# sourceMappingURL=concat.js.map
/***/ }),
-/* 348 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "from", function() { return from; });
-/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(346);
-/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(345);
-/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(349);
-/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(350);
-/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(314);
-/* harmony import */ var _fromPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(351);
-/* harmony import */ var _fromIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(352);
-/* harmony import */ var _fromObservable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(353);
-/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(340);
-/** PURE_IMPORTS_START _Observable,_util_isPromise,_util_isArrayLike,_util_isInteropObservable,_util_isIterable,_fromArray,_fromPromise,_fromIterable,_fromObservable,_util_subscribeTo PURE_IMPORTS_END */
-
-
-
-
-
-
-
-
-
-
-function from(input, scheduler) {
- if (!scheduler) {
- if (input instanceof _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"]) {
- return input;
- }
- return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](Object(_util_subscribeTo__WEBPACK_IMPORTED_MODULE_9__["subscribeTo"])(input));
- }
- if (input != null) {
- if (Object(_util_isInteropObservable__WEBPACK_IMPORTED_MODULE_3__["isInteropObservable"])(input)) {
- return Object(_fromObservable__WEBPACK_IMPORTED_MODULE_8__["fromObservable"])(input, scheduler);
- }
- else if (Object(_util_isPromise__WEBPACK_IMPORTED_MODULE_1__["isPromise"])(input)) {
- return Object(_fromPromise__WEBPACK_IMPORTED_MODULE_6__["fromPromise"])(input, scheduler);
- }
- else if (Object(_util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__["isArrayLike"])(input)) {
- return Object(_fromArray__WEBPACK_IMPORTED_MODULE_5__["fromArray"])(input, scheduler);
- }
- else if (Object(_util_isIterable__WEBPACK_IMPORTED_MODULE_4__["isIterable"])(input) || typeof input === 'string') {
- return Object(_fromIterable__WEBPACK_IMPORTED_MODULE_7__["fromIterable"])(input, scheduler);
- }
- }
- throw new TypeError((input !== null && typeof input || input) + ' is not observable');
-}
-//# sourceMappingURL=from.js.map
-
-
-/***/ }),
-/* 349 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isInteropObservable", function() { return isInteropObservable; });
-/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(291);
-/** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */
-
-function isInteropObservable(input) {
- return input && typeof input[_symbol_observable__WEBPACK_IMPORTED_MODULE_0__["observable"]] === 'function';
-}
-//# sourceMappingURL=isInteropObservable.js.map
-
-
-/***/ }),
-/* 350 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isIterable", function() { return isIterable; });
-/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(343);
-/** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */
-
-function isIterable(input) {
- return input && typeof input[_symbol_iterator__WEBPACK_IMPORTED_MODULE_0__["iterator"]] === 'function';
-}
-//# sourceMappingURL=isIterable.js.map
-
-
-/***/ }),
-/* 351 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromPromise", function() { return fromPromise; });
-/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
-/* harmony import */ var _util_subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(341);
-/** PURE_IMPORTS_START _Observable,_Subscription,_util_subscribeToPromise PURE_IMPORTS_END */
-
-
-
-function fromPromise(input, scheduler) {
- if (!scheduler) {
- return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](Object(_util_subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__["subscribeToPromise"])(input));
- }
- else {
- return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
- var sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
- sub.add(scheduler.schedule(function () {
- return input.then(function (value) {
- sub.add(scheduler.schedule(function () {
- subscriber.next(value);
- sub.add(scheduler.schedule(function () { return subscriber.complete(); }));
- }));
- }, function (err) {
- sub.add(scheduler.schedule(function () { return subscriber.error(err); }));
- });
- }));
- return sub;
- });
- }
-}
-//# sourceMappingURL=fromPromise.js.map
-
-
-/***/ }),
-/* 352 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromIterable", function() { return fromIterable; });
-/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
-/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(343);
-/* harmony import */ var _util_subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(342);
-/** PURE_IMPORTS_START _Observable,_Subscription,_symbol_iterator,_util_subscribeToIterable PURE_IMPORTS_END */
-
-
-
-
-function fromIterable(input, scheduler) {
- if (!input) {
- throw new Error('Iterable cannot be null');
- }
- if (!scheduler) {
- return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](Object(_util_subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__["subscribeToIterable"])(input));
- }
- else {
- return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
- var sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
- var iterator;
- sub.add(function () {
- if (iterator && typeof iterator.return === 'function') {
- iterator.return();
- }
- });
- sub.add(scheduler.schedule(function () {
- iterator = input[_symbol_iterator__WEBPACK_IMPORTED_MODULE_2__["iterator"]]();
- sub.add(scheduler.schedule(function () {
- if (subscriber.closed) {
- return;
- }
- var value;
- var done;
- try {
- var result = iterator.next();
- value = result.value;
- done = result.done;
- }
- catch (err) {
- subscriber.error(err);
- return;
- }
- if (done) {
- subscriber.complete();
- }
- else {
- subscriber.next(value);
- this.schedule();
- }
- }));
- }));
- return sub;
- });
- }
-}
-//# sourceMappingURL=fromIterable.js.map
-
-
-/***/ }),
-/* 353 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromObservable", function() { return fromObservable; });
-/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
-/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(291);
-/* harmony import */ var _util_subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(344);
-/** PURE_IMPORTS_START _Observable,_Subscription,_symbol_observable,_util_subscribeToObservable PURE_IMPORTS_END */
-
-
-
-
-function fromObservable(input, scheduler) {
- if (!scheduler) {
- return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](Object(_util_subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__["subscribeToObservable"])(input));
- }
- else {
- return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
- var sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
- sub.add(scheduler.schedule(function () {
- var observable = input[_symbol_observable__WEBPACK_IMPORTED_MODULE_2__["observable"]]();
- sub.add(observable.subscribe({
- next: function (value) { sub.add(scheduler.schedule(function () { return subscriber.next(value); })); },
- error: function (err) { sub.add(scheduler.schedule(function () { return subscriber.error(err); })); },
- complete: function () { sub.add(scheduler.schedule(function () { return subscriber.complete(); })); },
- }));
- }));
- return sub;
- });
- }
-}
-//# sourceMappingURL=fromObservable.js.map
-
-
-/***/ }),
-/* 354 */
+/* 347 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return concatAll; });
-/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(355);
+/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(348);
/** PURE_IMPORTS_START _mergeAll PURE_IMPORTS_END */
function concatAll() {
@@ -37553,14 +37321,14 @@ function concatAll() {
/***/ }),
-/* 355 */
+/* 348 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return mergeAll; });
-/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(356);
-/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328);
+/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(349);
+/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(327);
/** PURE_IMPORTS_START _mergeMap,_util_identity PURE_IMPORTS_END */
@@ -37574,7 +37342,7 @@ function mergeAll(concurrent) {
/***/ }),
-/* 356 */
+/* 349 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -37583,11 +37351,13 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapOperator", function() { return MergeMapOperator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapSubscriber", function() { return MergeMapSubscriber; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(338);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
-/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334);
-/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(348);
-/** PURE_IMPORTS_START tslib,_util_subscribeToResult,_OuterSubscriber,_map,_observable_from PURE_IMPORTS_END */
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(336);
+/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(338);
+/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(333);
+/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(350);
+/** PURE_IMPORTS_START tslib,_util_subscribeToResult,_OuterSubscriber,_InnerSubscriber,_map,_observable_from PURE_IMPORTS_END */
+
@@ -37598,7 +37368,7 @@ function mergeMap(project, resultSelector, concurrent) {
concurrent = Number.POSITIVE_INFINITY;
}
if (typeof resultSelector === 'function') {
- return function (source) { return source.pipe(mergeMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_4__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_3__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); }, concurrent)); };
+ return function (source) { return source.pipe(mergeMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_5__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_4__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); }, concurrent)); };
}
else if (typeof resultSelector === 'number') {
concurrent = resultSelector;
@@ -37656,13 +37426,17 @@ var MergeMapSubscriber = /*@__PURE__*/ (function (_super) {
this._innerSub(result, value, index);
};
MergeMapSubscriber.prototype._innerSub = function (ish, value, index) {
- this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__["subscribeToResult"])(this, ish, value, index));
+ var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_3__["InnerSubscriber"](this, undefined, undefined);
+ var destination = this.destination;
+ destination.add(innerSubscriber);
+ Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__["subscribeToResult"])(this, ish, value, index, innerSubscriber);
};
MergeMapSubscriber.prototype._complete = function () {
this.hasCompleted = true;
if (this.active === 0 && this.buffer.length === 0) {
this.destination.complete();
}
+ this.unsubscribe();
};
MergeMapSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
this.destination.next(innerValue);
@@ -37684,6 +37458,230 @@ var MergeMapSubscriber = /*@__PURE__*/ (function (_super) {
//# sourceMappingURL=mergeMap.js.map
+/***/ }),
+/* 350 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "from", function() { return from; });
+/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
+/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(339);
+/* harmony import */ var _scheduled_scheduled__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(351);
+/** PURE_IMPORTS_START _Observable,_util_subscribeTo,_scheduled_scheduled PURE_IMPORTS_END */
+
+
+
+function from(input, scheduler) {
+ if (!scheduler) {
+ if (input instanceof _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"]) {
+ return input;
+ }
+ return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](Object(_util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__["subscribeTo"])(input));
+ }
+ else {
+ return Object(_scheduled_scheduled__WEBPACK_IMPORTED_MODULE_2__["scheduled"])(input, scheduler);
+ }
+}
+//# sourceMappingURL=from.js.map
+
+
+/***/ }),
+/* 351 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scheduled", function() { return scheduled; });
+/* harmony import */ var _scheduleObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(352);
+/* harmony import */ var _schedulePromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(353);
+/* harmony import */ var _scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(315);
+/* harmony import */ var _scheduleIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(354);
+/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(355);
+/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(345);
+/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(344);
+/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(356);
+/** PURE_IMPORTS_START _scheduleObservable,_schedulePromise,_scheduleArray,_scheduleIterable,_util_isInteropObservable,_util_isPromise,_util_isArrayLike,_util_isIterable PURE_IMPORTS_END */
+
+
+
+
+
+
+
+
+function scheduled(input, scheduler) {
+ if (input != null) {
+ if (Object(_util_isInteropObservable__WEBPACK_IMPORTED_MODULE_4__["isInteropObservable"])(input)) {
+ return Object(_scheduleObservable__WEBPACK_IMPORTED_MODULE_0__["scheduleObservable"])(input, scheduler);
+ }
+ else if (Object(_util_isPromise__WEBPACK_IMPORTED_MODULE_5__["isPromise"])(input)) {
+ return Object(_schedulePromise__WEBPACK_IMPORTED_MODULE_1__["schedulePromise"])(input, scheduler);
+ }
+ else if (Object(_util_isArrayLike__WEBPACK_IMPORTED_MODULE_6__["isArrayLike"])(input)) {
+ return Object(_scheduleArray__WEBPACK_IMPORTED_MODULE_2__["scheduleArray"])(input, scheduler);
+ }
+ else if (Object(_util_isIterable__WEBPACK_IMPORTED_MODULE_7__["isIterable"])(input) || typeof input === 'string') {
+ return Object(_scheduleIterable__WEBPACK_IMPORTED_MODULE_3__["scheduleIterable"])(input, scheduler);
+ }
+ }
+ throw new TypeError((input !== null && typeof input || input) + ' is not observable');
+}
+//# sourceMappingURL=scheduled.js.map
+
+
+/***/ }),
+/* 352 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scheduleObservable", function() { return scheduleObservable; });
+/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
+/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
+/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(290);
+/** PURE_IMPORTS_START _Observable,_Subscription,_symbol_observable PURE_IMPORTS_END */
+
+
+
+function scheduleObservable(input, scheduler) {
+ return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
+ var sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
+ sub.add(scheduler.schedule(function () {
+ var observable = input[_symbol_observable__WEBPACK_IMPORTED_MODULE_2__["observable"]]();
+ sub.add(observable.subscribe({
+ next: function (value) { sub.add(scheduler.schedule(function () { return subscriber.next(value); })); },
+ error: function (err) { sub.add(scheduler.schedule(function () { return subscriber.error(err); })); },
+ complete: function () { sub.add(scheduler.schedule(function () { return subscriber.complete(); })); },
+ }));
+ }));
+ return sub;
+ });
+}
+//# sourceMappingURL=scheduleObservable.js.map
+
+
+/***/ }),
+/* 353 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "schedulePromise", function() { return schedulePromise; });
+/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
+/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
+/** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */
+
+
+function schedulePromise(input, scheduler) {
+ return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
+ var sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
+ sub.add(scheduler.schedule(function () {
+ return input.then(function (value) {
+ sub.add(scheduler.schedule(function () {
+ subscriber.next(value);
+ sub.add(scheduler.schedule(function () { return subscriber.complete(); }));
+ }));
+ }, function (err) {
+ sub.add(scheduler.schedule(function () { return subscriber.error(err); }));
+ });
+ }));
+ return sub;
+ });
+}
+//# sourceMappingURL=schedulePromise.js.map
+
+
+/***/ }),
+/* 354 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scheduleIterable", function() { return scheduleIterable; });
+/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
+/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
+/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(342);
+/** PURE_IMPORTS_START _Observable,_Subscription,_symbol_iterator PURE_IMPORTS_END */
+
+
+
+function scheduleIterable(input, scheduler) {
+ if (!input) {
+ throw new Error('Iterable cannot be null');
+ }
+ return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
+ var sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
+ var iterator;
+ sub.add(function () {
+ if (iterator && typeof iterator.return === 'function') {
+ iterator.return();
+ }
+ });
+ sub.add(scheduler.schedule(function () {
+ iterator = input[_symbol_iterator__WEBPACK_IMPORTED_MODULE_2__["iterator"]]();
+ sub.add(scheduler.schedule(function () {
+ if (subscriber.closed) {
+ return;
+ }
+ var value;
+ var done;
+ try {
+ var result = iterator.next();
+ value = result.value;
+ done = result.done;
+ }
+ catch (err) {
+ subscriber.error(err);
+ return;
+ }
+ if (done) {
+ subscriber.complete();
+ }
+ else {
+ subscriber.next(value);
+ this.schedule();
+ }
+ }));
+ }));
+ return sub;
+ });
+}
+//# sourceMappingURL=scheduleIterable.js.map
+
+
+/***/ }),
+/* 355 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isInteropObservable", function() { return isInteropObservable; });
+/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(290);
+/** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */
+
+function isInteropObservable(input) {
+ return input && typeof input[_symbol_observable__WEBPACK_IMPORTED_MODULE_0__["observable"]] === 'function';
+}
+//# sourceMappingURL=isInteropObservable.js.map
+
+
+/***/ }),
+/* 356 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isIterable", function() { return isIterable; });
+/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(342);
+/** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */
+
+function isIterable(input) {
+ return input && typeof input[_symbol_iterator__WEBPACK_IMPORTED_MODULE_0__["iterator"]] === 'function';
+}
+//# sourceMappingURL=isIterable.js.map
+
+
/***/ }),
/* 357 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
@@ -37692,8 +37690,8 @@ var MergeMapSubscriber = /*@__PURE__*/ (function (_super) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return defer; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(348);
-/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311);
+/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(350);
+/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(310);
/** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */
@@ -37722,16 +37720,12 @@ function defer(observableFactory) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return forkJoin; });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276);
-/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285);
-/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(337);
-/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(334);
-/** PURE_IMPORTS_START tslib,_Observable,_util_isArray,_empty,_util_subscribeToResult,_OuterSubscriber,_operators_map PURE_IMPORTS_END */
-
-
+/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
+/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(285);
+/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(333);
+/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(286);
+/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(350);
+/** PURE_IMPORTS_START _Observable,_util_isArray,_operators_map,_util_isObject,_from PURE_IMPORTS_END */
@@ -37742,66 +37736,63 @@ function forkJoin() {
for (var _i = 0; _i < arguments.length; _i++) {
sources[_i] = arguments[_i];
}
- var resultSelector;
- if (typeof sources[sources.length - 1] === 'function') {
- resultSelector = sources.pop();
- }
- if (sources.length === 1 && Object(_util_isArray__WEBPACK_IMPORTED_MODULE_2__["isArray"])(sources[0])) {
- sources = sources[0];
- }
- if (sources.length === 0) {
- return _empty__WEBPACK_IMPORTED_MODULE_3__["EMPTY"];
+ if (sources.length === 1) {
+ var first_1 = sources[0];
+ if (Object(_util_isArray__WEBPACK_IMPORTED_MODULE_1__["isArray"])(first_1)) {
+ return forkJoinInternal(first_1, null);
+ }
+ if (Object(_util_isObject__WEBPACK_IMPORTED_MODULE_3__["isObject"])(first_1) && Object.getPrototypeOf(first_1) === Object.prototype) {
+ var keys = Object.keys(first_1);
+ return forkJoinInternal(keys.map(function (key) { return first_1[key]; }), keys);
+ }
}
- if (resultSelector) {
- return forkJoin(sources).pipe(Object(_operators_map__WEBPACK_IMPORTED_MODULE_6__["map"])(function (args) { return resultSelector.apply(void 0, args); }));
+ if (typeof sources[sources.length - 1] === 'function') {
+ var resultSelector_1 = sources.pop();
+ sources = (sources.length === 1 && Object(_util_isArray__WEBPACK_IMPORTED_MODULE_1__["isArray"])(sources[0])) ? sources[0] : sources;
+ return forkJoinInternal(sources, null).pipe(Object(_operators_map__WEBPACK_IMPORTED_MODULE_2__["map"])(function (args) { return resultSelector_1.apply(void 0, args); }));
}
- return new _Observable__WEBPACK_IMPORTED_MODULE_1__["Observable"](function (subscriber) {
- return new ForkJoinSubscriber(subscriber, sources);
- });
+ return forkJoinInternal(sources, null);
}
-var ForkJoinSubscriber = /*@__PURE__*/ (function (_super) {
- tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](ForkJoinSubscriber, _super);
- function ForkJoinSubscriber(destination, sources) {
- var _this = _super.call(this, destination) || this;
- _this.sources = sources;
- _this.completed = 0;
- _this.haveValues = 0;
+function forkJoinInternal(sources, keys) {
+ return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
var len = sources.length;
- _this.values = new Array(len);
- for (var i = 0; i < len; i++) {
- var source = sources[i];
- var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(_this, source, null, i);
- if (innerSubscription) {
- _this.add(innerSubscription);
- }
- }
- return _this;
- }
- ForkJoinSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
- this.values[outerIndex] = innerValue;
- if (!innerSub._hasValue) {
- innerSub._hasValue = true;
- this.haveValues++;
- }
- };
- ForkJoinSubscriber.prototype.notifyComplete = function (innerSub) {
- var _a = this, destination = _a.destination, haveValues = _a.haveValues, values = _a.values;
- var len = values.length;
- if (!innerSub._hasValue) {
- destination.complete();
- return;
- }
- this.completed++;
- if (this.completed !== len) {
+ if (len === 0) {
+ subscriber.complete();
return;
}
- if (haveValues === len) {
- destination.next(values);
+ var values = new Array(len);
+ var completed = 0;
+ var emitted = 0;
+ var _loop_1 = function (i) {
+ var source = Object(_from__WEBPACK_IMPORTED_MODULE_4__["from"])(sources[i]);
+ var hasValue = false;
+ subscriber.add(source.subscribe({
+ next: function (value) {
+ if (!hasValue) {
+ hasValue = true;
+ emitted++;
+ }
+ values[i] = value;
+ },
+ error: function (err) { return subscriber.error(err); },
+ complete: function () {
+ completed++;
+ if (completed === len || !hasValue) {
+ if (emitted === len) {
+ subscriber.next(keys ?
+ keys.reduce(function (result, key, i) { return (result[key] = values[i], result); }, {}) :
+ values);
+ }
+ subscriber.complete();
+ }
+ }
+ }));
+ };
+ for (var i = 0; i < len; i++) {
+ _loop_1(i);
}
- destination.complete();
- };
- return ForkJoinSubscriber;
-}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__["OuterSubscriber"]));
+ });
+}
//# sourceMappingURL=forkJoin.js.map
@@ -37815,13 +37806,13 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(285);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(280);
-/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334);
+/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(333);
/** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */
-var toString = Object.prototype.toString;
+var toString = /*@__PURE__*/ (function () { return Object.prototype.toString; })();
function fromEvent(target, eventName, options, resultSelector) {
if (Object(_util_isFunction__WEBPACK_IMPORTED_MODULE_2__["isFunction"])(options)) {
resultSelector = options;
@@ -37891,7 +37882,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(285);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(280);
-/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334);
+/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(333);
/** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */
@@ -37934,8 +37925,8 @@ function fromEventPattern(addHandler, removeHandler, resultSelector) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return generate; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(313);
+/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(327);
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(312);
/** PURE_IMPORTS_START _Observable,_util_identity,_util_isScheduler PURE_IMPORTS_END */
@@ -38071,7 +38062,7 @@ function dispatch(state) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return iif; });
/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(357);
-/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(311);
+/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(310);
/** PURE_IMPORTS_START _defer,_empty PURE_IMPORTS_END */
@@ -38095,7 +38086,7 @@ function iif(condition, trueResult, falseResult) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return interval; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(322);
/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(364);
/** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric PURE_IMPORTS_END */
@@ -38151,9 +38142,9 @@ function isNumeric(val) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return merge; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313);
-/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(355);
-/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(314);
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(312);
+/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(348);
+/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(313);
/** PURE_IMPORTS_START _Observable,_util_isScheduler,_operators_mergeAll,_fromArray PURE_IMPORTS_END */
@@ -38193,7 +38184,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return NEVER; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "never", function() { return never; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(293);
+/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(292);
/** PURE_IMPORTS_START _Observable,_util_noop PURE_IMPORTS_END */
@@ -38212,9 +38203,9 @@ function never() {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(348);
+/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(350);
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285);
-/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311);
+/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(310);
/** PURE_IMPORTS_START _Observable,_from,_util_isArray,_empty PURE_IMPORTS_END */
@@ -38299,6 +38290,104 @@ function dispatch(state) {
/* 369 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return partition; });
+/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(370);
+/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(339);
+/* harmony import */ var _operators_filter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(371);
+/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(276);
+/** PURE_IMPORTS_START _util_not,_util_subscribeTo,_operators_filter,_Observable PURE_IMPORTS_END */
+
+
+
+
+function partition(source, predicate, thisArg) {
+ return [
+ Object(_operators_filter__WEBPACK_IMPORTED_MODULE_2__["filter"])(predicate, thisArg)(new _Observable__WEBPACK_IMPORTED_MODULE_3__["Observable"](Object(_util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__["subscribeTo"])(source))),
+ Object(_operators_filter__WEBPACK_IMPORTED_MODULE_2__["filter"])(Object(_util_not__WEBPACK_IMPORTED_MODULE_0__["not"])(predicate, thisArg))(new _Observable__WEBPACK_IMPORTED_MODULE_3__["Observable"](Object(_util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__["subscribeTo"])(source)))
+ ];
+}
+//# sourceMappingURL=partition.js.map
+
+
+/***/ }),
+/* 370 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "not", function() { return not; });
+/** PURE_IMPORTS_START PURE_IMPORTS_END */
+function not(pred, thisArg) {
+ function notPred() {
+ return !(notPred.pred.apply(notPred.thisArg, arguments));
+ }
+ notPred.pred = pred;
+ notPred.thisArg = thisArg;
+ return notPred;
+}
+//# sourceMappingURL=not.js.map
+
+
+/***/ }),
+/* 371 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return filter; });
+/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
+/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
+/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
+
+
+function filter(predicate, thisArg) {
+ return function filterOperatorFunction(source) {
+ return source.lift(new FilterOperator(predicate, thisArg));
+ };
+}
+var FilterOperator = /*@__PURE__*/ (function () {
+ function FilterOperator(predicate, thisArg) {
+ this.predicate = predicate;
+ this.thisArg = thisArg;
+ }
+ FilterOperator.prototype.call = function (subscriber, source) {
+ return source.subscribe(new FilterSubscriber(subscriber, this.predicate, this.thisArg));
+ };
+ return FilterOperator;
+}());
+var FilterSubscriber = /*@__PURE__*/ (function (_super) {
+ tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](FilterSubscriber, _super);
+ function FilterSubscriber(destination, predicate, thisArg) {
+ var _this = _super.call(this, destination) || this;
+ _this.predicate = predicate;
+ _this.thisArg = thisArg;
+ _this.count = 0;
+ return _this;
+ }
+ FilterSubscriber.prototype._next = function (value) {
+ var result;
+ try {
+ result = this.predicate.call(this.thisArg, value, this.count++);
+ }
+ catch (err) {
+ this.destination.error(err);
+ return;
+ }
+ if (result) {
+ this.destination.next(value);
+ }
+ };
+ return FilterSubscriber;
+}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"]));
+//# sourceMappingURL=filter.js.map
+
+
+/***/ }),
+/* 372 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; });
@@ -38306,9 +38395,9 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RaceSubscriber", function() { return RaceSubscriber; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(285);
-/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(314);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338);
+/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(313);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_util_isArray,_fromArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -38390,7 +38479,7 @@ var RaceSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 370 */
+/* 373 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -38404,10 +38493,11 @@ function range(start, count, scheduler) {
if (start === void 0) {
start = 0;
}
- if (count === void 0) {
- count = 0;
- }
return new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) {
+ if (count === undefined) {
+ count = start;
+ start = 0;
+ }
var index = 0;
var current = start;
if (scheduler) {
@@ -38448,16 +38538,16 @@ function dispatch(state) {
/***/ }),
-/* 371 */
+/* 374 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return timer; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(322);
/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(364);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(313);
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(312);
/** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */
@@ -38502,15 +38592,15 @@ function dispatch(state) {
/***/ }),
-/* 372 */
+/* 375 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "using", function() { return using; });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276);
-/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(348);
-/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311);
+/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(350);
+/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(310);
/** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */
@@ -38547,7 +38637,7 @@ function using(resourceFactory, observableFactory) {
/***/ }),
-/* 373 */
+/* 376 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -38556,12 +38646,12 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipOperator", function() { return ZipOperator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipSubscriber", function() { return ZipSubscriber; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(314);
+/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313);
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338);
-/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(343);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(337);
+/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(342);
/** PURE_IMPORTS_START tslib,_fromArray,_util_isArray,_Subscriber,_OuterSubscriber,_util_subscribeToResult,_.._internal_symbol_iterator PURE_IMPORTS_END */
@@ -38619,6 +38709,7 @@ var ZipSubscriber = /*@__PURE__*/ (function (_super) {
ZipSubscriber.prototype._complete = function () {
var iterators = this.iterators;
var len = iterators.length;
+ this.unsubscribe();
if (len === 0) {
this.destination.complete();
return;
@@ -38627,7 +38718,8 @@ var ZipSubscriber = /*@__PURE__*/ (function (_super) {
for (var i = 0; i < len; i++) {
var iterator = iterators[i];
if (iterator.stillUnsubscribed) {
- this.add(iterator.subscribe(iterator, i));
+ var destination = this.destination;
+ destination.add(iterator.subscribe(iterator, i));
}
else {
this.active--;
@@ -38781,173 +38873,173 @@ var ZipBufferIterator = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 374 */
+/* 377 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(375);
+/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(378);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__["audit"]; });
-/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(376);
+/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(379);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__["auditTime"]; });
-/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(377);
+/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(380);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__["buffer"]; });
-/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(378);
+/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(381);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__["bufferCount"]; });
-/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(379);
+/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(382);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__["bufferTime"]; });
-/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(380);
+/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(383);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__["bufferToggle"]; });
-/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(381);
+/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(384);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__["bufferWhen"]; });
-/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(382);
+/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(385);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__["catchError"]; });
-/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(383);
+/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(386);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__["combineAll"]; });
-/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(384);
+/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(387);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__["combineLatest"]; });
-/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(385);
+/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(388);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__["concat"]; });
-/* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(354);
+/* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(347);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__["concatAll"]; });
-/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(386);
+/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(389);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__["concatMap"]; });
-/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(387);
+/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(390);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__["concatMapTo"]; });
-/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(388);
+/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(391);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "count", function() { return _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__["count"]; });
-/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(389);
+/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(392);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__["debounce"]; });
-/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(390);
+/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(393);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__["debounceTime"]; });
-/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(391);
+/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(394);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__["defaultIfEmpty"]; });
-/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(392);
+/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(395);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__["delay"]; });
-/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(394);
+/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(397);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__["delayWhen"]; });
-/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(395);
+/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(398);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__["dematerialize"]; });
-/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(396);
+/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(399);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__["distinct"]; });
-/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(397);
+/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(400);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__["distinctUntilChanged"]; });
-/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(398);
+/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(401);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__["distinctUntilKeyChanged"]; });
-/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(399);
+/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(402);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__["elementAt"]; });
-/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(404);
+/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(405);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__["endWith"]; });
-/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(405);
+/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(406);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "every", function() { return _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__["every"]; });
-/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(406);
+/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(407);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__["exhaust"]; });
-/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(407);
+/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(408);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__["exhaustMap"]; });
-/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(408);
+/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(409);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__["expand"]; });
-/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(400);
+/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(371);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__["filter"]; });
-/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(409);
+/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(410);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__["finalize"]; });
-/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(410);
+/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(411);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "find", function() { return _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__["find"]; });
-/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(411);
+/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(412);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__["findIndex"]; });
-/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(412);
+/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(413);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "first", function() { return _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__["first"]; });
-/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(299);
+/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(298);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__["groupBy"]; });
-/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(413);
+/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(414);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__["ignoreElements"]; });
-/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(414);
+/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(415);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__["isEmpty"]; });
-/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(415);
+/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(416);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "last", function() { return _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__["last"]; });
-/* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(334);
+/* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(333);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "map", function() { return _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__["map"]; });
-/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(417);
+/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(418);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__["mapTo"]; });
-/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(418);
+/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(419);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__["materialize"]; });
-/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(419);
+/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(420);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "max", function() { return _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__["max"]; });
-/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(422);
+/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(423);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__["merge"]; });
-/* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(355);
+/* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(348);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__["mergeAll"]; });
-/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(356);
+/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(349);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["mergeMap"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["mergeMap"]; });
-/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(423);
+/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(424);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__["mergeMapTo"]; });
-/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(424);
+/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(425);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__["mergeScan"]; });
-/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(425);
+/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(426);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "min", function() { return _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__["min"]; });
-/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(426);
+/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(427);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__["multicast"]; });
-/* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(309);
+/* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(308);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observeOn", function() { return _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__["observeOn"]; });
-/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(427);
+/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(428);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__["onErrorResumeNext"]; });
-/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(428);
+/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(429);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__["pairwise"]; });
-/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(429);
+/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(430);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__["partition"]; });
/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(431);
@@ -38968,7 +39060,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(436);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__["race"]; });
-/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(420);
+/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(421);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__["reduce"]; });
/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(437);
@@ -38983,7 +39075,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(440);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__["retryWhen"]; });
-/* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(298);
+/* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(297);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__["refCount"]; });
/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(441);
@@ -38992,7 +39084,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(442);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__["sampleTime"]; });
-/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(421);
+/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(422);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__["scan"]; });
/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(443);
@@ -39034,10 +39126,10 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(456);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__["switchMapTo"]; });
-/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(403);
+/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(404);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "take", function() { return _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__["take"]; });
-/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(416);
+/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(417);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__["takeLast"]; });
/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(457);
@@ -39046,55 +39138,55 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(458);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__["takeWhile"]; });
-/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(402);
+/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(459);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__["tap"]; });
-/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(459);
+/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(460);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__["throttle"]; });
-/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(460);
+/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(461);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__["throttleTime"]; });
-/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(401);
+/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(403);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__["throwIfEmpty"]; });
-/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(461);
+/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(462);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__["timeInterval"]; });
-/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(462);
+/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(463);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__["timeout"]; });
-/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(463);
+/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(464);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__["timeoutWith"]; });
-/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(464);
+/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(465);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__["timestamp"]; });
-/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(465);
+/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(466);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__["toArray"]; });
-/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(466);
+/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(467);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "window", function() { return _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__["window"]; });
-/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(467);
+/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(468);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__["windowCount"]; });
-/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(468);
+/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(469);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__["windowTime"]; });
-/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(469);
+/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(470);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__["windowToggle"]; });
-/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(470);
+/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(471);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__["windowWhen"]; });
-/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(471);
+/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(472);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__["withLatestFrom"]; });
-/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(472);
+/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(473);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__["zip"]; });
-/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(473);
+/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(474);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__["zipAll"]; });
/** PURE_IMPORTS_START PURE_IMPORTS_END */
@@ -39206,20 +39298,16 @@ __webpack_require__.r(__webpack_exports__);
/***/ }),
-/* 375 */
+/* 378 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return audit; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(288);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
-
-
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -39249,18 +39337,20 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) {
this.value = value;
this.hasValue = true;
if (!this.throttled) {
- var duration = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_1__["tryCatch"])(this.durationSelector)(value);
- if (duration === _util_errorObject__WEBPACK_IMPORTED_MODULE_2__["errorObject"]) {
- this.destination.error(_util_errorObject__WEBPACK_IMPORTED_MODULE_2__["errorObject"].e);
+ var duration = void 0;
+ try {
+ var durationSelector = this.durationSelector;
+ duration = durationSelector(value);
+ }
+ catch (err) {
+ return this.destination.error(err);
+ }
+ var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, duration);
+ if (!innerSubscription || innerSubscription.closed) {
+ this.clearThrottle();
}
else {
- var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(this, duration);
- if (!innerSubscription || innerSubscription.closed) {
- this.clearThrottle();
- }
- else {
- this.add(this.throttled = innerSubscription);
- }
+ this.add(this.throttled = innerSubscription);
}
}
};
@@ -39284,20 +39374,20 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) {
this.clearThrottle();
};
return AuditSubscriber;
-}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__["OuterSubscriber"]));
+}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"]));
//# sourceMappingURL=audit.js.map
/***/ }),
-/* 376 */
+/* 379 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return auditTime; });
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(323);
-/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(375);
-/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(371);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(322);
+/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(378);
+/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(374);
/** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */
@@ -39312,15 +39402,15 @@ function auditTime(duration, scheduler) {
/***/ }),
-/* 377 */
+/* 380 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return buffer; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -39361,7 +39451,7 @@ var BufferSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 378 */
+/* 381 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -39462,16 +39552,16 @@ var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 379 */
+/* 382 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return bufferTime; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(322);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(278);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(313);
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(312);
/** PURE_IMPORTS_START tslib,_scheduler_async,_Subscriber,_util_isScheduler PURE_IMPORTS_END */
@@ -39623,7 +39713,7 @@ function dispatchBufferClose(arg) {
/***/ }),
-/* 380 */
+/* 383 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -39631,8 +39721,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return bufferToggle; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(336);
/** PURE_IMPORTS_START tslib,_Subscription,_util_subscribeToResult,_OuterSubscriber PURE_IMPORTS_END */
@@ -39743,7 +39833,7 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 381 */
+/* 384 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -39751,13 +39841,9 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return bufferWhen; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_Subscription,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
-
-
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_Subscription,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -39821,35 +39907,39 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) {
this.destination.next(buffer);
}
this.buffer = [];
- var closingNotifier = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_2__["tryCatch"])(this.closingSelector)();
- if (closingNotifier === _util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"]) {
- this.error(_util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"].e);
+ var closingNotifier;
+ try {
+ var closingSelector = this.closingSelector;
+ closingNotifier = closingSelector();
}
- else {
- closingSubscription = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
- this.closingSubscription = closingSubscription;
- this.add(closingSubscription);
- this.subscribing = true;
- closingSubscription.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__["subscribeToResult"])(this, closingNotifier));
- this.subscribing = false;
+ catch (err) {
+ return this.error(err);
}
+ closingSubscription = new _Subscription__WEBPACK_IMPORTED_MODULE_1__["Subscription"]();
+ this.closingSubscription = closingSubscription;
+ this.add(closingSubscription);
+ this.subscribing = true;
+ closingSubscription.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, closingNotifier));
+ this.subscribing = false;
};
return BufferWhenSubscriber;
-}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__["OuterSubscriber"]));
+}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"]));
//# sourceMappingURL=bufferWhen.js.map
/***/ }),
-/* 382 */
+/* 385 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return catchError; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
+
@@ -39888,7 +39978,9 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) {
return;
}
this._unsubscribeAndRecycle();
- this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, result));
+ var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__["InnerSubscriber"](this, undefined, undefined);
+ this.add(innerSubscriber);
+ Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, result, undefined, undefined, innerSubscriber);
}
};
return CatchSubscriber;
@@ -39897,13 +39989,13 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 383 */
+/* 386 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return combineAll; });
-/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(336);
+/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(335);
/** PURE_IMPORTS_START _observable_combineLatest PURE_IMPORTS_END */
function combineAll(project) {
@@ -39913,15 +40005,15 @@ function combineAll(project) {
/***/ }),
-/* 384 */
+/* 387 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return combineLatest; });
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285);
-/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
-/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(348);
+/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(335);
+/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(350);
/** PURE_IMPORTS_START _util_isArray,_observable_combineLatest,_observable_from PURE_IMPORTS_END */
@@ -39945,13 +40037,13 @@ function combineLatest() {
/***/ }),
-/* 385 */
+/* 388 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; });
-/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(347);
+/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(346);
/** PURE_IMPORTS_START _observable_concat PURE_IMPORTS_END */
function concat() {
@@ -39965,13 +40057,13 @@ function concat() {
/***/ }),
-/* 386 */
+/* 389 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return concatMap; });
-/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(356);
+/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(349);
/** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */
function concatMap(project, resultSelector) {
@@ -39981,13 +40073,13 @@ function concatMap(project, resultSelector) {
/***/ }),
-/* 387 */
+/* 390 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return concatMapTo; });
-/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(386);
+/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(389);
/** PURE_IMPORTS_START _concatMap PURE_IMPORTS_END */
function concatMapTo(innerObservable, resultSelector) {
@@ -39997,7 +40089,7 @@ function concatMapTo(innerObservable, resultSelector) {
/***/ }),
-/* 388 */
+/* 391 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40062,15 +40154,15 @@ var CountSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 389 */
+/* 392 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return debounce; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -40150,7 +40242,7 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 390 */
+/* 393 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40158,7 +40250,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return debounceTime; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(323);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(322);
/** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */
@@ -40226,7 +40318,7 @@ function dispatchNext(subscriber) {
/***/ }),
-/* 391 */
+/* 394 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40276,17 +40368,17 @@ var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 392 */
+/* 395 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return delay; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323);
-/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(393);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(322);
+/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(396);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278);
-/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(310);
+/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(309);
/** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */
@@ -40341,7 +40433,8 @@ var DelaySubscriber = /*@__PURE__*/ (function (_super) {
};
DelaySubscriber.prototype._schedule = function (scheduler) {
this.active = true;
- this.add(scheduler.schedule(DelaySubscriber.dispatch, this.delay, {
+ var destination = this.destination;
+ destination.add(scheduler.schedule(DelaySubscriber.dispatch, this.delay, {
source: this, destination: this.destination, scheduler: scheduler
}));
};
@@ -40363,9 +40456,11 @@ var DelaySubscriber = /*@__PURE__*/ (function (_super) {
this.errored = true;
this.queue = [];
this.destination.error(err);
+ this.unsubscribe();
};
DelaySubscriber.prototype._complete = function () {
this.scheduleNotification(_Notification__WEBPACK_IMPORTED_MODULE_4__["Notification"].createComplete());
+ this.unsubscribe();
};
return DelaySubscriber;
}(_Subscriber__WEBPACK_IMPORTED_MODULE_3__["Subscriber"]));
@@ -40380,7 +40475,7 @@ var DelayMessage = /*@__PURE__*/ (function () {
/***/ }),
-/* 393 */
+/* 396 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40394,7 +40489,7 @@ function isDate(value) {
/***/ }),
-/* 394 */
+/* 397 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40403,8 +40498,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -40436,6 +40531,7 @@ var DelayWhenSubscriber = /*@__PURE__*/ (function (_super) {
_this.delayDurationSelector = delayDurationSelector;
_this.completed = false;
_this.delayNotifierSubscriptions = [];
+ _this.index = 0;
return _this;
}
DelayWhenSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
@@ -40454,8 +40550,9 @@ var DelayWhenSubscriber = /*@__PURE__*/ (function (_super) {
this.tryComplete();
};
DelayWhenSubscriber.prototype._next = function (value) {
+ var index = this.index++;
try {
- var delayNotifier = this.delayDurationSelector(value);
+ var delayNotifier = this.delayDurationSelector(value, index);
if (delayNotifier) {
this.tryDelay(delayNotifier, value);
}
@@ -40467,6 +40564,7 @@ var DelayWhenSubscriber = /*@__PURE__*/ (function (_super) {
DelayWhenSubscriber.prototype._complete = function () {
this.completed = true;
this.tryComplete();
+ this.unsubscribe();
};
DelayWhenSubscriber.prototype.removeSubscription = function (subscription) {
subscription.unsubscribe();
@@ -40479,7 +40577,8 @@ var DelayWhenSubscriber = /*@__PURE__*/ (function (_super) {
DelayWhenSubscriber.prototype.tryDelay = function (delayNotifier, value) {
var notifierSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(this, delayNotifier, value);
if (notifierSubscription && !notifierSubscription.closed) {
- this.add(notifierSubscription);
+ var destination = this.destination;
+ destination.add(notifierSubscription);
this.delayNotifierSubscriptions.push(notifierSubscription);
}
};
@@ -40520,6 +40619,7 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) {
this.parent.error(err);
};
SubscriptionDelaySubscriber.prototype._complete = function () {
+ this.unsubscribe();
this.subscribeToSource();
};
SubscriptionDelaySubscriber.prototype.subscribeToSource = function () {
@@ -40535,7 +40635,7 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 395 */
+/* 398 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40573,7 +40673,7 @@ var DeMaterializeSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 396 */
+/* 399 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40581,8 +40681,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return distinct; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DistinctSubscriber", function() { return DistinctSubscriber; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -40651,7 +40751,7 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 397 */
+/* 400 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40659,11 +40759,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return distinctUntilChanged; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288);
-/** PURE_IMPORTS_START tslib,_Subscriber,_util_tryCatch,_util_errorObject PURE_IMPORTS_END */
-
-
+/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function distinctUntilChanged(compare, keySelector) {
@@ -40694,25 +40790,28 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) {
return x === y;
};
DistinctUntilChangedSubscriber.prototype._next = function (value) {
- var keySelector = this.keySelector;
- var key = value;
- if (keySelector) {
- key = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_2__["tryCatch"])(this.keySelector)(value);
- if (key === _util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"]) {
- return this.destination.error(_util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"].e);
- }
+ var key;
+ try {
+ var keySelector = this.keySelector;
+ key = keySelector ? keySelector(value) : value;
+ }
+ catch (err) {
+ return this.destination.error(err);
}
var result = false;
if (this.hasKey) {
- result = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_2__["tryCatch"])(this.compare)(this.key, key);
- if (result === _util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"]) {
- return this.destination.error(_util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"].e);
+ try {
+ var compare = this.compare;
+ result = compare(this.key, key);
+ }
+ catch (err) {
+ return this.destination.error(err);
}
}
else {
this.hasKey = true;
}
- if (Boolean(result) === false) {
+ if (!result) {
this.key = key;
this.destination.next(value);
}
@@ -40723,13 +40822,13 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 398 */
+/* 401 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return distinctUntilKeyChanged; });
-/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(397);
+/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(400);
/** PURE_IMPORTS_START _distinctUntilChanged PURE_IMPORTS_END */
function distinctUntilKeyChanged(key, compare) {
@@ -40739,17 +40838,17 @@ function distinctUntilKeyChanged(key, compare) {
/***/ }),
-/* 399 */
+/* 402 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return elementAt; });
-/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(330);
-/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(400);
-/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(401);
-/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(391);
-/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(403);
+/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(329);
+/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(371);
+/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(403);
+/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(394);
+/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(404);
/** PURE_IMPORTS_START _util_ArgumentOutOfRangeError,_filter,_throwIfEmpty,_defaultIfEmpty,_take PURE_IMPORTS_END */
@@ -40771,181 +40870,73 @@ function elementAt(index, defaultValue) {
/***/ }),
-/* 400 */
+/* 403 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return filter; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return throwIfEmpty; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
-
-
-function filter(predicate, thisArg) {
- return function filterOperatorFunction(source) {
- return source.lift(new FilterOperator(predicate, thisArg));
- };
-}
-var FilterOperator = /*@__PURE__*/ (function () {
- function FilterOperator(predicate, thisArg) {
- this.predicate = predicate;
- this.thisArg = thisArg;
- }
- FilterOperator.prototype.call = function (subscriber, source) {
- return source.subscribe(new FilterSubscriber(subscriber, this.predicate, this.thisArg));
- };
- return FilterOperator;
-}());
-var FilterSubscriber = /*@__PURE__*/ (function (_super) {
- tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](FilterSubscriber, _super);
- function FilterSubscriber(destination, predicate, thisArg) {
- var _this = _super.call(this, destination) || this;
- _this.predicate = predicate;
- _this.thisArg = thisArg;
- _this.count = 0;
- return _this;
- }
- FilterSubscriber.prototype._next = function (value) {
- var result;
- try {
- result = this.predicate.call(this.thisArg, value, this.count++);
- }
- catch (err) {
- this.destination.error(err);
- return;
- }
- if (result) {
- this.destination.next(value);
- }
- };
- return FilterSubscriber;
-}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"]));
-//# sourceMappingURL=filter.js.map
-
-
-/***/ }),
-/* 401 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
+/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(330);
+/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(278);
+/** PURE_IMPORTS_START tslib,_util_EmptyError,_Subscriber PURE_IMPORTS_END */
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return throwIfEmpty; });
-/* harmony import */ var _tap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(402);
-/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(331);
-/** PURE_IMPORTS_START _tap,_util_EmptyError PURE_IMPORTS_END */
-var throwIfEmpty = function (errorFactory) {
+function throwIfEmpty(errorFactory) {
if (errorFactory === void 0) {
errorFactory = defaultErrorFactory;
}
- return Object(_tap__WEBPACK_IMPORTED_MODULE_0__["tap"])({
- hasValue: false,
- next: function () { this.hasValue = true; },
- complete: function () {
- if (!this.hasValue) {
- throw errorFactory();
- }
- }
- });
-};
-function defaultErrorFactory() {
- return new _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__["EmptyError"]();
-}
-//# sourceMappingURL=throwIfEmpty.js.map
-
-
-/***/ }),
-/* 402 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return tap; });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(293);
-/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(280);
-/** PURE_IMPORTS_START tslib,_Subscriber,_util_noop,_util_isFunction PURE_IMPORTS_END */
-
-
-
-
-function tap(nextOrObserver, error, complete) {
- return function tapOperatorFunction(source) {
- return source.lift(new DoOperator(nextOrObserver, error, complete));
+ return function (source) {
+ return source.lift(new ThrowIfEmptyOperator(errorFactory));
};
}
-var DoOperator = /*@__PURE__*/ (function () {
- function DoOperator(nextOrObserver, error, complete) {
- this.nextOrObserver = nextOrObserver;
- this.error = error;
- this.complete = complete;
+var ThrowIfEmptyOperator = /*@__PURE__*/ (function () {
+ function ThrowIfEmptyOperator(errorFactory) {
+ this.errorFactory = errorFactory;
}
- DoOperator.prototype.call = function (subscriber, source) {
- return source.subscribe(new TapSubscriber(subscriber, this.nextOrObserver, this.error, this.complete));
+ ThrowIfEmptyOperator.prototype.call = function (subscriber, source) {
+ return source.subscribe(new ThrowIfEmptySubscriber(subscriber, this.errorFactory));
};
- return DoOperator;
+ return ThrowIfEmptyOperator;
}());
-var TapSubscriber = /*@__PURE__*/ (function (_super) {
- tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](TapSubscriber, _super);
- function TapSubscriber(destination, observerOrNext, error, complete) {
+var ThrowIfEmptySubscriber = /*@__PURE__*/ (function (_super) {
+ tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](ThrowIfEmptySubscriber, _super);
+ function ThrowIfEmptySubscriber(destination, errorFactory) {
var _this = _super.call(this, destination) || this;
- _this._tapNext = _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
- _this._tapError = _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
- _this._tapComplete = _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
- _this._tapError = error || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
- _this._tapComplete = complete || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
- if (Object(_util_isFunction__WEBPACK_IMPORTED_MODULE_3__["isFunction"])(observerOrNext)) {
- _this._context = _this;
- _this._tapNext = observerOrNext;
- }
- else if (observerOrNext) {
- _this._context = observerOrNext;
- _this._tapNext = observerOrNext.next || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
- _this._tapError = observerOrNext.error || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
- _this._tapComplete = observerOrNext.complete || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
- }
+ _this.errorFactory = errorFactory;
+ _this.hasValue = false;
return _this;
}
- TapSubscriber.prototype._next = function (value) {
- try {
- this._tapNext.call(this._context, value);
- }
- catch (err) {
- this.destination.error(err);
- return;
- }
+ ThrowIfEmptySubscriber.prototype._next = function (value) {
+ this.hasValue = true;
this.destination.next(value);
};
- TapSubscriber.prototype._error = function (err) {
- try {
- this._tapError.call(this._context, err);
- }
- catch (err) {
+ ThrowIfEmptySubscriber.prototype._complete = function () {
+ if (!this.hasValue) {
+ var err = void 0;
+ try {
+ err = this.errorFactory();
+ }
+ catch (e) {
+ err = e;
+ }
this.destination.error(err);
- return;
}
- this.destination.error(err);
- };
- TapSubscriber.prototype._complete = function () {
- try {
- this._tapComplete.call(this._context);
- }
- catch (err) {
- this.destination.error(err);
- return;
+ else {
+ return this.destination.complete();
}
- return this.destination.complete();
};
- return TapSubscriber;
-}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"]));
-//# sourceMappingURL=tap.js.map
+ return ThrowIfEmptySubscriber;
+}(_Subscriber__WEBPACK_IMPORTED_MODULE_2__["Subscriber"]));
+function defaultErrorFactory() {
+ return new _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__["EmptyError"]();
+}
+//# sourceMappingURL=throwIfEmpty.js.map
/***/ }),
-/* 403 */
+/* 404 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40953,8 +40944,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "take", function() { return take; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(330);
-/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311);
+/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(329);
+/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(310);
/** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */
@@ -41007,21 +40998,15 @@ var TakeSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 404 */
+/* 405 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return endWith; });
-/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(314);
-/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(316);
-/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311);
-/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(347);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(313);
-/** PURE_IMPORTS_START _observable_fromArray,_observable_scalar,_observable_empty,_observable_concat,_util_isScheduler PURE_IMPORTS_END */
-
-
-
+/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(346);
+/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(311);
+/** PURE_IMPORTS_START _observable_concat,_observable_of PURE_IMPORTS_END */
function endWith() {
@@ -41029,31 +41014,13 @@ function endWith() {
for (var _i = 0; _i < arguments.length; _i++) {
array[_i] = arguments[_i];
}
- return function (source) {
- var scheduler = array[array.length - 1];
- if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_4__["isScheduler"])(scheduler)) {
- array.pop();
- }
- else {
- scheduler = null;
- }
- var len = array.length;
- if (len === 1 && !scheduler) {
- return Object(_observable_concat__WEBPACK_IMPORTED_MODULE_3__["concat"])(source, Object(_observable_scalar__WEBPACK_IMPORTED_MODULE_1__["scalar"])(array[0]));
- }
- else if (len > 0) {
- return Object(_observable_concat__WEBPACK_IMPORTED_MODULE_3__["concat"])(source, Object(_observable_fromArray__WEBPACK_IMPORTED_MODULE_0__["fromArray"])(array, scheduler));
- }
- else {
- return Object(_observable_concat__WEBPACK_IMPORTED_MODULE_3__["concat"])(source, Object(_observable_empty__WEBPACK_IMPORTED_MODULE_2__["empty"])(scheduler));
- }
- };
+ return function (source) { return Object(_observable_concat__WEBPACK_IMPORTED_MODULE_0__["concat"])(source, _observable_of__WEBPACK_IMPORTED_MODULE_1__["of"].apply(void 0, array)); };
}
//# sourceMappingURL=endWith.js.map
/***/ }),
-/* 405 */
+/* 406 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41115,15 +41082,15 @@ var EverySubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 406 */
+/* 407 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return exhaust; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -41172,18 +41139,20 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 407 */
+/* 408 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return exhaustMap; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
-/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334);
-/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(348);
-/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
+/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(333);
+/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(350);
+/** PURE_IMPORTS_START tslib,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */
+
@@ -41191,20 +41160,20 @@ __webpack_require__.r(__webpack_exports__);
function exhaustMap(project, resultSelector) {
if (resultSelector) {
- return function (source) { return source.pipe(exhaustMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_4__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_3__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); })); };
+ return function (source) { return source.pipe(exhaustMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_5__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_4__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); })); };
}
return function (source) {
- return source.lift(new ExhauseMapOperator(project));
+ return source.lift(new ExhaustMapOperator(project));
};
}
-var ExhauseMapOperator = /*@__PURE__*/ (function () {
- function ExhauseMapOperator(project) {
+var ExhaustMapOperator = /*@__PURE__*/ (function () {
+ function ExhaustMapOperator(project) {
this.project = project;
}
- ExhauseMapOperator.prototype.call = function (subscriber, source) {
+ ExhaustMapOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new ExhaustMapSubscriber(subscriber, this.project));
};
- return ExhauseMapOperator;
+ return ExhaustMapOperator;
}());
var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) {
tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](ExhaustMapSubscriber, _super);
@@ -41222,22 +41191,30 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) {
}
};
ExhaustMapSubscriber.prototype.tryNext = function (value) {
+ var result;
var index = this.index++;
- var destination = this.destination;
try {
- var result = this.project(value, index);
- this.hasSubscription = true;
- this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, result, value, index));
+ result = this.project(value, index);
}
catch (err) {
- destination.error(err);
+ this.destination.error(err);
+ return;
}
+ this.hasSubscription = true;
+ this._innerSub(result, value, index);
+ };
+ ExhaustMapSubscriber.prototype._innerSub = function (result, value, index) {
+ var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__["InnerSubscriber"](this, undefined, undefined);
+ var destination = this.destination;
+ destination.add(innerSubscriber);
+ Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, result, value, index, innerSubscriber);
};
ExhaustMapSubscriber.prototype._complete = function () {
this.hasCompleted = true;
if (!this.hasSubscription) {
this.destination.complete();
}
+ this.unsubscribe();
};
ExhaustMapSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
this.destination.next(innerValue);
@@ -41246,7 +41223,8 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) {
this.destination.error(err);
};
ExhaustMapSubscriber.prototype.notifyComplete = function (innerSub) {
- this.remove(innerSub);
+ var destination = this.destination;
+ destination.remove(innerSub);
this.hasSubscription = false;
if (this.hasCompleted) {
this.destination.complete();
@@ -41258,7 +41236,7 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 408 */
+/* 409 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41267,13 +41245,9 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandOperator", function() { return ExpandOperator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandSubscriber", function() { return ExpandSubscriber; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(288);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
-
-
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -41327,16 +41301,20 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) {
var index = this.index++;
if (this.active < this.concurrent) {
destination.next(value);
- var result = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_1__["tryCatch"])(this.project)(value, index);
- if (result === _util_errorObject__WEBPACK_IMPORTED_MODULE_2__["errorObject"]) {
- destination.error(_util_errorObject__WEBPACK_IMPORTED_MODULE_2__["errorObject"].e);
+ try {
+ var project = this.project;
+ var result = project(value, index);
+ if (!this.scheduler) {
+ this.subscribeToProjection(result, value, index);
+ }
+ else {
+ var state = { subscriber: this, result: result, value: value, index: index };
+ var destination_1 = this.destination;
+ destination_1.add(this.scheduler.schedule(ExpandSubscriber.dispatch, 0, state));
+ }
}
- else if (!this.scheduler) {
- this.subscribeToProjection(result, value, index);
- }
- else {
- var state = { subscriber: this, result: result, value: value, index: index };
- this.add(this.scheduler.schedule(ExpandSubscriber.dispatch, 0, state));
+ catch (e) {
+ destination.error(e);
}
}
else {
@@ -41345,20 +41323,23 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) {
};
ExpandSubscriber.prototype.subscribeToProjection = function (result, value, index) {
this.active++;
- this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(this, result, value, index));
+ var destination = this.destination;
+ destination.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, result, value, index));
};
ExpandSubscriber.prototype._complete = function () {
this.hasCompleted = true;
if (this.hasCompleted && this.active === 0) {
this.destination.complete();
}
+ this.unsubscribe();
};
ExpandSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
this._next(innerValue);
};
ExpandSubscriber.prototype.notifyComplete = function (innerSub) {
var buffer = this.buffer;
- this.remove(innerSub);
+ var destination = this.destination;
+ destination.remove(innerSub);
this.active--;
if (buffer && buffer.length > 0) {
this._next(buffer.shift());
@@ -41368,13 +41349,13 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) {
}
};
return ExpandSubscriber;
-}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__["OuterSubscriber"]));
+}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"]));
//# sourceMappingURL=expand.js.map
/***/ }),
-/* 409 */
+/* 410 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41412,7 +41393,7 @@ var FinallySubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 410 */
+/* 411 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41459,6 +41440,7 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) {
var destination = this.destination;
destination.next(value);
destination.complete();
+ this.unsubscribe();
};
FindValueSubscriber.prototype._next = function (value) {
var _a = this, predicate = _a.predicate, thisArg = _a.thisArg;
@@ -41483,13 +41465,13 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 411 */
+/* 412 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return findIndex; });
-/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(410);
+/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(411);
/** PURE_IMPORTS_START _operators_find PURE_IMPORTS_END */
function findIndex(predicate, thisArg) {
@@ -41499,18 +41481,18 @@ function findIndex(predicate, thisArg) {
/***/ }),
-/* 412 */
+/* 413 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "first", function() { return first; });
-/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(331);
-/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(400);
-/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(403);
-/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(391);
-/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(401);
-/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(328);
+/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(330);
+/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(371);
+/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(404);
+/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(394);
+/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(403);
+/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(327);
/** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */
@@ -41526,7 +41508,7 @@ function first(predicate, defaultValue) {
/***/ }),
-/* 413 */
+/* 414 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41563,7 +41545,7 @@ var IgnoreElementsSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 414 */
+/* 415 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41607,18 +41589,18 @@ var IsEmptySubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 415 */
+/* 416 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "last", function() { return last; });
-/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(331);
-/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(400);
-/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(416);
-/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(401);
-/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(391);
-/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(328);
+/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(330);
+/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(371);
+/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(417);
+/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(403);
+/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(394);
+/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(327);
/** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */
@@ -41634,7 +41616,7 @@ function last(predicate, defaultValue) {
/***/ }),
-/* 416 */
+/* 417 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41642,8 +41624,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return takeLast; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(330);
-/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311);
+/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(329);
+/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(310);
/** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */
@@ -41711,7 +41693,7 @@ var TakeLastSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 417 */
+/* 418 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41750,7 +41732,7 @@ var MapToSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 418 */
+/* 419 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41758,7 +41740,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return materialize; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(310);
+/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(309);
/** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */
@@ -41800,13 +41782,13 @@ var MaterializeSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 419 */
+/* 420 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "max", function() { return max; });
-/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(420);
+/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(421);
/** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */
function max(comparer) {
@@ -41819,16 +41801,16 @@ function max(comparer) {
/***/ }),
-/* 420 */
+/* 421 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return reduce; });
-/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(421);
-/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(416);
-/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(391);
-/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(292);
+/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(422);
+/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(417);
+/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(394);
+/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(291);
/** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */
@@ -41841,16 +41823,14 @@ function reduce(accumulator, seed) {
};
}
return function reduceOperatorFunction(source) {
- return Object(_util_pipe__WEBPACK_IMPORTED_MODULE_3__["pipe"])(Object(_scan__WEBPACK_IMPORTED_MODULE_0__["scan"])(function (acc, value, index) {
- return accumulator(acc, value, index + 1);
- }), Object(_takeLast__WEBPACK_IMPORTED_MODULE_1__["takeLast"])(1))(source);
+ return Object(_util_pipe__WEBPACK_IMPORTED_MODULE_3__["pipe"])(Object(_scan__WEBPACK_IMPORTED_MODULE_0__["scan"])(function (acc, value, index) { return accumulator(acc, value, index + 1); }), Object(_takeLast__WEBPACK_IMPORTED_MODULE_1__["takeLast"])(1))(source);
};
}
//# sourceMappingURL=reduce.js.map
/***/ }),
-/* 421 */
+/* 422 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41932,7 +41912,7 @@ var ScanSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 422 */
+/* 423 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41952,13 +41932,13 @@ function merge() {
/***/ }),
-/* 423 */
+/* 424 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return mergeMapTo; });
-/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(356);
+/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(349);
/** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */
function mergeMapTo(innerObservable, resultSelector, concurrent) {
@@ -41977,7 +41957,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) {
/***/ }),
-/* 424 */
+/* 425 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -41986,12 +41966,10 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanOperator", function() { return MergeScanOperator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanSubscriber", function() { return MergeScanSubscriber; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(288);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(338);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
-/** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_util_subscribeToResult,_OuterSubscriber PURE_IMPORTS_END */
-
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(336);
+/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(338);
+/** PURE_IMPORTS_START tslib,_util_subscribeToResult,_OuterSubscriber,_InnerSubscriber PURE_IMPORTS_END */
@@ -42031,22 +42009,27 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) {
MergeScanSubscriber.prototype._next = function (value) {
if (this.active < this.concurrent) {
var index = this.index++;
- var ish = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_1__["tryCatch"])(this.accumulator)(this.acc, value);
var destination = this.destination;
- if (ish === _util_errorObject__WEBPACK_IMPORTED_MODULE_2__["errorObject"]) {
- destination.error(_util_errorObject__WEBPACK_IMPORTED_MODULE_2__["errorObject"].e);
+ var ish = void 0;
+ try {
+ var accumulator = this.accumulator;
+ ish = accumulator(this.acc, value, index);
}
- else {
- this.active++;
- this._innerSub(ish, value, index);
+ catch (e) {
+ return destination.error(e);
}
+ this.active++;
+ this._innerSub(ish, value, index);
}
else {
this.buffer.push(value);
}
};
MergeScanSubscriber.prototype._innerSub = function (ish, value, index) {
- this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, ish, value, index));
+ var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_3__["InnerSubscriber"](this, undefined, undefined);
+ var destination = this.destination;
+ destination.add(innerSubscriber);
+ Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__["subscribeToResult"])(this, ish, value, index, innerSubscriber);
};
MergeScanSubscriber.prototype._complete = function () {
this.hasCompleted = true;
@@ -42056,6 +42039,7 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) {
}
this.destination.complete();
}
+ this.unsubscribe();
};
MergeScanSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
var destination = this.destination;
@@ -42065,7 +42049,8 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) {
};
MergeScanSubscriber.prototype.notifyComplete = function (innerSub) {
var buffer = this.buffer;
- this.remove(innerSub);
+ var destination = this.destination;
+ destination.remove(innerSub);
this.active--;
if (buffer.length > 0) {
this._next(buffer.shift());
@@ -42078,19 +42063,19 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) {
}
};
return MergeScanSubscriber;
-}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__["OuterSubscriber"]));
+}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"]));
//# sourceMappingURL=mergeScan.js.map
/***/ }),
-/* 425 */
+/* 426 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "min", function() { return min; });
-/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(420);
+/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(421);
/** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */
function min(comparer) {
@@ -42103,14 +42088,14 @@ function min(comparer) {
/***/ }),
-/* 426 */
+/* 427 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return multicast; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MulticastOperator", function() { return MulticastOperator; });
-/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(294);
+/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(293);
/** PURE_IMPORTS_START _observable_ConnectableObservable PURE_IMPORTS_END */
function multicast(subjectOrSubjectFactory, selector) {
@@ -42152,7 +42137,7 @@ var MulticastOperator = /*@__PURE__*/ (function () {
/***/ }),
-/* 427 */
+/* 428 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -42160,11 +42145,13 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNextStatic", function() { return onErrorResumeNextStatic; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(348);
+/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(350);
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_observable_from,_util_isArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(336);
+/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_observable_from,_util_isArray,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
+
@@ -42217,14 +42204,19 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) {
};
OnErrorResumeNextSubscriber.prototype._error = function (err) {
this.subscribeToNextSource();
+ this.unsubscribe();
};
OnErrorResumeNextSubscriber.prototype._complete = function () {
this.subscribeToNextSource();
+ this.unsubscribe();
};
OnErrorResumeNextSubscriber.prototype.subscribeToNextSource = function () {
var next = this.nextSources.shift();
- if (next) {
- this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(this, next));
+ if (!!next) {
+ var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_4__["InnerSubscriber"](this, undefined, undefined);
+ var destination = this.destination;
+ destination.add(innerSubscriber);
+ Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__["subscribeToResult"])(this, next, undefined, undefined, innerSubscriber);
}
else {
this.destination.complete();
@@ -42236,7 +42228,7 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 428 */
+/* 429 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -42266,13 +42258,17 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) {
return _this;
}
PairwiseSubscriber.prototype._next = function (value) {
+ var pair;
if (this.hasPrev) {
- this.destination.next([this.prev, value]);
+ pair = [this.prev, value];
}
else {
this.hasPrev = true;
}
this.prev = value;
+ if (pair) {
+ this.destination.next(pair);
+ }
};
return PairwiseSubscriber;
}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"]));
@@ -42280,14 +42276,14 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 429 */
+/* 430 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return partition; });
-/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(430);
-/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(400);
+/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(370);
+/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(371);
/** PURE_IMPORTS_START _util_not,_filter PURE_IMPORTS_END */
@@ -42302,25 +42298,6 @@ function partition(predicate, thisArg) {
//# sourceMappingURL=partition.js.map
-/***/ }),
-/* 430 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "not", function() { return not; });
-/** PURE_IMPORTS_START PURE_IMPORTS_END */
-function not(pred, thisArg) {
- function notPred() {
- return !(notPred.pred.apply(notPred.thisArg, arguments));
- }
- notPred.pred = pred;
- notPred.thisArg = thisArg;
- return notPred;
-}
-//# sourceMappingURL=not.js.map
-
-
/***/ }),
/* 431 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
@@ -42328,7 +42305,7 @@ function not(pred, thisArg) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return pluck; });
-/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(334);
+/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(333);
/** PURE_IMPORTS_START _map PURE_IMPORTS_END */
function pluck() {
@@ -42368,8 +42345,8 @@ function plucker(props, length) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return publish; });
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(295);
-/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(426);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(294);
+/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(427);
/** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */
@@ -42388,8 +42365,8 @@ function publish(selector) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return publishBehavior; });
-/* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(300);
-/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(426);
+/* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(299);
+/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(427);
/** PURE_IMPORTS_START _BehaviorSubject,_multicast PURE_IMPORTS_END */
@@ -42406,8 +42383,8 @@ function publishBehavior(value) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return publishLast; });
-/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(318);
-/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(426);
+/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(317);
+/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(427);
/** PURE_IMPORTS_START _AsyncSubject,_multicast PURE_IMPORTS_END */
@@ -42424,8 +42401,8 @@ function publishLast() {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return publishReplay; });
-/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(301);
-/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(426);
+/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(300);
+/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(427);
/** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */
@@ -42448,7 +42425,7 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; });
/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285);
-/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(369);
+/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(372);
/** PURE_IMPORTS_START _util_isArray,_observable_race PURE_IMPORTS_END */
@@ -42476,7 +42453,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return repeat; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311);
+/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(310);
/** PURE_IMPORTS_START tslib,_Subscriber,_observable_empty PURE_IMPORTS_END */
@@ -42540,14 +42517,10 @@ var RepeatSubscriber = /*@__PURE__*/ (function (_super) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return repeatWhen; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
-
-
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -42616,15 +42589,19 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) {
};
RepeatWhenSubscriber.prototype.subscribeToRetries = function () {
this.notifications = new _Subject__WEBPACK_IMPORTED_MODULE_1__["Subject"]();
- var retries = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_2__["tryCatch"])(this.notifier)(this.notifications);
- if (retries === _util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"]) {
+ var retries;
+ try {
+ var notifier = this.notifier;
+ retries = notifier(this.notifications);
+ }
+ catch (e) {
return _super.prototype.complete.call(this);
}
this.retries = retries;
- this.retriesSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__["subscribeToResult"])(this, retries);
+ this.retriesSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, retries);
};
return RepeatWhenSubscriber;
-}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__["OuterSubscriber"]));
+}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"]));
//# sourceMappingURL=repeatWhen.js.map
@@ -42689,14 +42666,10 @@ var RetrySubscriber = /*@__PURE__*/ (function (_super) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return retryWhen; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
-
-
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -42729,11 +42702,14 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) {
var retriesSubscription = this.retriesSubscription;
if (!retries) {
errors = new _Subject__WEBPACK_IMPORTED_MODULE_1__["Subject"]();
- retries = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_2__["tryCatch"])(this.notifier)(errors);
- if (retries === _util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"]) {
- return _super.prototype.error.call(this, _util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"].e);
+ try {
+ var notifier = this.notifier;
+ retries = notifier(errors);
}
- retriesSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__["subscribeToResult"])(this, retries);
+ catch (e) {
+ return _super.prototype.error.call(this, e);
+ }
+ retriesSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, retries);
}
else {
this.errors = null;
@@ -42766,7 +42742,7 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) {
this.source.subscribe(this);
};
return RetryWhenSubscriber;
-}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__["OuterSubscriber"]));
+}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"]));
//# sourceMappingURL=retryWhen.js.map
@@ -42778,8 +42754,8 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return sample; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -42836,7 +42812,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return sampleTime; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(323);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(322);
/** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */
@@ -42898,37 +42874,33 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SequenceEqualSubscriber", function() { return SequenceEqualSubscriber; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288);
-/** PURE_IMPORTS_START tslib,_Subscriber,_util_tryCatch,_util_errorObject PURE_IMPORTS_END */
-
-
+/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
-function sequenceEqual(compareTo, comparor) {
- return function (source) { return source.lift(new SequenceEqualOperator(compareTo, comparor)); };
+function sequenceEqual(compareTo, comparator) {
+ return function (source) { return source.lift(new SequenceEqualOperator(compareTo, comparator)); };
}
var SequenceEqualOperator = /*@__PURE__*/ (function () {
- function SequenceEqualOperator(compareTo, comparor) {
+ function SequenceEqualOperator(compareTo, comparator) {
this.compareTo = compareTo;
- this.comparor = comparor;
+ this.comparator = comparator;
}
SequenceEqualOperator.prototype.call = function (subscriber, source) {
- return source.subscribe(new SequenceEqualSubscriber(subscriber, this.compareTo, this.comparor));
+ return source.subscribe(new SequenceEqualSubscriber(subscriber, this.compareTo, this.comparator));
};
return SequenceEqualOperator;
}());
var SequenceEqualSubscriber = /*@__PURE__*/ (function (_super) {
tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](SequenceEqualSubscriber, _super);
- function SequenceEqualSubscriber(destination, compareTo, comparor) {
+ function SequenceEqualSubscriber(destination, compareTo, comparator) {
var _this = _super.call(this, destination) || this;
_this.compareTo = compareTo;
- _this.comparor = comparor;
+ _this.comparator = comparator;
_this._a = [];
_this._b = [];
_this._oneComplete = false;
- _this.add(compareTo.subscribe(new SequenceEqualCompareToSubscriber(destination, _this)));
+ _this.destination.add(compareTo.subscribe(new SequenceEqualCompareToSubscriber(destination, _this)));
return _this;
}
SequenceEqualSubscriber.prototype._next = function (value) {
@@ -42947,21 +42919,19 @@ var SequenceEqualSubscriber = /*@__PURE__*/ (function (_super) {
else {
this._oneComplete = true;
}
+ this.unsubscribe();
};
SequenceEqualSubscriber.prototype.checkValues = function () {
- var _c = this, _a = _c._a, _b = _c._b, comparor = _c.comparor;
+ var _c = this, _a = _c._a, _b = _c._b, comparator = _c.comparator;
while (_a.length > 0 && _b.length > 0) {
var a = _a.shift();
var b = _b.shift();
var areEqual = false;
- if (comparor) {
- areEqual = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_2__["tryCatch"])(comparor)(a, b);
- if (areEqual === _util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"]) {
- this.destination.error(_util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"].e);
- }
+ try {
+ areEqual = comparator ? comparator(a, b) : a === b;
}
- else {
- areEqual = a === b;
+ catch (e) {
+ this.destination.error(e);
}
if (!areEqual) {
this.emit(false);
@@ -42982,6 +42952,14 @@ var SequenceEqualSubscriber = /*@__PURE__*/ (function (_super) {
this.checkValues();
}
};
+ SequenceEqualSubscriber.prototype.completeB = function () {
+ if (this._oneComplete) {
+ this.emit(this._a.length === 0 && this._b.length === 0);
+ }
+ else {
+ this._oneComplete = true;
+ }
+ };
return SequenceEqualSubscriber;
}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"]));
@@ -42997,9 +42975,11 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) {
};
SequenceEqualCompareToSubscriber.prototype._error = function (err) {
this.parent.error(err);
+ this.unsubscribe();
};
SequenceEqualCompareToSubscriber.prototype._complete = function () {
- this.parent._complete();
+ this.parent.completeB();
+ this.unsubscribe();
};
return SequenceEqualCompareToSubscriber;
}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"]));
@@ -43013,9 +42993,9 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "share", function() { return share; });
-/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(426);
-/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(298);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(295);
+/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(427);
+/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(297);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(294);
/** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */
@@ -43036,13 +43016,26 @@ function share() {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return shareReplay; });
-/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(301);
+/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(300);
/** PURE_IMPORTS_START _ReplaySubject PURE_IMPORTS_END */
-function shareReplay(bufferSize, windowTime, scheduler) {
- return function (source) { return source.lift(shareReplayOperator(bufferSize, windowTime, scheduler)); };
+function shareReplay(configOrBufferSize, windowTime, scheduler) {
+ var config;
+ if (configOrBufferSize && typeof configOrBufferSize === 'object') {
+ config = configOrBufferSize;
+ }
+ else {
+ config = {
+ bufferSize: configOrBufferSize,
+ windowTime: windowTime,
+ refCount: false,
+ scheduler: scheduler
+ };
+ }
+ return function (source) { return source.lift(shareReplayOperator(config)); };
}
-function shareReplayOperator(bufferSize, windowTime, scheduler) {
+function shareReplayOperator(_a) {
+ var _b = _a.bufferSize, bufferSize = _b === void 0 ? Number.POSITIVE_INFINITY : _b, _c = _a.windowTime, windowTime = _c === void 0 ? Number.POSITIVE_INFINITY : _c, useRefCount = _a.refCount, scheduler = _a.scheduler;
var subject;
var refCount = 0;
var subscription;
@@ -43066,13 +43059,15 @@ function shareReplayOperator(bufferSize, windowTime, scheduler) {
});
}
var innerSub = subject.subscribe(this);
- return function () {
+ this.add(function () {
refCount--;
innerSub.unsubscribe();
- if (subscription && refCount === 0 && isComplete) {
+ if (subscription && !isComplete && useRefCount && refCount === 0) {
subscription.unsubscribe();
+ subscription = undefined;
+ subject = undefined;
}
- };
+ });
};
}
//# sourceMappingURL=shareReplay.js.map
@@ -43087,7 +43082,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "single", function() { return single; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(331);
+/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(330);
/** PURE_IMPORTS_START tslib,_Subscriber,_util_EmptyError PURE_IMPORTS_END */
@@ -43209,7 +43204,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return skipLast; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(330);
+/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(329);
/** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError PURE_IMPORTS_END */
@@ -43270,9 +43265,11 @@ var SkipLastSubscriber = /*@__PURE__*/ (function (_super) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return skipUntil; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
+
@@ -43293,7 +43290,10 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) {
function SkipUntilSubscriber(destination, notifier) {
var _this = _super.call(this, destination) || this;
_this.hasValue = false;
- _this.add(_this.innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(_this, notifier));
+ var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__["InnerSubscriber"](_this, undefined, undefined);
+ _this.add(innerSubscriber);
+ _this.innerSubscription = innerSubscriber;
+ Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(_this, notifier, undefined, undefined, innerSubscriber);
return _this;
}
SkipUntilSubscriber.prototype._next = function (value) {
@@ -43377,15 +43377,9 @@ var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return startWith; });
-/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(314);
-/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(316);
-/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311);
-/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(347);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(313);
-/** PURE_IMPORTS_START _observable_fromArray,_observable_scalar,_observable_empty,_observable_concat,_util_isScheduler PURE_IMPORTS_END */
-
-
-
+/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(346);
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(312);
+/** PURE_IMPORTS_START _observable_concat,_util_isScheduler PURE_IMPORTS_END */
function startWith() {
@@ -43393,25 +43387,14 @@ function startWith() {
for (var _i = 0; _i < arguments.length; _i++) {
array[_i] = arguments[_i];
}
- return function (source) {
- var scheduler = array[array.length - 1];
- if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_4__["isScheduler"])(scheduler)) {
- array.pop();
- }
- else {
- scheduler = null;
- }
- var len = array.length;
- if (len === 1 && !scheduler) {
- return Object(_observable_concat__WEBPACK_IMPORTED_MODULE_3__["concat"])(Object(_observable_scalar__WEBPACK_IMPORTED_MODULE_1__["scalar"])(array[0]), source);
- }
- else if (len > 0) {
- return Object(_observable_concat__WEBPACK_IMPORTED_MODULE_3__["concat"])(Object(_observable_fromArray__WEBPACK_IMPORTED_MODULE_0__["fromArray"])(array, scheduler), source);
- }
- else {
- return Object(_observable_concat__WEBPACK_IMPORTED_MODULE_3__["concat"])(Object(_observable_empty__WEBPACK_IMPORTED_MODULE_2__["empty"])(scheduler), source);
- }
- };
+ var scheduler = array[array.length - 1];
+ if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_1__["isScheduler"])(scheduler)) {
+ array.pop();
+ return function (source) { return Object(_observable_concat__WEBPACK_IMPORTED_MODULE_0__["concat"])(array, source, scheduler); };
+ }
+ else {
+ return function (source) { return Object(_observable_concat__WEBPACK_IMPORTED_MODULE_0__["concat"])(array, source); };
+ }
}
//# sourceMappingURL=startWith.js.map
@@ -43456,7 +43439,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubscribeOnObservable", function() { return SubscribeOnObservable; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276);
-/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(319);
+/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(318);
/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(364);
/** PURE_IMPORTS_START tslib,_Observable,_scheduler_asap,_util_isNumeric PURE_IMPORTS_END */
@@ -43519,7 +43502,7 @@ var SubscribeOnObservable = /*@__PURE__*/ (function (_super) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return switchAll; });
/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(455);
-/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328);
+/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(327);
/** PURE_IMPORTS_START _switchMap,_util_identity PURE_IMPORTS_END */
@@ -43537,11 +43520,13 @@ function switchAll() {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return switchMap; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
-/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334);
-/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(348);
-/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
+/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(333);
+/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(350);
+/** PURE_IMPORTS_START tslib,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */
+
@@ -43549,7 +43534,7 @@ __webpack_require__.r(__webpack_exports__);
function switchMap(project, resultSelector) {
if (typeof resultSelector === 'function') {
- return function (source) { return source.pipe(switchMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_4__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_3__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); })); };
+ return function (source) { return source.pipe(switchMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_5__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_4__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); })); };
}
return function (source) { return source.lift(new SwitchMapOperator(project)); };
}
@@ -43587,19 +43572,24 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) {
if (innerSubscription) {
innerSubscription.unsubscribe();
}
- this.add(this.innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, result, value, index));
+ var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__["InnerSubscriber"](this, undefined, undefined);
+ var destination = this.destination;
+ destination.add(innerSubscriber);
+ this.innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, result, value, index, innerSubscriber);
};
SwitchMapSubscriber.prototype._complete = function () {
var innerSubscription = this.innerSubscription;
if (!innerSubscription || innerSubscription.closed) {
_super.prototype._complete.call(this);
}
+ this.unsubscribe();
};
SwitchMapSubscriber.prototype._unsubscribe = function () {
this.innerSubscription = null;
};
SwitchMapSubscriber.prototype.notifyComplete = function (innerSub) {
- this.remove(innerSub);
+ var destination = this.destination;
+ destination.remove(innerSub);
this.innerSubscription = null;
if (this.isStopped) {
_super.prototype._complete.call(this);
@@ -43637,8 +43627,8 @@ function switchMapTo(innerObservable, resultSelector) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return takeUntil; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -43653,7 +43643,7 @@ var TakeUntilOperator = /*@__PURE__*/ (function () {
TakeUntilOperator.prototype.call = function (subscriber, source) {
var takeUntilSubscriber = new TakeUntilSubscriber(subscriber);
var notifierSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(takeUntilSubscriber, this.notifier);
- if (notifierSubscription && !notifierSubscription.closed) {
+ if (notifierSubscription && !takeUntilSubscriber.seenValue) {
takeUntilSubscriber.add(notifierSubscription);
return source.subscribe(takeUntilSubscriber);
}
@@ -43664,9 +43654,12 @@ var TakeUntilOperator = /*@__PURE__*/ (function () {
var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) {
tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](TakeUntilSubscriber, _super);
function TakeUntilSubscriber(destination) {
- return _super.call(this, destination) || this;
+ var _this = _super.call(this, destination) || this;
+ _this.seenValue = false;
+ return _this;
}
TakeUntilSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
+ this.seenValue = true;
this.complete();
};
TakeUntilSubscriber.prototype.notifyComplete = function () {
@@ -43688,23 +43681,30 @@ __webpack_require__.r(__webpack_exports__);
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
-function takeWhile(predicate) {
- return function (source) { return source.lift(new TakeWhileOperator(predicate)); };
+function takeWhile(predicate, inclusive) {
+ if (inclusive === void 0) {
+ inclusive = false;
+ }
+ return function (source) {
+ return source.lift(new TakeWhileOperator(predicate, inclusive));
+ };
}
var TakeWhileOperator = /*@__PURE__*/ (function () {
- function TakeWhileOperator(predicate) {
+ function TakeWhileOperator(predicate, inclusive) {
this.predicate = predicate;
+ this.inclusive = inclusive;
}
TakeWhileOperator.prototype.call = function (subscriber, source) {
- return source.subscribe(new TakeWhileSubscriber(subscriber, this.predicate));
+ return source.subscribe(new TakeWhileSubscriber(subscriber, this.predicate, this.inclusive));
};
return TakeWhileOperator;
}());
var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) {
tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](TakeWhileSubscriber, _super);
- function TakeWhileSubscriber(destination, predicate) {
+ function TakeWhileSubscriber(destination, predicate, inclusive) {
var _this = _super.call(this, destination) || this;
_this.predicate = predicate;
+ _this.inclusive = inclusive;
_this.index = 0;
return _this;
}
@@ -43726,6 +43726,9 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) {
destination.next(value);
}
else {
+ if (this.inclusive) {
+ destination.next(value);
+ }
destination.complete();
}
};
@@ -43738,13 +43741,101 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) {
/* 459 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return tap; });
+/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
+/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
+/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(292);
+/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(280);
+/** PURE_IMPORTS_START tslib,_Subscriber,_util_noop,_util_isFunction PURE_IMPORTS_END */
+
+
+
+
+function tap(nextOrObserver, error, complete) {
+ return function tapOperatorFunction(source) {
+ return source.lift(new DoOperator(nextOrObserver, error, complete));
+ };
+}
+var DoOperator = /*@__PURE__*/ (function () {
+ function DoOperator(nextOrObserver, error, complete) {
+ this.nextOrObserver = nextOrObserver;
+ this.error = error;
+ this.complete = complete;
+ }
+ DoOperator.prototype.call = function (subscriber, source) {
+ return source.subscribe(new TapSubscriber(subscriber, this.nextOrObserver, this.error, this.complete));
+ };
+ return DoOperator;
+}());
+var TapSubscriber = /*@__PURE__*/ (function (_super) {
+ tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](TapSubscriber, _super);
+ function TapSubscriber(destination, observerOrNext, error, complete) {
+ var _this = _super.call(this, destination) || this;
+ _this._tapNext = _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
+ _this._tapError = _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
+ _this._tapComplete = _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
+ _this._tapError = error || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
+ _this._tapComplete = complete || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
+ if (Object(_util_isFunction__WEBPACK_IMPORTED_MODULE_3__["isFunction"])(observerOrNext)) {
+ _this._context = _this;
+ _this._tapNext = observerOrNext;
+ }
+ else if (observerOrNext) {
+ _this._context = observerOrNext;
+ _this._tapNext = observerOrNext.next || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
+ _this._tapError = observerOrNext.error || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
+ _this._tapComplete = observerOrNext.complete || _util_noop__WEBPACK_IMPORTED_MODULE_2__["noop"];
+ }
+ return _this;
+ }
+ TapSubscriber.prototype._next = function (value) {
+ try {
+ this._tapNext.call(this._context, value);
+ }
+ catch (err) {
+ this.destination.error(err);
+ return;
+ }
+ this.destination.next(value);
+ };
+ TapSubscriber.prototype._error = function (err) {
+ try {
+ this._tapError.call(this._context, err);
+ }
+ catch (err) {
+ this.destination.error(err);
+ return;
+ }
+ this.destination.error(err);
+ };
+ TapSubscriber.prototype._complete = function () {
+ try {
+ this._tapComplete.call(this._context);
+ }
+ catch (err) {
+ this.destination.error(err);
+ return;
+ }
+ return this.destination.complete();
+ };
+ return TapSubscriber;
+}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"]));
+//# sourceMappingURL=tap.js.map
+
+
+/***/ }),
+/* 460 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultThrottleConfig", function() { return defaultThrottleConfig; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return throttle; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -43804,7 +43895,7 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) {
};
ThrottleSubscriber.prototype.throttle = function (value) {
var duration = this.tryDurationSelector(value);
- if (duration) {
+ if (!!duration) {
this.add(this._throttled = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, duration));
}
};
@@ -43839,7 +43930,7 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 460 */
+/* 461 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -43847,8 +43938,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return throttleTime; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(323);
-/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(459);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(322);
+/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(460);
/** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */
@@ -43899,6 +43990,10 @@ var ThrottleTimeSubscriber = /*@__PURE__*/ (function (_super) {
if (this.leading) {
this.destination.next(value);
}
+ else if (this.trailing) {
+ this._trailingValue = value;
+ this._hasTrailingValue = true;
+ }
}
};
ThrottleTimeSubscriber.prototype._complete = function () {
@@ -43933,17 +44028,17 @@ function dispatchNext(arg) {
/***/ }),
-/* 461 */
+/* 462 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return timeInterval; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeInterval", function() { return TimeInterval; });
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(323);
-/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(421);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(322);
+/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(422);
/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(357);
-/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334);
+/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(333);
/** PURE_IMPORTS_START _scheduler_async,_scan,_observable_defer,_map PURE_IMPORTS_END */
@@ -43977,16 +44072,16 @@ var TimeInterval = /*@__PURE__*/ (function () {
/***/ }),
-/* 462 */
+/* 463 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return timeout; });
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(323);
-/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(332);
-/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(463);
-/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(317);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(322);
+/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(331);
+/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(464);
+/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(316);
/** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */
@@ -44002,17 +44097,17 @@ function timeout(due, scheduler) {
/***/ }),
-/* 463 */
+/* 464 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return timeoutWith; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323);
-/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(393);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(322);
+/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(396);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -44084,15 +44179,15 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 464 */
+/* 465 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return timestamp; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Timestamp", function() { return Timestamp; });
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(323);
-/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(334);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(322);
+/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(333);
/** PURE_IMPORTS_START _scheduler_async,_map PURE_IMPORTS_END */
@@ -44114,13 +44209,13 @@ var Timestamp = /*@__PURE__*/ (function () {
/***/ }),
-/* 465 */
+/* 466 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return toArray; });
-/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(420);
+/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(421);
/** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */
function toArrayReducer(arr, item, index) {
@@ -44137,16 +44232,16 @@ function toArray() {
/***/ }),
-/* 466 */
+/* 467 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "window", function() { return window; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(338);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -44217,7 +44312,7 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 467 */
+/* 468 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -44225,7 +44320,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return windowCount; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(295);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(294);
/** PURE_IMPORTS_START tslib,_Subscriber,_Subject PURE_IMPORTS_END */
@@ -44307,18 +44402,18 @@ var WindowCountSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 468 */
+/* 469 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return windowTime; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
-/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(323);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
+/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(322);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278);
/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(364);
-/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(313);
+/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(312);
/** PURE_IMPORTS_START tslib,_Subject,_scheduler_async,_Subscriber,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */
@@ -44477,22 +44572,18 @@ function dispatchWindowClose(state) {
/***/ }),
-/* 469 */
+/* 470 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return windowToggle; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(284);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(288);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_Subject,_Subscription,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
-
-
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_Subject,_Subscription,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -44518,7 +44609,7 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) {
_this.openings = openings;
_this.closingSelector = closingSelector;
_this.contexts = [];
- _this.add(_this.openSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_6__["subscribeToResult"])(_this, openings, openings));
+ _this.add(_this.openSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(_this, openings, openings));
return _this;
}
WindowToggleSubscriber.prototype._next = function (value) {
@@ -44573,26 +44664,27 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) {
};
WindowToggleSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
if (outerValue === this.openings) {
- var closingSelector = this.closingSelector;
- var closingNotifier = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_3__["tryCatch"])(closingSelector)(innerValue);
- if (closingNotifier === _util_errorObject__WEBPACK_IMPORTED_MODULE_4__["errorObject"]) {
- return this.error(_util_errorObject__WEBPACK_IMPORTED_MODULE_4__["errorObject"].e);
+ var closingNotifier = void 0;
+ try {
+ var closingSelector = this.closingSelector;
+ closingNotifier = closingSelector(innerValue);
+ }
+ catch (e) {
+ return this.error(e);
+ }
+ var window_1 = new _Subject__WEBPACK_IMPORTED_MODULE_1__["Subject"]();
+ var subscription = new _Subscription__WEBPACK_IMPORTED_MODULE_2__["Subscription"]();
+ var context_4 = { window: window_1, subscription: subscription };
+ this.contexts.push(context_4);
+ var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(this, closingNotifier, context_4);
+ if (innerSubscription.closed) {
+ this.closeWindow(this.contexts.length - 1);
}
else {
- var window_1 = new _Subject__WEBPACK_IMPORTED_MODULE_1__["Subject"]();
- var subscription = new _Subscription__WEBPACK_IMPORTED_MODULE_2__["Subscription"]();
- var context_4 = { window: window_1, subscription: subscription };
- this.contexts.push(context_4);
- var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_6__["subscribeToResult"])(this, closingNotifier, context_4);
- if (innerSubscription.closed) {
- this.closeWindow(this.contexts.length - 1);
- }
- else {
- innerSubscription.context = context_4;
- subscription.add(innerSubscription);
- }
- this.destination.next(window_1);
+ innerSubscription.context = context_4;
+ subscription.add(innerSubscription);
}
+ this.destination.next(window_1);
}
else {
this.closeWindow(this.contexts.indexOf(outerValue));
@@ -44618,26 +44710,22 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) {
subscription.unsubscribe();
};
return WindowToggleSubscriber;
-}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__["OuterSubscriber"]));
+}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__["OuterSubscriber"]));
//# sourceMappingURL=windowToggle.js.map
/***/ }),
-/* 470 */
+/* 471 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return windowWhen; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295);
-/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287);
-/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338);
-/** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
-
-
+/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337);
+/** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -44706,31 +44794,33 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) {
}
var window = this.window = new _Subject__WEBPACK_IMPORTED_MODULE_1__["Subject"]();
this.destination.next(window);
- var closingNotifier = Object(_util_tryCatch__WEBPACK_IMPORTED_MODULE_2__["tryCatch"])(this.closingSelector)();
- if (closingNotifier === _util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"]) {
- var err = _util_errorObject__WEBPACK_IMPORTED_MODULE_3__["errorObject"].e;
- this.destination.error(err);
- this.window.error(err);
+ var closingNotifier;
+ try {
+ var closingSelector = this.closingSelector;
+ closingNotifier = closingSelector();
}
- else {
- this.add(this.closingNotification = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__["subscribeToResult"])(this, closingNotifier));
+ catch (e) {
+ this.destination.error(e);
+ this.window.error(e);
+ return;
}
+ this.add(this.closingNotification = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, closingNotifier));
};
return WindowSubscriber;
-}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__["OuterSubscriber"]));
+}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"]));
//# sourceMappingURL=windowWhen.js.map
/***/ }),
-/* 471 */
+/* 472 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return withLatestFrom; });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279);
-/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337);
-/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338);
+/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336);
+/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337);
/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
@@ -44817,13 +44907,13 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 472 */
+/* 473 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return zip; });
-/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(373);
+/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(376);
/** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */
function zip() {
@@ -44839,13 +44929,13 @@ function zip() {
/***/ }),
-/* 473 */
+/* 474 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return zipAll; });
-/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(373);
+/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(376);
/** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */
function zipAll(project) {
@@ -44855,7 +44945,7 @@ function zipAll(project) {
/***/ }),
-/* 474 */
+/* 475 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -44865,13 +44955,13 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(259);
/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(475);
+/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(476);
/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(172);
/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(53);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34);
/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(36);
-/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(482);
+/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(483);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -44949,13 +45039,13 @@ function toArray(value) {
}
/***/ }),
-/* 475 */
+/* 476 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const stringWidth = __webpack_require__(476);
-const stripAnsi = __webpack_require__(480);
+const stringWidth = __webpack_require__(477);
+const stripAnsi = __webpack_require__(481);
const ESCAPES = new Set([
'\u001B',
@@ -45149,13 +45239,13 @@ module.exports = (str, cols, opts) => {
/***/ }),
-/* 476 */
+/* 477 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const stripAnsi = __webpack_require__(477);
-const isFullwidthCodePoint = __webpack_require__(479);
+const stripAnsi = __webpack_require__(478);
+const isFullwidthCodePoint = __webpack_require__(480);
module.exports = str => {
if (typeof str !== 'string' || str.length === 0) {
@@ -45192,18 +45282,18 @@ module.exports = str => {
/***/ }),
-/* 477 */
+/* 478 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const ansiRegex = __webpack_require__(478);
+const ansiRegex = __webpack_require__(479);
module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input;
/***/ }),
-/* 478 */
+/* 479 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -45220,7 +45310,7 @@ module.exports = () => {
/***/ }),
-/* 479 */
+/* 480 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -45273,18 +45363,18 @@ module.exports = x => {
/***/ }),
-/* 480 */
+/* 481 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const ansiRegex = __webpack_require__(481);
+const ansiRegex = __webpack_require__(482);
module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input;
/***/ }),
-/* 481 */
+/* 482 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -45301,7 +45391,7 @@ module.exports = () => {
/***/ }),
-/* 482 */
+/* 483 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -45454,15 +45544,15 @@ function addProjectToTree(tree, pathParts, project) {
}
/***/ }),
-/* 483 */
+/* 484 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(484);
+/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(485);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; });
-/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(691);
+/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(692);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; });
/*
@@ -45487,13 +45577,13 @@ __webpack_require__.r(__webpack_exports__);
/***/ }),
-/* 484 */
+/* 485 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; });
-/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(485);
+/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(486);
/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(174);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__);
@@ -45633,17 +45723,17 @@ async function copyToBuild(project, kibanaRoot, buildRoot) {
}
/***/ }),
-/* 485 */
+/* 486 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const EventEmitter = __webpack_require__(46);
const path = __webpack_require__(16);
-const arrify = __webpack_require__(486);
-const globby = __webpack_require__(487);
-const cpFile = __webpack_require__(681);
-const CpyError = __webpack_require__(689);
+const arrify = __webpack_require__(487);
+const globby = __webpack_require__(488);
+const cpFile = __webpack_require__(682);
+const CpyError = __webpack_require__(690);
const preprocessSrcPath = (srcPath, options) => options.cwd ? path.resolve(options.cwd, srcPath) : srcPath;
@@ -45748,7 +45838,7 @@ module.exports.default = cpy;
/***/ }),
-/* 486 */
+/* 487 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -45763,17 +45853,17 @@ module.exports = function (val) {
/***/ }),
-/* 487 */
+/* 488 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(23);
-const arrayUnion = __webpack_require__(488);
+const arrayUnion = __webpack_require__(489);
const glob = __webpack_require__(37);
-const fastGlob = __webpack_require__(490);
-const dirGlob = __webpack_require__(674);
-const gitignore = __webpack_require__(677);
+const fastGlob = __webpack_require__(491);
+const dirGlob = __webpack_require__(675);
+const gitignore = __webpack_require__(678);
const DEFAULT_FILTER = () => false;
@@ -45918,12 +46008,12 @@ module.exports.gitignore = gitignore;
/***/ }),
-/* 488 */
+/* 489 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var arrayUniq = __webpack_require__(489);
+var arrayUniq = __webpack_require__(490);
module.exports = function () {
return arrayUniq([].concat.apply([], arguments));
@@ -45931,7 +46021,7 @@ module.exports = function () {
/***/ }),
-/* 489 */
+/* 490 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -46000,10 +46090,10 @@ if ('Set' in global) {
/***/ }),
-/* 490 */
+/* 491 */
/***/ (function(module, exports, __webpack_require__) {
-const pkg = __webpack_require__(491);
+const pkg = __webpack_require__(492);
module.exports = pkg.async;
module.exports.default = pkg.async;
@@ -46016,19 +46106,19 @@ module.exports.generateTasks = pkg.generateTasks;
/***/ }),
-/* 491 */
+/* 492 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-var optionsManager = __webpack_require__(492);
-var taskManager = __webpack_require__(493);
-var reader_async_1 = __webpack_require__(645);
-var reader_stream_1 = __webpack_require__(669);
-var reader_sync_1 = __webpack_require__(670);
-var arrayUtils = __webpack_require__(672);
-var streamUtils = __webpack_require__(673);
+var optionsManager = __webpack_require__(493);
+var taskManager = __webpack_require__(494);
+var reader_async_1 = __webpack_require__(646);
+var reader_stream_1 = __webpack_require__(670);
+var reader_sync_1 = __webpack_require__(671);
+var arrayUtils = __webpack_require__(673);
+var streamUtils = __webpack_require__(674);
/**
* Synchronous API.
*/
@@ -46094,7 +46184,7 @@ function isString(source) {
/***/ }),
-/* 492 */
+/* 493 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -46132,13 +46222,13 @@ exports.prepare = prepare;
/***/ }),
-/* 493 */
+/* 494 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-var patternUtils = __webpack_require__(494);
+var patternUtils = __webpack_require__(495);
/**
* Generate tasks based on parent directory of each pattern.
*/
@@ -46229,16 +46319,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask;
/***/ }),
-/* 494 */
+/* 495 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var path = __webpack_require__(16);
-var globParent = __webpack_require__(495);
-var isGlob = __webpack_require__(498);
-var micromatch = __webpack_require__(499);
+var globParent = __webpack_require__(496);
+var isGlob = __webpack_require__(499);
+var micromatch = __webpack_require__(500);
var GLOBSTAR = '**';
/**
* Return true for static pattern.
@@ -46384,15 +46474,15 @@ exports.matchAny = matchAny;
/***/ }),
-/* 495 */
+/* 496 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var path = __webpack_require__(16);
-var isglob = __webpack_require__(496);
-var pathDirname = __webpack_require__(497);
+var isglob = __webpack_require__(497);
+var pathDirname = __webpack_require__(498);
var isWin32 = __webpack_require__(11).platform() === 'win32';
module.exports = function globParent(str) {
@@ -46415,7 +46505,7 @@ module.exports = function globParent(str) {
/***/ }),
-/* 496 */
+/* 497 */
/***/ (function(module, exports, __webpack_require__) {
/*!
@@ -46446,7 +46536,7 @@ module.exports = function isGlob(str) {
/***/ }),
-/* 497 */
+/* 498 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -46596,7 +46686,7 @@ module.exports.win32 = win32;
/***/ }),
-/* 498 */
+/* 499 */
/***/ (function(module, exports, __webpack_require__) {
/*!
@@ -46648,7 +46738,7 @@ module.exports = function isGlob(str, options) {
/***/ }),
-/* 499 */
+/* 500 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -46659,18 +46749,18 @@ module.exports = function isGlob(str, options) {
*/
var util = __webpack_require__(29);
-var braces = __webpack_require__(500);
-var toRegex = __webpack_require__(603);
-var extend = __webpack_require__(611);
+var braces = __webpack_require__(501);
+var toRegex = __webpack_require__(604);
+var extend = __webpack_require__(612);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(614);
-var parsers = __webpack_require__(641);
-var cache = __webpack_require__(642);
-var utils = __webpack_require__(643);
+var compilers = __webpack_require__(615);
+var parsers = __webpack_require__(642);
+var cache = __webpack_require__(643);
+var utils = __webpack_require__(644);
var MAX_LENGTH = 1024 * 64;
/**
@@ -47532,7 +47622,7 @@ module.exports = micromatch;
/***/ }),
-/* 500 */
+/* 501 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -47542,18 +47632,18 @@ module.exports = micromatch;
* Module dependencies
*/
-var toRegex = __webpack_require__(501);
-var unique = __webpack_require__(513);
-var extend = __webpack_require__(510);
+var toRegex = __webpack_require__(502);
+var unique = __webpack_require__(514);
+var extend = __webpack_require__(511);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(514);
-var parsers = __webpack_require__(529);
-var Braces = __webpack_require__(539);
-var utils = __webpack_require__(515);
+var compilers = __webpack_require__(515);
+var parsers = __webpack_require__(530);
+var Braces = __webpack_require__(540);
+var utils = __webpack_require__(516);
var MAX_LENGTH = 1024 * 64;
var cache = {};
@@ -47857,15 +47947,15 @@ module.exports = braces;
/***/ }),
-/* 501 */
+/* 502 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var define = __webpack_require__(502);
-var extend = __webpack_require__(510);
-var not = __webpack_require__(512);
+var define = __webpack_require__(503);
+var extend = __webpack_require__(511);
+var not = __webpack_require__(513);
var MAX_LENGTH = 1024 * 64;
/**
@@ -48012,7 +48102,7 @@ module.exports.makeRe = makeRe;
/***/ }),
-/* 502 */
+/* 503 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -48025,7 +48115,7 @@ module.exports.makeRe = makeRe;
-var isDescriptor = __webpack_require__(503);
+var isDescriptor = __webpack_require__(504);
module.exports = function defineProperty(obj, prop, val) {
if (typeof obj !== 'object' && typeof obj !== 'function') {
@@ -48050,7 +48140,7 @@ module.exports = function defineProperty(obj, prop, val) {
/***/ }),
-/* 503 */
+/* 504 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -48063,9 +48153,9 @@ module.exports = function defineProperty(obj, prop, val) {
-var typeOf = __webpack_require__(504);
-var isAccessor = __webpack_require__(505);
-var isData = __webpack_require__(508);
+var typeOf = __webpack_require__(505);
+var isAccessor = __webpack_require__(506);
+var isData = __webpack_require__(509);
module.exports = function isDescriptor(obj, key) {
if (typeOf(obj) !== 'object') {
@@ -48079,7 +48169,7 @@ module.exports = function isDescriptor(obj, key) {
/***/ }),
-/* 504 */
+/* 505 */
/***/ (function(module, exports) {
var toString = Object.prototype.toString;
@@ -48232,7 +48322,7 @@ function isBuffer(val) {
/***/ }),
-/* 505 */
+/* 506 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -48245,7 +48335,7 @@ function isBuffer(val) {
-var typeOf = __webpack_require__(506);
+var typeOf = __webpack_require__(507);
// accessor descriptor properties
var accessor = {
@@ -48308,10 +48398,10 @@ module.exports = isAccessorDescriptor;
/***/ }),
-/* 506 */
+/* 507 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(507);
+var isBuffer = __webpack_require__(508);
var toString = Object.prototype.toString;
/**
@@ -48430,7 +48520,7 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 507 */
+/* 508 */
/***/ (function(module, exports) {
/*!
@@ -48457,7 +48547,7 @@ function isSlowBuffer (obj) {
/***/ }),
-/* 508 */
+/* 509 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -48470,7 +48560,7 @@ function isSlowBuffer (obj) {
-var typeOf = __webpack_require__(509);
+var typeOf = __webpack_require__(510);
// data descriptor properties
var data = {
@@ -48519,10 +48609,10 @@ module.exports = isDataDescriptor;
/***/ }),
-/* 509 */
+/* 510 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(507);
+var isBuffer = __webpack_require__(508);
var toString = Object.prototype.toString;
/**
@@ -48641,13 +48731,13 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 510 */
+/* 511 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isObject = __webpack_require__(511);
+var isObject = __webpack_require__(512);
module.exports = function extend(o/*, objects*/) {
if (!isObject(o)) { o = {}; }
@@ -48681,7 +48771,7 @@ function hasOwn(obj, key) {
/***/ }),
-/* 511 */
+/* 512 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -48701,13 +48791,13 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 512 */
+/* 513 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var extend = __webpack_require__(510);
+var extend = __webpack_require__(511);
/**
* The main export is a function that takes a `pattern` string and an `options` object.
@@ -48774,7 +48864,7 @@ module.exports = toRegex;
/***/ }),
-/* 513 */
+/* 514 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -48824,13 +48914,13 @@ module.exports.immutable = function uniqueImmutable(arr) {
/***/ }),
-/* 514 */
+/* 515 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(515);
+var utils = __webpack_require__(516);
module.exports = function(braces, options) {
braces.compiler
@@ -49113,25 +49203,25 @@ function hasQueue(node) {
/***/ }),
-/* 515 */
+/* 516 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var splitString = __webpack_require__(516);
+var splitString = __webpack_require__(517);
var utils = module.exports;
/**
* Module dependencies
*/
-utils.extend = __webpack_require__(510);
-utils.flatten = __webpack_require__(522);
-utils.isObject = __webpack_require__(520);
-utils.fillRange = __webpack_require__(523);
-utils.repeat = __webpack_require__(528);
-utils.unique = __webpack_require__(513);
+utils.extend = __webpack_require__(511);
+utils.flatten = __webpack_require__(523);
+utils.isObject = __webpack_require__(521);
+utils.fillRange = __webpack_require__(524);
+utils.repeat = __webpack_require__(529);
+utils.unique = __webpack_require__(514);
utils.define = function(obj, key, val) {
Object.defineProperty(obj, key, {
@@ -49463,7 +49553,7 @@ utils.escapeRegex = function(str) {
/***/ }),
-/* 516 */
+/* 517 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -49476,7 +49566,7 @@ utils.escapeRegex = function(str) {
-var extend = __webpack_require__(517);
+var extend = __webpack_require__(518);
module.exports = function(str, options, fn) {
if (typeof str !== 'string') {
@@ -49641,14 +49731,14 @@ function keepEscaping(opts, str, idx) {
/***/ }),
-/* 517 */
+/* 518 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(518);
-var assignSymbols = __webpack_require__(521);
+var isExtendable = __webpack_require__(519);
+var assignSymbols = __webpack_require__(522);
module.exports = Object.assign || function(obj/*, objects*/) {
if (obj === null || typeof obj === 'undefined') {
@@ -49708,7 +49798,7 @@ function isEnum(obj, key) {
/***/ }),
-/* 518 */
+/* 519 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -49721,7 +49811,7 @@ function isEnum(obj, key) {
-var isPlainObject = __webpack_require__(519);
+var isPlainObject = __webpack_require__(520);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -49729,7 +49819,7 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 519 */
+/* 520 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -49742,7 +49832,7 @@ module.exports = function isExtendable(val) {
-var isObject = __webpack_require__(520);
+var isObject = __webpack_require__(521);
function isObjectObject(o) {
return isObject(o) === true
@@ -49773,7 +49863,7 @@ module.exports = function isPlainObject(o) {
/***/ }),
-/* 520 */
+/* 521 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -49792,7 +49882,7 @@ module.exports = function isObject(val) {
/***/ }),
-/* 521 */
+/* 522 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -49839,7 +49929,7 @@ module.exports = function(receiver, objects) {
/***/ }),
-/* 522 */
+/* 523 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -49868,7 +49958,7 @@ function flat(arr, res) {
/***/ }),
-/* 523 */
+/* 524 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -49882,10 +49972,10 @@ function flat(arr, res) {
var util = __webpack_require__(29);
-var isNumber = __webpack_require__(524);
-var extend = __webpack_require__(510);
-var repeat = __webpack_require__(526);
-var toRegex = __webpack_require__(527);
+var isNumber = __webpack_require__(525);
+var extend = __webpack_require__(511);
+var repeat = __webpack_require__(527);
+var toRegex = __webpack_require__(528);
/**
* Return a range of numbers or letters.
@@ -50083,7 +50173,7 @@ module.exports = fillRange;
/***/ }),
-/* 524 */
+/* 525 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -50096,7 +50186,7 @@ module.exports = fillRange;
-var typeOf = __webpack_require__(525);
+var typeOf = __webpack_require__(526);
module.exports = function isNumber(num) {
var type = typeOf(num);
@@ -50112,10 +50202,10 @@ module.exports = function isNumber(num) {
/***/ }),
-/* 525 */
+/* 526 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(507);
+var isBuffer = __webpack_require__(508);
var toString = Object.prototype.toString;
/**
@@ -50234,7 +50324,7 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 526 */
+/* 527 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -50311,7 +50401,7 @@ function repeat(str, num) {
/***/ }),
-/* 527 */
+/* 528 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -50324,8 +50414,8 @@ function repeat(str, num) {
-var repeat = __webpack_require__(526);
-var isNumber = __webpack_require__(524);
+var repeat = __webpack_require__(527);
+var isNumber = __webpack_require__(525);
var cache = {};
function toRegexRange(min, max, options) {
@@ -50612,7 +50702,7 @@ module.exports = toRegexRange;
/***/ }),
-/* 528 */
+/* 529 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -50637,14 +50727,14 @@ module.exports = function repeat(ele, num) {
/***/ }),
-/* 529 */
+/* 530 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var Node = __webpack_require__(530);
-var utils = __webpack_require__(515);
+var Node = __webpack_require__(531);
+var utils = __webpack_require__(516);
/**
* Braces parsers
@@ -51004,15 +51094,15 @@ function concatNodes(pos, node, parent, options) {
/***/ }),
-/* 530 */
+/* 531 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isObject = __webpack_require__(520);
-var define = __webpack_require__(531);
-var utils = __webpack_require__(538);
+var isObject = __webpack_require__(521);
+var define = __webpack_require__(532);
+var utils = __webpack_require__(539);
var ownNames;
/**
@@ -51503,7 +51593,7 @@ exports = module.exports = Node;
/***/ }),
-/* 531 */
+/* 532 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -51516,7 +51606,7 @@ exports = module.exports = Node;
-var isDescriptor = __webpack_require__(532);
+var isDescriptor = __webpack_require__(533);
module.exports = function defineProperty(obj, prop, val) {
if (typeof obj !== 'object' && typeof obj !== 'function') {
@@ -51541,7 +51631,7 @@ module.exports = function defineProperty(obj, prop, val) {
/***/ }),
-/* 532 */
+/* 533 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -51554,9 +51644,9 @@ module.exports = function defineProperty(obj, prop, val) {
-var typeOf = __webpack_require__(533);
-var isAccessor = __webpack_require__(534);
-var isData = __webpack_require__(536);
+var typeOf = __webpack_require__(534);
+var isAccessor = __webpack_require__(535);
+var isData = __webpack_require__(537);
module.exports = function isDescriptor(obj, key) {
if (typeOf(obj) !== 'object') {
@@ -51569,219 +51659,8 @@ module.exports = function isDescriptor(obj, key) {
};
-/***/ }),
-/* 533 */
-/***/ (function(module, exports) {
-
-var toString = Object.prototype.toString;
-
-module.exports = function kindOf(val) {
- if (val === void 0) return 'undefined';
- if (val === null) return 'null';
-
- var type = typeof val;
- if (type === 'boolean') return 'boolean';
- if (type === 'string') return 'string';
- if (type === 'number') return 'number';
- if (type === 'symbol') return 'symbol';
- if (type === 'function') {
- return isGeneratorFn(val) ? 'generatorfunction' : 'function';
- }
-
- if (isArray(val)) return 'array';
- if (isBuffer(val)) return 'buffer';
- if (isArguments(val)) return 'arguments';
- if (isDate(val)) return 'date';
- if (isError(val)) return 'error';
- if (isRegexp(val)) return 'regexp';
-
- switch (ctorName(val)) {
- case 'Symbol': return 'symbol';
- case 'Promise': return 'promise';
-
- // Set, Map, WeakSet, WeakMap
- case 'WeakMap': return 'weakmap';
- case 'WeakSet': return 'weakset';
- case 'Map': return 'map';
- case 'Set': return 'set';
-
- // 8-bit typed arrays
- case 'Int8Array': return 'int8array';
- case 'Uint8Array': return 'uint8array';
- case 'Uint8ClampedArray': return 'uint8clampedarray';
-
- // 16-bit typed arrays
- case 'Int16Array': return 'int16array';
- case 'Uint16Array': return 'uint16array';
-
- // 32-bit typed arrays
- case 'Int32Array': return 'int32array';
- case 'Uint32Array': return 'uint32array';
- case 'Float32Array': return 'float32array';
- case 'Float64Array': return 'float64array';
- }
-
- if (isGeneratorObj(val)) {
- return 'generator';
- }
-
- // Non-plain objects
- type = toString.call(val);
- switch (type) {
- case '[object Object]': return 'object';
- // iterators
- case '[object Map Iterator]': return 'mapiterator';
- case '[object Set Iterator]': return 'setiterator';
- case '[object String Iterator]': return 'stringiterator';
- case '[object Array Iterator]': return 'arrayiterator';
- }
-
- // other
- return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
-};
-
-function ctorName(val) {
- return val.constructor ? val.constructor.name : null;
-}
-
-function isArray(val) {
- if (Array.isArray) return Array.isArray(val);
- return val instanceof Array;
-}
-
-function isError(val) {
- return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
-}
-
-function isDate(val) {
- if (val instanceof Date) return true;
- return typeof val.toDateString === 'function'
- && typeof val.getDate === 'function'
- && typeof val.setDate === 'function';
-}
-
-function isRegexp(val) {
- if (val instanceof RegExp) return true;
- return typeof val.flags === 'string'
- && typeof val.ignoreCase === 'boolean'
- && typeof val.multiline === 'boolean'
- && typeof val.global === 'boolean';
-}
-
-function isGeneratorFn(name, val) {
- return ctorName(name) === 'GeneratorFunction';
-}
-
-function isGeneratorObj(val) {
- return typeof val.throw === 'function'
- && typeof val.return === 'function'
- && typeof val.next === 'function';
-}
-
-function isArguments(val) {
- try {
- if (typeof val.length === 'number' && typeof val.callee === 'function') {
- return true;
- }
- } catch (err) {
- if (err.message.indexOf('callee') !== -1) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * If you need to support Safari 5-7 (8-10 yr-old browser),
- * take a look at https://github.com/feross/is-buffer
- */
-
-function isBuffer(val) {
- if (val.constructor && typeof val.constructor.isBuffer === 'function') {
- return val.constructor.isBuffer(val);
- }
- return false;
-}
-
-
/***/ }),
/* 534 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-/*!
- * is-accessor-descriptor
- *
- * Copyright (c) 2015-2017, Jon Schlinkert.
- * Released under the MIT License.
- */
-
-
-
-var typeOf = __webpack_require__(535);
-
-// accessor descriptor properties
-var accessor = {
- get: 'function',
- set: 'function',
- configurable: 'boolean',
- enumerable: 'boolean'
-};
-
-function isAccessorDescriptor(obj, prop) {
- if (typeof prop === 'string') {
- var val = Object.getOwnPropertyDescriptor(obj, prop);
- return typeof val !== 'undefined';
- }
-
- if (typeOf(obj) !== 'object') {
- return false;
- }
-
- if (has(obj, 'value') || has(obj, 'writable')) {
- return false;
- }
-
- if (!has(obj, 'get') || typeof obj.get !== 'function') {
- return false;
- }
-
- // tldr: it's valid to have "set" be undefined
- // "set" might be undefined if `Object.getOwnPropertyDescriptor`
- // was used to get the value, and only `get` was defined by the user
- if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') {
- return false;
- }
-
- for (var key in obj) {
- if (!accessor.hasOwnProperty(key)) {
- continue;
- }
-
- if (typeOf(obj[key]) === accessor[key]) {
- continue;
- }
-
- if (typeof obj[key] !== 'undefined') {
- return false;
- }
- }
- return true;
-}
-
-function has(obj, key) {
- return {}.hasOwnProperty.call(obj, key);
-}
-
-/**
- * Expose `isAccessorDescriptor`
- */
-
-module.exports = isAccessorDescriptor;
-
-
-/***/ }),
-/* 535 */
/***/ (function(module, exports) {
var toString = Object.prototype.toString;
@@ -51915,8 +51794,219 @@ function isBuffer(val) {
}
+/***/ }),
+/* 535 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*!
+ * is-accessor-descriptor
+ *
+ * Copyright (c) 2015-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+
+
+var typeOf = __webpack_require__(536);
+
+// accessor descriptor properties
+var accessor = {
+ get: 'function',
+ set: 'function',
+ configurable: 'boolean',
+ enumerable: 'boolean'
+};
+
+function isAccessorDescriptor(obj, prop) {
+ if (typeof prop === 'string') {
+ var val = Object.getOwnPropertyDescriptor(obj, prop);
+ return typeof val !== 'undefined';
+ }
+
+ if (typeOf(obj) !== 'object') {
+ return false;
+ }
+
+ if (has(obj, 'value') || has(obj, 'writable')) {
+ return false;
+ }
+
+ if (!has(obj, 'get') || typeof obj.get !== 'function') {
+ return false;
+ }
+
+ // tldr: it's valid to have "set" be undefined
+ // "set" might be undefined if `Object.getOwnPropertyDescriptor`
+ // was used to get the value, and only `get` was defined by the user
+ if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') {
+ return false;
+ }
+
+ for (var key in obj) {
+ if (!accessor.hasOwnProperty(key)) {
+ continue;
+ }
+
+ if (typeOf(obj[key]) === accessor[key]) {
+ continue;
+ }
+
+ if (typeof obj[key] !== 'undefined') {
+ return false;
+ }
+ }
+ return true;
+}
+
+function has(obj, key) {
+ return {}.hasOwnProperty.call(obj, key);
+}
+
+/**
+ * Expose `isAccessorDescriptor`
+ */
+
+module.exports = isAccessorDescriptor;
+
+
/***/ }),
/* 536 */
+/***/ (function(module, exports) {
+
+var toString = Object.prototype.toString;
+
+module.exports = function kindOf(val) {
+ if (val === void 0) return 'undefined';
+ if (val === null) return 'null';
+
+ var type = typeof val;
+ if (type === 'boolean') return 'boolean';
+ if (type === 'string') return 'string';
+ if (type === 'number') return 'number';
+ if (type === 'symbol') return 'symbol';
+ if (type === 'function') {
+ return isGeneratorFn(val) ? 'generatorfunction' : 'function';
+ }
+
+ if (isArray(val)) return 'array';
+ if (isBuffer(val)) return 'buffer';
+ if (isArguments(val)) return 'arguments';
+ if (isDate(val)) return 'date';
+ if (isError(val)) return 'error';
+ if (isRegexp(val)) return 'regexp';
+
+ switch (ctorName(val)) {
+ case 'Symbol': return 'symbol';
+ case 'Promise': return 'promise';
+
+ // Set, Map, WeakSet, WeakMap
+ case 'WeakMap': return 'weakmap';
+ case 'WeakSet': return 'weakset';
+ case 'Map': return 'map';
+ case 'Set': return 'set';
+
+ // 8-bit typed arrays
+ case 'Int8Array': return 'int8array';
+ case 'Uint8Array': return 'uint8array';
+ case 'Uint8ClampedArray': return 'uint8clampedarray';
+
+ // 16-bit typed arrays
+ case 'Int16Array': return 'int16array';
+ case 'Uint16Array': return 'uint16array';
+
+ // 32-bit typed arrays
+ case 'Int32Array': return 'int32array';
+ case 'Uint32Array': return 'uint32array';
+ case 'Float32Array': return 'float32array';
+ case 'Float64Array': return 'float64array';
+ }
+
+ if (isGeneratorObj(val)) {
+ return 'generator';
+ }
+
+ // Non-plain objects
+ type = toString.call(val);
+ switch (type) {
+ case '[object Object]': return 'object';
+ // iterators
+ case '[object Map Iterator]': return 'mapiterator';
+ case '[object Set Iterator]': return 'setiterator';
+ case '[object String Iterator]': return 'stringiterator';
+ case '[object Array Iterator]': return 'arrayiterator';
+ }
+
+ // other
+ return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
+};
+
+function ctorName(val) {
+ return val.constructor ? val.constructor.name : null;
+}
+
+function isArray(val) {
+ if (Array.isArray) return Array.isArray(val);
+ return val instanceof Array;
+}
+
+function isError(val) {
+ return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
+}
+
+function isDate(val) {
+ if (val instanceof Date) return true;
+ return typeof val.toDateString === 'function'
+ && typeof val.getDate === 'function'
+ && typeof val.setDate === 'function';
+}
+
+function isRegexp(val) {
+ if (val instanceof RegExp) return true;
+ return typeof val.flags === 'string'
+ && typeof val.ignoreCase === 'boolean'
+ && typeof val.multiline === 'boolean'
+ && typeof val.global === 'boolean';
+}
+
+function isGeneratorFn(name, val) {
+ return ctorName(name) === 'GeneratorFunction';
+}
+
+function isGeneratorObj(val) {
+ return typeof val.throw === 'function'
+ && typeof val.return === 'function'
+ && typeof val.next === 'function';
+}
+
+function isArguments(val) {
+ try {
+ if (typeof val.length === 'number' && typeof val.callee === 'function') {
+ return true;
+ }
+ } catch (err) {
+ if (err.message.indexOf('callee') !== -1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+ if (val.constructor && typeof val.constructor.isBuffer === 'function') {
+ return val.constructor.isBuffer(val);
+ }
+ return false;
+}
+
+
+/***/ }),
+/* 537 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -51929,7 +52019,7 @@ function isBuffer(val) {
-var typeOf = __webpack_require__(537);
+var typeOf = __webpack_require__(538);
module.exports = function isDataDescriptor(obj, prop) {
// data descriptor properties
@@ -51972,7 +52062,7 @@ module.exports = function isDataDescriptor(obj, prop) {
/***/ }),
-/* 537 */
+/* 538 */
/***/ (function(module, exports) {
var toString = Object.prototype.toString;
@@ -52107,13 +52197,13 @@ function isBuffer(val) {
/***/ }),
-/* 538 */
+/* 539 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var typeOf = __webpack_require__(525);
+var typeOf = __webpack_require__(526);
var utils = module.exports;
/**
@@ -53133,17 +53223,17 @@ function assert(val, message) {
/***/ }),
-/* 539 */
+/* 540 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var extend = __webpack_require__(510);
-var Snapdragon = __webpack_require__(540);
-var compilers = __webpack_require__(514);
-var parsers = __webpack_require__(529);
-var utils = __webpack_require__(515);
+var extend = __webpack_require__(511);
+var Snapdragon = __webpack_require__(541);
+var compilers = __webpack_require__(515);
+var parsers = __webpack_require__(530);
+var utils = __webpack_require__(516);
/**
* Customize Snapdragon parser and renderer
@@ -53244,17 +53334,17 @@ module.exports = Braces;
/***/ }),
-/* 540 */
+/* 541 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var Base = __webpack_require__(541);
-var define = __webpack_require__(502);
-var Compiler = __webpack_require__(570);
-var Parser = __webpack_require__(600);
-var utils = __webpack_require__(580);
+var Base = __webpack_require__(542);
+var define = __webpack_require__(503);
+var Compiler = __webpack_require__(571);
+var Parser = __webpack_require__(601);
+var utils = __webpack_require__(581);
var regexCache = {};
var cache = {};
@@ -53425,20 +53515,20 @@ module.exports.Parser = Parser;
/***/ }),
-/* 541 */
+/* 542 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(29);
-var define = __webpack_require__(542);
-var CacheBase = __webpack_require__(543);
-var Emitter = __webpack_require__(544);
-var isObject = __webpack_require__(520);
-var merge = __webpack_require__(561);
-var pascal = __webpack_require__(564);
-var cu = __webpack_require__(565);
+var define = __webpack_require__(543);
+var CacheBase = __webpack_require__(544);
+var Emitter = __webpack_require__(545);
+var isObject = __webpack_require__(521);
+var merge = __webpack_require__(562);
+var pascal = __webpack_require__(565);
+var cu = __webpack_require__(566);
/**
* Optionally define a custom `cache` namespace to use.
@@ -53867,7 +53957,7 @@ module.exports.namespace = namespace;
/***/ }),
-/* 542 */
+/* 543 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -53880,7 +53970,7 @@ module.exports.namespace = namespace;
-var isDescriptor = __webpack_require__(532);
+var isDescriptor = __webpack_require__(533);
module.exports = function defineProperty(obj, prop, val) {
if (typeof obj !== 'object' && typeof obj !== 'function') {
@@ -53905,21 +53995,21 @@ module.exports = function defineProperty(obj, prop, val) {
/***/ }),
-/* 543 */
+/* 544 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isObject = __webpack_require__(520);
-var Emitter = __webpack_require__(544);
-var visit = __webpack_require__(545);
-var toPath = __webpack_require__(548);
-var union = __webpack_require__(549);
-var del = __webpack_require__(553);
-var get = __webpack_require__(551);
-var has = __webpack_require__(558);
-var set = __webpack_require__(552);
+var isObject = __webpack_require__(521);
+var Emitter = __webpack_require__(545);
+var visit = __webpack_require__(546);
+var toPath = __webpack_require__(549);
+var union = __webpack_require__(550);
+var del = __webpack_require__(554);
+var get = __webpack_require__(552);
+var has = __webpack_require__(559);
+var set = __webpack_require__(553);
/**
* Create a `Cache` constructor that when instantiated will
@@ -54173,7 +54263,7 @@ module.exports.namespace = namespace;
/***/ }),
-/* 544 */
+/* 545 */
/***/ (function(module, exports, __webpack_require__) {
@@ -54342,7 +54432,7 @@ Emitter.prototype.hasListeners = function(event){
/***/ }),
-/* 545 */
+/* 546 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54355,8 +54445,8 @@ Emitter.prototype.hasListeners = function(event){
-var visit = __webpack_require__(546);
-var mapVisit = __webpack_require__(547);
+var visit = __webpack_require__(547);
+var mapVisit = __webpack_require__(548);
module.exports = function(collection, method, val) {
var result;
@@ -54379,7 +54469,7 @@ module.exports = function(collection, method, val) {
/***/ }),
-/* 546 */
+/* 547 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54392,7 +54482,7 @@ module.exports = function(collection, method, val) {
-var isObject = __webpack_require__(520);
+var isObject = __webpack_require__(521);
module.exports = function visit(thisArg, method, target, val) {
if (!isObject(thisArg) && typeof thisArg !== 'function') {
@@ -54419,14 +54509,14 @@ module.exports = function visit(thisArg, method, target, val) {
/***/ }),
-/* 547 */
+/* 548 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(29);
-var visit = __webpack_require__(546);
+var visit = __webpack_require__(547);
/**
* Map `visit` over an array of objects.
@@ -54463,7 +54553,7 @@ function isObject(val) {
/***/ }),
-/* 548 */
+/* 549 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54476,7 +54566,7 @@ function isObject(val) {
-var typeOf = __webpack_require__(525);
+var typeOf = __webpack_require__(526);
module.exports = function toPath(args) {
if (typeOf(args) !== 'arguments') {
@@ -54503,16 +54593,16 @@ function filter(arr) {
/***/ }),
-/* 549 */
+/* 550 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isObject = __webpack_require__(511);
-var union = __webpack_require__(550);
-var get = __webpack_require__(551);
-var set = __webpack_require__(552);
+var isObject = __webpack_require__(512);
+var union = __webpack_require__(551);
+var get = __webpack_require__(552);
+var set = __webpack_require__(553);
module.exports = function unionValue(obj, prop, value) {
if (!isObject(obj)) {
@@ -54540,7 +54630,7 @@ function arrayify(val) {
/***/ }),
-/* 550 */
+/* 551 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54576,7 +54666,7 @@ module.exports = function union(init) {
/***/ }),
-/* 551 */
+/* 552 */
/***/ (function(module, exports) {
/*!
@@ -54632,7 +54722,7 @@ function toString(val) {
/***/ }),
-/* 552 */
+/* 553 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54645,10 +54735,10 @@ function toString(val) {
-var split = __webpack_require__(516);
-var extend = __webpack_require__(510);
-var isPlainObject = __webpack_require__(519);
-var isObject = __webpack_require__(511);
+var split = __webpack_require__(517);
+var extend = __webpack_require__(511);
+var isPlainObject = __webpack_require__(520);
+var isObject = __webpack_require__(512);
module.exports = function(obj, prop, val) {
if (!isObject(obj)) {
@@ -54694,7 +54784,7 @@ function isValidKey(key) {
/***/ }),
-/* 553 */
+/* 554 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54707,8 +54797,8 @@ function isValidKey(key) {
-var isObject = __webpack_require__(520);
-var has = __webpack_require__(554);
+var isObject = __webpack_require__(521);
+var has = __webpack_require__(555);
module.exports = function unset(obj, prop) {
if (!isObject(obj)) {
@@ -54733,7 +54823,7 @@ module.exports = function unset(obj, prop) {
/***/ }),
-/* 554 */
+/* 555 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54746,9 +54836,9 @@ module.exports = function unset(obj, prop) {
-var isObject = __webpack_require__(555);
-var hasValues = __webpack_require__(557);
-var get = __webpack_require__(551);
+var isObject = __webpack_require__(556);
+var hasValues = __webpack_require__(558);
+var get = __webpack_require__(552);
module.exports = function(obj, prop, noZero) {
if (isObject(obj)) {
@@ -54759,7 +54849,7 @@ module.exports = function(obj, prop, noZero) {
/***/ }),
-/* 555 */
+/* 556 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54772,7 +54862,7 @@ module.exports = function(obj, prop, noZero) {
-var isArray = __webpack_require__(556);
+var isArray = __webpack_require__(557);
module.exports = function isObject(val) {
return val != null && typeof val === 'object' && isArray(val) === false;
@@ -54780,7 +54870,7 @@ module.exports = function isObject(val) {
/***/ }),
-/* 556 */
+/* 557 */
/***/ (function(module, exports) {
var toString = {}.toString;
@@ -54791,7 +54881,7 @@ module.exports = Array.isArray || function (arr) {
/***/ }),
-/* 557 */
+/* 558 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54834,7 +54924,7 @@ module.exports = function hasValue(o, noZero) {
/***/ }),
-/* 558 */
+/* 559 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54847,9 +54937,9 @@ module.exports = function hasValue(o, noZero) {
-var isObject = __webpack_require__(520);
-var hasValues = __webpack_require__(559);
-var get = __webpack_require__(551);
+var isObject = __webpack_require__(521);
+var hasValues = __webpack_require__(560);
+var get = __webpack_require__(552);
module.exports = function(val, prop) {
return hasValues(isObject(val) && prop ? get(val, prop) : val);
@@ -54857,7 +54947,7 @@ module.exports = function(val, prop) {
/***/ }),
-/* 559 */
+/* 560 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54870,8 +54960,8 @@ module.exports = function(val, prop) {
-var typeOf = __webpack_require__(560);
-var isNumber = __webpack_require__(524);
+var typeOf = __webpack_require__(561);
+var isNumber = __webpack_require__(525);
module.exports = function hasValue(val) {
// is-number checks for NaN and other edge cases
@@ -54924,10 +55014,10 @@ module.exports = function hasValue(val) {
/***/ }),
-/* 560 */
+/* 561 */
/***/ (function(module, exports, __webpack_require__) {
-var isBuffer = __webpack_require__(507);
+var isBuffer = __webpack_require__(508);
var toString = Object.prototype.toString;
/**
@@ -55049,14 +55139,14 @@ module.exports = function kindOf(val) {
/***/ }),
-/* 561 */
+/* 562 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(562);
-var forIn = __webpack_require__(563);
+var isExtendable = __webpack_require__(563);
+var forIn = __webpack_require__(564);
function mixinDeep(target, objects) {
var len = arguments.length, i = 0;
@@ -55120,7 +55210,7 @@ module.exports = mixinDeep;
/***/ }),
-/* 562 */
+/* 563 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55133,7 +55223,7 @@ module.exports = mixinDeep;
-var isPlainObject = __webpack_require__(519);
+var isPlainObject = __webpack_require__(520);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -55141,7 +55231,7 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 563 */
+/* 564 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55164,7 +55254,7 @@ module.exports = function forIn(obj, fn, thisArg) {
/***/ }),
-/* 564 */
+/* 565 */
/***/ (function(module, exports) {
/*!
@@ -55191,14 +55281,14 @@ module.exports = pascalcase;
/***/ }),
-/* 565 */
+/* 566 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(29);
-var utils = __webpack_require__(566);
+var utils = __webpack_require__(567);
/**
* Expose class utils
@@ -55563,7 +55653,7 @@ cu.bubble = function(Parent, events) {
/***/ }),
-/* 566 */
+/* 567 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55577,10 +55667,10 @@ var utils = {};
* Lazily required module dependencies
*/
-utils.union = __webpack_require__(550);
-utils.define = __webpack_require__(502);
-utils.isObj = __webpack_require__(520);
-utils.staticExtend = __webpack_require__(567);
+utils.union = __webpack_require__(551);
+utils.define = __webpack_require__(503);
+utils.isObj = __webpack_require__(521);
+utils.staticExtend = __webpack_require__(568);
/**
@@ -55591,7 +55681,7 @@ module.exports = utils;
/***/ }),
-/* 567 */
+/* 568 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55604,8 +55694,8 @@ module.exports = utils;
-var copy = __webpack_require__(568);
-var define = __webpack_require__(502);
+var copy = __webpack_require__(569);
+var define = __webpack_require__(503);
var util = __webpack_require__(29);
/**
@@ -55688,15 +55778,15 @@ module.exports = extend;
/***/ }),
-/* 568 */
+/* 569 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var typeOf = __webpack_require__(525);
-var copyDescriptor = __webpack_require__(569);
-var define = __webpack_require__(502);
+var typeOf = __webpack_require__(526);
+var copyDescriptor = __webpack_require__(570);
+var define = __webpack_require__(503);
/**
* Copy static properties, prototype properties, and descriptors from one object to another.
@@ -55869,7 +55959,7 @@ module.exports.has = has;
/***/ }),
-/* 569 */
+/* 570 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55957,16 +56047,16 @@ function isObject(val) {
/***/ }),
-/* 570 */
+/* 571 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var use = __webpack_require__(571);
-var define = __webpack_require__(502);
-var debug = __webpack_require__(573)('snapdragon:compiler');
-var utils = __webpack_require__(580);
+var use = __webpack_require__(572);
+var define = __webpack_require__(503);
+var debug = __webpack_require__(574)('snapdragon:compiler');
+var utils = __webpack_require__(581);
/**
* Create a new `Compiler` with the given `options`.
@@ -56120,7 +56210,7 @@ Compiler.prototype = {
// source map support
if (opts.sourcemap) {
- var sourcemaps = __webpack_require__(599);
+ var sourcemaps = __webpack_require__(600);
sourcemaps(this);
this.mapVisit(this.ast.nodes);
this.applySourceMaps();
@@ -56141,7 +56231,7 @@ module.exports = Compiler;
/***/ }),
-/* 571 */
+/* 572 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -56154,7 +56244,7 @@ module.exports = Compiler;
-var utils = __webpack_require__(572);
+var utils = __webpack_require__(573);
module.exports = function base(app, opts) {
if (!utils.isObject(app) && typeof app !== 'function') {
@@ -56269,7 +56359,7 @@ module.exports = function base(app, opts) {
/***/ }),
-/* 572 */
+/* 573 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -56283,8 +56373,8 @@ var utils = {};
* Lazily required module dependencies
*/
-utils.define = __webpack_require__(502);
-utils.isObject = __webpack_require__(520);
+utils.define = __webpack_require__(503);
+utils.isObject = __webpack_require__(521);
utils.isString = function(val) {
@@ -56299,7 +56389,7 @@ module.exports = utils;
/***/ }),
-/* 573 */
+/* 574 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -56308,14 +56398,14 @@ module.exports = utils;
*/
if (typeof process !== 'undefined' && process.type === 'renderer') {
- module.exports = __webpack_require__(574);
+ module.exports = __webpack_require__(575);
} else {
- module.exports = __webpack_require__(577);
+ module.exports = __webpack_require__(578);
}
/***/ }),
-/* 574 */
+/* 575 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -56324,7 +56414,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') {
* Expose `debug()` as the module.
*/
-exports = module.exports = __webpack_require__(575);
+exports = module.exports = __webpack_require__(576);
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
@@ -56506,7 +56596,7 @@ function localstorage() {
/***/ }),
-/* 575 */
+/* 576 */
/***/ (function(module, exports, __webpack_require__) {
@@ -56522,7 +56612,7 @@ exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
-exports.humanize = __webpack_require__(576);
+exports.humanize = __webpack_require__(577);
/**
* The currently active debug mode names, and names to skip.
@@ -56714,7 +56804,7 @@ function coerce(val) {
/***/ }),
-/* 576 */
+/* 577 */
/***/ (function(module, exports) {
/**
@@ -56872,14 +56962,14 @@ function plural(ms, n, name) {
/***/ }),
-/* 577 */
+/* 578 */
/***/ (function(module, exports, __webpack_require__) {
/**
* Module dependencies.
*/
-var tty = __webpack_require__(578);
+var tty = __webpack_require__(579);
var util = __webpack_require__(29);
/**
@@ -56888,7 +56978,7 @@ var util = __webpack_require__(29);
* Expose `debug()` as the module.
*/
-exports = module.exports = __webpack_require__(575);
+exports = module.exports = __webpack_require__(576);
exports.init = init;
exports.log = log;
exports.formatArgs = formatArgs;
@@ -57067,7 +57157,7 @@ function createWritableStdioStream (fd) {
case 'PIPE':
case 'TCP':
- var net = __webpack_require__(579);
+ var net = __webpack_require__(580);
stream = new net.Socket({
fd: fd,
readable: false,
@@ -57126,19 +57216,19 @@ exports.enable(load());
/***/ }),
-/* 578 */
+/* 579 */
/***/ (function(module, exports) {
module.exports = require("tty");
/***/ }),
-/* 579 */
+/* 580 */
/***/ (function(module, exports) {
module.exports = require("net");
/***/ }),
-/* 580 */
+/* 581 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -57148,9 +57238,9 @@ module.exports = require("net");
* Module dependencies
*/
-exports.extend = __webpack_require__(510);
-exports.SourceMap = __webpack_require__(581);
-exports.sourceMapResolve = __webpack_require__(592);
+exports.extend = __webpack_require__(511);
+exports.SourceMap = __webpack_require__(582);
+exports.sourceMapResolve = __webpack_require__(593);
/**
* Convert backslash in the given string to forward slashes
@@ -57193,7 +57283,7 @@ exports.last = function(arr, n) {
/***/ }),
-/* 581 */
+/* 582 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -57201,13 +57291,13 @@ exports.last = function(arr, n) {
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
-exports.SourceMapGenerator = __webpack_require__(582).SourceMapGenerator;
-exports.SourceMapConsumer = __webpack_require__(588).SourceMapConsumer;
-exports.SourceNode = __webpack_require__(591).SourceNode;
+exports.SourceMapGenerator = __webpack_require__(583).SourceMapGenerator;
+exports.SourceMapConsumer = __webpack_require__(589).SourceMapConsumer;
+exports.SourceNode = __webpack_require__(592).SourceNode;
/***/ }),
-/* 582 */
+/* 583 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -57217,10 +57307,10 @@ exports.SourceNode = __webpack_require__(591).SourceNode;
* http://opensource.org/licenses/BSD-3-Clause
*/
-var base64VLQ = __webpack_require__(583);
-var util = __webpack_require__(585);
-var ArraySet = __webpack_require__(586).ArraySet;
-var MappingList = __webpack_require__(587).MappingList;
+var base64VLQ = __webpack_require__(584);
+var util = __webpack_require__(586);
+var ArraySet = __webpack_require__(587).ArraySet;
+var MappingList = __webpack_require__(588).MappingList;
/**
* An instance of the SourceMapGenerator represents a source map which is
@@ -57629,7 +57719,7 @@ exports.SourceMapGenerator = SourceMapGenerator;
/***/ }),
-/* 583 */
+/* 584 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -57669,7 +57759,7 @@ exports.SourceMapGenerator = SourceMapGenerator;
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-var base64 = __webpack_require__(584);
+var base64 = __webpack_require__(585);
// A single base 64 digit can contain 6 bits of data. For the base 64 variable
// length quantities we use in the source map spec, the first bit is the sign,
@@ -57775,7 +57865,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {
/***/ }),
-/* 584 */
+/* 585 */
/***/ (function(module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -57848,7 +57938,7 @@ exports.decode = function (charCode) {
/***/ }),
-/* 585 */
+/* 586 */
/***/ (function(module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -58271,7 +58361,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate
/***/ }),
-/* 586 */
+/* 587 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -58281,7 +58371,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate
* http://opensource.org/licenses/BSD-3-Clause
*/
-var util = __webpack_require__(585);
+var util = __webpack_require__(586);
var has = Object.prototype.hasOwnProperty;
var hasNativeMap = typeof Map !== "undefined";
@@ -58398,7 +58488,7 @@ exports.ArraySet = ArraySet;
/***/ }),
-/* 587 */
+/* 588 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -58408,7 +58498,7 @@ exports.ArraySet = ArraySet;
* http://opensource.org/licenses/BSD-3-Clause
*/
-var util = __webpack_require__(585);
+var util = __webpack_require__(586);
/**
* Determine whether mappingB is after mappingA with respect to generated
@@ -58483,7 +58573,7 @@ exports.MappingList = MappingList;
/***/ }),
-/* 588 */
+/* 589 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -58493,11 +58583,11 @@ exports.MappingList = MappingList;
* http://opensource.org/licenses/BSD-3-Clause
*/
-var util = __webpack_require__(585);
-var binarySearch = __webpack_require__(589);
-var ArraySet = __webpack_require__(586).ArraySet;
-var base64VLQ = __webpack_require__(583);
-var quickSort = __webpack_require__(590).quickSort;
+var util = __webpack_require__(586);
+var binarySearch = __webpack_require__(590);
+var ArraySet = __webpack_require__(587).ArraySet;
+var base64VLQ = __webpack_require__(584);
+var quickSort = __webpack_require__(591).quickSort;
function SourceMapConsumer(aSourceMap) {
var sourceMap = aSourceMap;
@@ -59571,7 +59661,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
/***/ }),
-/* 589 */
+/* 590 */
/***/ (function(module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -59688,7 +59778,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) {
/***/ }),
-/* 590 */
+/* 591 */
/***/ (function(module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -59808,7 +59898,7 @@ exports.quickSort = function (ary, comparator) {
/***/ }),
-/* 591 */
+/* 592 */
/***/ (function(module, exports, __webpack_require__) {
/* -*- Mode: js; js-indent-level: 2; -*- */
@@ -59818,8 +59908,8 @@ exports.quickSort = function (ary, comparator) {
* http://opensource.org/licenses/BSD-3-Clause
*/
-var SourceMapGenerator = __webpack_require__(582).SourceMapGenerator;
-var util = __webpack_require__(585);
+var SourceMapGenerator = __webpack_require__(583).SourceMapGenerator;
+var util = __webpack_require__(586);
// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
// operating systems these days (capturing the result).
@@ -60227,17 +60317,17 @@ exports.SourceNode = SourceNode;
/***/ }),
-/* 592 */
+/* 593 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright 2014, 2015, 2016, 2017 Simon Lydell
// X11 (“MIT”) Licensed. (See LICENSE.)
-var sourceMappingURL = __webpack_require__(593)
-var resolveUrl = __webpack_require__(594)
-var decodeUriComponent = __webpack_require__(595)
-var urix = __webpack_require__(597)
-var atob = __webpack_require__(598)
+var sourceMappingURL = __webpack_require__(594)
+var resolveUrl = __webpack_require__(595)
+var decodeUriComponent = __webpack_require__(596)
+var urix = __webpack_require__(598)
+var atob = __webpack_require__(599)
@@ -60535,7 +60625,7 @@ module.exports = {
/***/ }),
-/* 593 */
+/* 594 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell
@@ -60598,7 +60688,7 @@ void (function(root, factory) {
/***/ }),
-/* 594 */
+/* 595 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright 2014 Simon Lydell
@@ -60616,13 +60706,13 @@ module.exports = resolveUrl
/***/ }),
-/* 595 */
+/* 596 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright 2017 Simon Lydell
// X11 (“MIT”) Licensed. (See LICENSE.)
-var decodeUriComponent = __webpack_require__(596)
+var decodeUriComponent = __webpack_require__(597)
function customDecodeUriComponent(string) {
// `decodeUriComponent` turns `+` into ` `, but that's not wanted.
@@ -60633,7 +60723,7 @@ module.exports = customDecodeUriComponent
/***/ }),
-/* 596 */
+/* 597 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -60734,7 +60824,7 @@ module.exports = function (encodedURI) {
/***/ }),
-/* 597 */
+/* 598 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright 2014 Simon Lydell
@@ -60757,7 +60847,7 @@ module.exports = urix
/***/ }),
-/* 598 */
+/* 599 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -60771,7 +60861,7 @@ module.exports = atob.atob = atob;
/***/ }),
-/* 599 */
+/* 600 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -60779,8 +60869,8 @@ module.exports = atob.atob = atob;
var fs = __webpack_require__(23);
var path = __webpack_require__(16);
-var define = __webpack_require__(502);
-var utils = __webpack_require__(580);
+var define = __webpack_require__(503);
+var utils = __webpack_require__(581);
/**
* Expose `mixin()`.
@@ -60923,19 +61013,19 @@ exports.comment = function(node) {
/***/ }),
-/* 600 */
+/* 601 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var use = __webpack_require__(571);
+var use = __webpack_require__(572);
var util = __webpack_require__(29);
-var Cache = __webpack_require__(601);
-var define = __webpack_require__(502);
-var debug = __webpack_require__(573)('snapdragon:parser');
-var Position = __webpack_require__(602);
-var utils = __webpack_require__(580);
+var Cache = __webpack_require__(602);
+var define = __webpack_require__(503);
+var debug = __webpack_require__(574)('snapdragon:parser');
+var Position = __webpack_require__(603);
+var utils = __webpack_require__(581);
/**
* Create a new `Parser` with the given `input` and `options`.
@@ -61463,7 +61553,7 @@ module.exports = Parser;
/***/ }),
-/* 601 */
+/* 602 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -61570,13 +61660,13 @@ MapCache.prototype.del = function mapDelete(key) {
/***/ }),
-/* 602 */
+/* 603 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var define = __webpack_require__(502);
+var define = __webpack_require__(503);
/**
* Store position for a node
@@ -61591,16 +61681,16 @@ module.exports = function Position(start, parser) {
/***/ }),
-/* 603 */
+/* 604 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var safe = __webpack_require__(604);
-var define = __webpack_require__(610);
-var extend = __webpack_require__(611);
-var not = __webpack_require__(613);
+var safe = __webpack_require__(605);
+var define = __webpack_require__(611);
+var extend = __webpack_require__(612);
+var not = __webpack_require__(614);
var MAX_LENGTH = 1024 * 64;
/**
@@ -61753,10 +61843,10 @@ module.exports.makeRe = makeRe;
/***/ }),
-/* 604 */
+/* 605 */
/***/ (function(module, exports, __webpack_require__) {
-var parse = __webpack_require__(605);
+var parse = __webpack_require__(606);
var types = parse.types;
module.exports = function (re, opts) {
@@ -61802,13 +61892,13 @@ function isRegExp (x) {
/***/ }),
-/* 605 */
+/* 606 */
/***/ (function(module, exports, __webpack_require__) {
-var util = __webpack_require__(606);
-var types = __webpack_require__(607);
-var sets = __webpack_require__(608);
-var positions = __webpack_require__(609);
+var util = __webpack_require__(607);
+var types = __webpack_require__(608);
+var sets = __webpack_require__(609);
+var positions = __webpack_require__(610);
module.exports = function(regexpStr) {
@@ -62090,11 +62180,11 @@ module.exports.types = types;
/***/ }),
-/* 606 */
+/* 607 */
/***/ (function(module, exports, __webpack_require__) {
-var types = __webpack_require__(607);
-var sets = __webpack_require__(608);
+var types = __webpack_require__(608);
+var sets = __webpack_require__(609);
// All of these are private and only used by randexp.
@@ -62207,7 +62297,7 @@ exports.error = function(regexp, msg) {
/***/ }),
-/* 607 */
+/* 608 */
/***/ (function(module, exports) {
module.exports = {
@@ -62223,10 +62313,10 @@ module.exports = {
/***/ }),
-/* 608 */
+/* 609 */
/***/ (function(module, exports, __webpack_require__) {
-var types = __webpack_require__(607);
+var types = __webpack_require__(608);
var INTS = function() {
return [{ type: types.RANGE , from: 48, to: 57 }];
@@ -62311,10 +62401,10 @@ exports.anyChar = function() {
/***/ }),
-/* 609 */
+/* 610 */
/***/ (function(module, exports, __webpack_require__) {
-var types = __webpack_require__(607);
+var types = __webpack_require__(608);
exports.wordBoundary = function() {
return { type: types.POSITION, value: 'b' };
@@ -62334,7 +62424,7 @@ exports.end = function() {
/***/ }),
-/* 610 */
+/* 611 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -62347,8 +62437,8 @@ exports.end = function() {
-var isobject = __webpack_require__(520);
-var isDescriptor = __webpack_require__(532);
+var isobject = __webpack_require__(521);
+var isDescriptor = __webpack_require__(533);
var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty)
? Reflect.defineProperty
: Object.defineProperty;
@@ -62379,14 +62469,14 @@ module.exports = function defineProperty(obj, key, val) {
/***/ }),
-/* 611 */
+/* 612 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(612);
-var assignSymbols = __webpack_require__(521);
+var isExtendable = __webpack_require__(613);
+var assignSymbols = __webpack_require__(522);
module.exports = Object.assign || function(obj/*, objects*/) {
if (obj === null || typeof obj === 'undefined') {
@@ -62446,7 +62536,7 @@ function isEnum(obj, key) {
/***/ }),
-/* 612 */
+/* 613 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -62459,7 +62549,7 @@ function isEnum(obj, key) {
-var isPlainObject = __webpack_require__(519);
+var isPlainObject = __webpack_require__(520);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -62467,14 +62557,14 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 613 */
+/* 614 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var extend = __webpack_require__(611);
-var safe = __webpack_require__(604);
+var extend = __webpack_require__(612);
+var safe = __webpack_require__(605);
/**
* The main export is a function that takes a `pattern` string and an `options` object.
@@ -62546,14 +62636,14 @@ module.exports = toRegex;
/***/ }),
-/* 614 */
+/* 615 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var nanomatch = __webpack_require__(615);
-var extglob = __webpack_require__(630);
+var nanomatch = __webpack_require__(616);
+var extglob = __webpack_require__(631);
module.exports = function(snapdragon) {
var compilers = snapdragon.compiler.compilers;
@@ -62630,7 +62720,7 @@ function escapeExtglobs(compiler) {
/***/ }),
-/* 615 */
+/* 616 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -62641,17 +62731,17 @@ function escapeExtglobs(compiler) {
*/
var util = __webpack_require__(29);
-var toRegex = __webpack_require__(501);
-var extend = __webpack_require__(616);
+var toRegex = __webpack_require__(502);
+var extend = __webpack_require__(617);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(618);
-var parsers = __webpack_require__(619);
-var cache = __webpack_require__(622);
-var utils = __webpack_require__(624);
+var compilers = __webpack_require__(619);
+var parsers = __webpack_require__(620);
+var cache = __webpack_require__(623);
+var utils = __webpack_require__(625);
var MAX_LENGTH = 1024 * 64;
/**
@@ -63475,14 +63565,14 @@ module.exports = nanomatch;
/***/ }),
-/* 616 */
+/* 617 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isExtendable = __webpack_require__(617);
-var assignSymbols = __webpack_require__(521);
+var isExtendable = __webpack_require__(618);
+var assignSymbols = __webpack_require__(522);
module.exports = Object.assign || function(obj/*, objects*/) {
if (obj === null || typeof obj === 'undefined') {
@@ -63542,7 +63632,7 @@ function isEnum(obj, key) {
/***/ }),
-/* 617 */
+/* 618 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -63555,7 +63645,7 @@ function isEnum(obj, key) {
-var isPlainObject = __webpack_require__(519);
+var isPlainObject = __webpack_require__(520);
module.exports = function isExtendable(val) {
return isPlainObject(val) || typeof val === 'function' || Array.isArray(val);
@@ -63563,7 +63653,7 @@ module.exports = function isExtendable(val) {
/***/ }),
-/* 618 */
+/* 619 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -63909,15 +63999,15 @@ module.exports = function(nanomatch, options) {
/***/ }),
-/* 619 */
+/* 620 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var regexNot = __webpack_require__(512);
-var toRegex = __webpack_require__(501);
-var isOdd = __webpack_require__(620);
+var regexNot = __webpack_require__(513);
+var toRegex = __webpack_require__(502);
+var isOdd = __webpack_require__(621);
/**
* Characters to use in negation regex (we want to "not" match
@@ -64303,7 +64393,7 @@ module.exports.not = NOT_REGEX;
/***/ }),
-/* 620 */
+/* 621 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64316,7 +64406,7 @@ module.exports.not = NOT_REGEX;
-var isNumber = __webpack_require__(621);
+var isNumber = __webpack_require__(622);
module.exports = function isOdd(i) {
if (!isNumber(i)) {
@@ -64330,7 +64420,7 @@ module.exports = function isOdd(i) {
/***/ }),
-/* 621 */
+/* 622 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64358,14 +64448,14 @@ module.exports = function isNumber(num) {
/***/ }),
-/* 622 */
+/* 623 */
/***/ (function(module, exports, __webpack_require__) {
-module.exports = new (__webpack_require__(623))();
+module.exports = new (__webpack_require__(624))();
/***/ }),
-/* 623 */
+/* 624 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64378,7 +64468,7 @@ module.exports = new (__webpack_require__(623))();
-var MapCache = __webpack_require__(601);
+var MapCache = __webpack_require__(602);
/**
* Create a new `FragmentCache` with an optional object to use for `caches`.
@@ -64500,7 +64590,7 @@ exports = module.exports = FragmentCache;
/***/ }),
-/* 624 */
+/* 625 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64513,14 +64603,14 @@ var path = __webpack_require__(16);
* Module dependencies
*/
-var isWindows = __webpack_require__(625)();
-var Snapdragon = __webpack_require__(540);
-utils.define = __webpack_require__(626);
-utils.diff = __webpack_require__(627);
-utils.extend = __webpack_require__(616);
-utils.pick = __webpack_require__(628);
-utils.typeOf = __webpack_require__(629);
-utils.unique = __webpack_require__(513);
+var isWindows = __webpack_require__(626)();
+var Snapdragon = __webpack_require__(541);
+utils.define = __webpack_require__(627);
+utils.diff = __webpack_require__(628);
+utils.extend = __webpack_require__(617);
+utils.pick = __webpack_require__(629);
+utils.typeOf = __webpack_require__(630);
+utils.unique = __webpack_require__(514);
/**
* Returns true if the given value is effectively an empty string
@@ -64886,7 +64976,7 @@ utils.unixify = function(options) {
/***/ }),
-/* 625 */
+/* 626 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
@@ -64914,7 +65004,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
/***/ }),
-/* 626 */
+/* 627 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -64927,8 +65017,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
-var isobject = __webpack_require__(520);
-var isDescriptor = __webpack_require__(532);
+var isobject = __webpack_require__(521);
+var isDescriptor = __webpack_require__(533);
var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty)
? Reflect.defineProperty
: Object.defineProperty;
@@ -64959,7 +65049,7 @@ module.exports = function defineProperty(obj, key, val) {
/***/ }),
-/* 627 */
+/* 628 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -65013,7 +65103,7 @@ function diffArray(one, two) {
/***/ }),
-/* 628 */
+/* 629 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -65026,7 +65116,7 @@ function diffArray(one, two) {
-var isObject = __webpack_require__(520);
+var isObject = __webpack_require__(521);
module.exports = function pick(obj, keys) {
if (!isObject(obj) && typeof obj !== 'function') {
@@ -65055,7 +65145,7 @@ module.exports = function pick(obj, keys) {
/***/ }),
-/* 629 */
+/* 630 */
/***/ (function(module, exports) {
var toString = Object.prototype.toString;
@@ -65190,7 +65280,7 @@ function isBuffer(val) {
/***/ }),
-/* 630 */
+/* 631 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -65200,18 +65290,18 @@ function isBuffer(val) {
* Module dependencies
*/
-var extend = __webpack_require__(510);
-var unique = __webpack_require__(513);
-var toRegex = __webpack_require__(501);
+var extend = __webpack_require__(511);
+var unique = __webpack_require__(514);
+var toRegex = __webpack_require__(502);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(631);
-var parsers = __webpack_require__(637);
-var Extglob = __webpack_require__(640);
-var utils = __webpack_require__(639);
+var compilers = __webpack_require__(632);
+var parsers = __webpack_require__(638);
+var Extglob = __webpack_require__(641);
+var utils = __webpack_require__(640);
var MAX_LENGTH = 1024 * 64;
/**
@@ -65528,13 +65618,13 @@ module.exports = extglob;
/***/ }),
-/* 631 */
+/* 632 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var brackets = __webpack_require__(632);
+var brackets = __webpack_require__(633);
/**
* Extglob compilers
@@ -65704,7 +65794,7 @@ module.exports = function(extglob) {
/***/ }),
-/* 632 */
+/* 633 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -65714,17 +65804,17 @@ module.exports = function(extglob) {
* Local dependencies
*/
-var compilers = __webpack_require__(633);
-var parsers = __webpack_require__(635);
+var compilers = __webpack_require__(634);
+var parsers = __webpack_require__(636);
/**
* Module dependencies
*/
-var debug = __webpack_require__(573)('expand-brackets');
-var extend = __webpack_require__(510);
-var Snapdragon = __webpack_require__(540);
-var toRegex = __webpack_require__(501);
+var debug = __webpack_require__(574)('expand-brackets');
+var extend = __webpack_require__(511);
+var Snapdragon = __webpack_require__(541);
+var toRegex = __webpack_require__(502);
/**
* Parses the given POSIX character class `pattern` and returns a
@@ -65922,13 +66012,13 @@ module.exports = brackets;
/***/ }),
-/* 633 */
+/* 634 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var posix = __webpack_require__(634);
+var posix = __webpack_require__(635);
module.exports = function(brackets) {
brackets.compiler
@@ -66016,7 +66106,7 @@ module.exports = function(brackets) {
/***/ }),
-/* 634 */
+/* 635 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -66045,14 +66135,14 @@ module.exports = {
/***/ }),
-/* 635 */
+/* 636 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(636);
-var define = __webpack_require__(502);
+var utils = __webpack_require__(637);
+var define = __webpack_require__(503);
/**
* Text regex
@@ -66271,14 +66361,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX;
/***/ }),
-/* 636 */
+/* 637 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toRegex = __webpack_require__(501);
-var regexNot = __webpack_require__(512);
+var toRegex = __webpack_require__(502);
+var regexNot = __webpack_require__(513);
var cached;
/**
@@ -66312,15 +66402,15 @@ exports.createRegex = function(pattern, include) {
/***/ }),
-/* 637 */
+/* 638 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var brackets = __webpack_require__(632);
-var define = __webpack_require__(638);
-var utils = __webpack_require__(639);
+var brackets = __webpack_require__(633);
+var define = __webpack_require__(639);
+var utils = __webpack_require__(640);
/**
* Characters to use in text regex (we want to "not" match
@@ -66475,7 +66565,7 @@ module.exports = parsers;
/***/ }),
-/* 638 */
+/* 639 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -66488,7 +66578,7 @@ module.exports = parsers;
-var isDescriptor = __webpack_require__(532);
+var isDescriptor = __webpack_require__(533);
module.exports = function defineProperty(obj, prop, val) {
if (typeof obj !== 'object' && typeof obj !== 'function') {
@@ -66513,14 +66603,14 @@ module.exports = function defineProperty(obj, prop, val) {
/***/ }),
-/* 639 */
+/* 640 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var regex = __webpack_require__(512);
-var Cache = __webpack_require__(623);
+var regex = __webpack_require__(513);
+var Cache = __webpack_require__(624);
/**
* Utils
@@ -66589,7 +66679,7 @@ utils.createRegex = function(str) {
/***/ }),
-/* 640 */
+/* 641 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -66599,16 +66689,16 @@ utils.createRegex = function(str) {
* Module dependencies
*/
-var Snapdragon = __webpack_require__(540);
-var define = __webpack_require__(638);
-var extend = __webpack_require__(510);
+var Snapdragon = __webpack_require__(541);
+var define = __webpack_require__(639);
+var extend = __webpack_require__(511);
/**
* Local dependencies
*/
-var compilers = __webpack_require__(631);
-var parsers = __webpack_require__(637);
+var compilers = __webpack_require__(632);
+var parsers = __webpack_require__(638);
/**
* Customize Snapdragon parser and renderer
@@ -66674,16 +66764,16 @@ module.exports = Extglob;
/***/ }),
-/* 641 */
+/* 642 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var extglob = __webpack_require__(630);
-var nanomatch = __webpack_require__(615);
-var regexNot = __webpack_require__(512);
-var toRegex = __webpack_require__(603);
+var extglob = __webpack_require__(631);
+var nanomatch = __webpack_require__(616);
+var regexNot = __webpack_require__(513);
+var toRegex = __webpack_require__(604);
var not;
/**
@@ -66764,14 +66854,14 @@ function textRegex(pattern) {
/***/ }),
-/* 642 */
+/* 643 */
/***/ (function(module, exports, __webpack_require__) {
-module.exports = new (__webpack_require__(623))();
+module.exports = new (__webpack_require__(624))();
/***/ }),
-/* 643 */
+/* 644 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -66784,13 +66874,13 @@ var path = __webpack_require__(16);
* Module dependencies
*/
-var Snapdragon = __webpack_require__(540);
-utils.define = __webpack_require__(610);
-utils.diff = __webpack_require__(627);
-utils.extend = __webpack_require__(611);
-utils.pick = __webpack_require__(628);
-utils.typeOf = __webpack_require__(644);
-utils.unique = __webpack_require__(513);
+var Snapdragon = __webpack_require__(541);
+utils.define = __webpack_require__(611);
+utils.diff = __webpack_require__(628);
+utils.extend = __webpack_require__(612);
+utils.pick = __webpack_require__(629);
+utils.typeOf = __webpack_require__(645);
+utils.unique = __webpack_require__(514);
/**
* Returns true if the platform is windows, or `path.sep` is `\\`.
@@ -67087,7 +67177,7 @@ utils.unixify = function(options) {
/***/ }),
-/* 644 */
+/* 645 */
/***/ (function(module, exports) {
var toString = Object.prototype.toString;
@@ -67222,7 +67312,7 @@ function isBuffer(val) {
/***/ }),
-/* 645 */
+/* 646 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67241,9 +67331,9 @@ var __extends = (this && this.__extends) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
-var readdir = __webpack_require__(646);
-var reader_1 = __webpack_require__(659);
-var fs_stream_1 = __webpack_require__(663);
+var readdir = __webpack_require__(647);
+var reader_1 = __webpack_require__(660);
+var fs_stream_1 = __webpack_require__(664);
var ReaderAsync = /** @class */ (function (_super) {
__extends(ReaderAsync, _super);
function ReaderAsync() {
@@ -67304,15 +67394,15 @@ exports.default = ReaderAsync;
/***/ }),
-/* 646 */
+/* 647 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const readdirSync = __webpack_require__(647);
-const readdirAsync = __webpack_require__(655);
-const readdirStream = __webpack_require__(658);
+const readdirSync = __webpack_require__(648);
+const readdirAsync = __webpack_require__(656);
+const readdirStream = __webpack_require__(659);
module.exports = exports = readdirAsyncPath;
exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath;
@@ -67396,7 +67486,7 @@ function readdirStreamStat (dir, options) {
/***/ }),
-/* 647 */
+/* 648 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67404,11 +67494,11 @@ function readdirStreamStat (dir, options) {
module.exports = readdirSync;
-const DirectoryReader = __webpack_require__(648);
+const DirectoryReader = __webpack_require__(649);
let syncFacade = {
- fs: __webpack_require__(653),
- forEach: __webpack_require__(654),
+ fs: __webpack_require__(654),
+ forEach: __webpack_require__(655),
sync: true
};
@@ -67437,7 +67527,7 @@ function readdirSync (dir, options, internalOptions) {
/***/ }),
-/* 648 */
+/* 649 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -67446,9 +67536,9 @@ function readdirSync (dir, options, internalOptions) {
const Readable = __webpack_require__(28).Readable;
const EventEmitter = __webpack_require__(46).EventEmitter;
const path = __webpack_require__(16);
-const normalizeOptions = __webpack_require__(649);
-const stat = __webpack_require__(651);
-const call = __webpack_require__(652);
+const normalizeOptions = __webpack_require__(650);
+const stat = __webpack_require__(652);
+const call = __webpack_require__(653);
/**
* Asynchronously reads the contents of a directory and streams the results
@@ -67824,14 +67914,14 @@ module.exports = DirectoryReader;
/***/ }),
-/* 649 */
+/* 650 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(16);
-const globToRegExp = __webpack_require__(650);
+const globToRegExp = __webpack_require__(651);
module.exports = normalizeOptions;
@@ -68008,7 +68098,7 @@ function normalizeOptions (options, internalOptions) {
/***/ }),
-/* 650 */
+/* 651 */
/***/ (function(module, exports) {
module.exports = function (glob, opts) {
@@ -68145,13 +68235,13 @@ module.exports = function (glob, opts) {
/***/ }),
-/* 651 */
+/* 652 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const call = __webpack_require__(652);
+const call = __webpack_require__(653);
module.exports = stat;
@@ -68226,7 +68316,7 @@ function symlinkStat (fs, path, lstats, callback) {
/***/ }),
-/* 652 */
+/* 653 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68287,14 +68377,14 @@ function callOnce (fn) {
/***/ }),
-/* 653 */
+/* 654 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(23);
-const call = __webpack_require__(652);
+const call = __webpack_require__(653);
/**
* A facade around {@link fs.readdirSync} that allows it to be called
@@ -68358,7 +68448,7 @@ exports.lstat = function (path, callback) {
/***/ }),
-/* 654 */
+/* 655 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68387,7 +68477,7 @@ function syncForEach (array, iterator, done) {
/***/ }),
-/* 655 */
+/* 656 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68395,12 +68485,12 @@ function syncForEach (array, iterator, done) {
module.exports = readdirAsync;
-const maybe = __webpack_require__(656);
-const DirectoryReader = __webpack_require__(648);
+const maybe = __webpack_require__(657);
+const DirectoryReader = __webpack_require__(649);
let asyncFacade = {
fs: __webpack_require__(23),
- forEach: __webpack_require__(657),
+ forEach: __webpack_require__(658),
async: true
};
@@ -68442,7 +68532,7 @@ function readdirAsync (dir, options, callback, internalOptions) {
/***/ }),
-/* 656 */
+/* 657 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68469,7 +68559,7 @@ module.exports = function maybe (cb, promise) {
/***/ }),
-/* 657 */
+/* 658 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68505,7 +68595,7 @@ function asyncForEach (array, iterator, done) {
/***/ }),
-/* 658 */
+/* 659 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68513,11 +68603,11 @@ function asyncForEach (array, iterator, done) {
module.exports = readdirStream;
-const DirectoryReader = __webpack_require__(648);
+const DirectoryReader = __webpack_require__(649);
let streamFacade = {
fs: __webpack_require__(23),
- forEach: __webpack_require__(657),
+ forEach: __webpack_require__(658),
async: true
};
@@ -68537,16 +68627,16 @@ function readdirStream (dir, options, internalOptions) {
/***/ }),
-/* 659 */
+/* 660 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var path = __webpack_require__(16);
-var deep_1 = __webpack_require__(660);
-var entry_1 = __webpack_require__(662);
-var pathUtil = __webpack_require__(661);
+var deep_1 = __webpack_require__(661);
+var entry_1 = __webpack_require__(663);
+var pathUtil = __webpack_require__(662);
var Reader = /** @class */ (function () {
function Reader(options) {
this.options = options;
@@ -68612,14 +68702,14 @@ exports.default = Reader;
/***/ }),
-/* 660 */
+/* 661 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-var pathUtils = __webpack_require__(661);
-var patternUtils = __webpack_require__(494);
+var pathUtils = __webpack_require__(662);
+var patternUtils = __webpack_require__(495);
var DeepFilter = /** @class */ (function () {
function DeepFilter(options, micromatchOptions) {
this.options = options;
@@ -68702,7 +68792,7 @@ exports.default = DeepFilter;
/***/ }),
-/* 661 */
+/* 662 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68733,14 +68823,14 @@ exports.makeAbsolute = makeAbsolute;
/***/ }),
-/* 662 */
+/* 663 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-var pathUtils = __webpack_require__(661);
-var patternUtils = __webpack_require__(494);
+var pathUtils = __webpack_require__(662);
+var patternUtils = __webpack_require__(495);
var EntryFilter = /** @class */ (function () {
function EntryFilter(options, micromatchOptions) {
this.options = options;
@@ -68825,7 +68915,7 @@ exports.default = EntryFilter;
/***/ }),
-/* 663 */
+/* 664 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68845,8 +68935,8 @@ var __extends = (this && this.__extends) || (function () {
})();
Object.defineProperty(exports, "__esModule", { value: true });
var stream = __webpack_require__(28);
-var fsStat = __webpack_require__(664);
-var fs_1 = __webpack_require__(668);
+var fsStat = __webpack_require__(665);
+var fs_1 = __webpack_require__(669);
var FileSystemStream = /** @class */ (function (_super) {
__extends(FileSystemStream, _super);
function FileSystemStream() {
@@ -68896,14 +68986,14 @@ exports.default = FileSystemStream;
/***/ }),
-/* 664 */
+/* 665 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const optionsManager = __webpack_require__(665);
-const statProvider = __webpack_require__(667);
+const optionsManager = __webpack_require__(666);
+const statProvider = __webpack_require__(668);
/**
* Asynchronous API.
*/
@@ -68934,13 +69024,13 @@ exports.statSync = statSync;
/***/ }),
-/* 665 */
+/* 666 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const fsAdapter = __webpack_require__(666);
+const fsAdapter = __webpack_require__(667);
function prepare(opts) {
const options = Object.assign({
fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined),
@@ -68953,7 +69043,7 @@ exports.prepare = prepare;
/***/ }),
-/* 666 */
+/* 667 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68976,7 +69066,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter;
/***/ }),
-/* 667 */
+/* 668 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69028,7 +69118,7 @@ exports.isFollowedSymlink = isFollowedSymlink;
/***/ }),
-/* 668 */
+/* 669 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69059,7 +69149,7 @@ exports.default = FileSystem;
/***/ }),
-/* 669 */
+/* 670 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69079,9 +69169,9 @@ var __extends = (this && this.__extends) || (function () {
})();
Object.defineProperty(exports, "__esModule", { value: true });
var stream = __webpack_require__(28);
-var readdir = __webpack_require__(646);
-var reader_1 = __webpack_require__(659);
-var fs_stream_1 = __webpack_require__(663);
+var readdir = __webpack_require__(647);
+var reader_1 = __webpack_require__(660);
+var fs_stream_1 = __webpack_require__(664);
var TransformStream = /** @class */ (function (_super) {
__extends(TransformStream, _super);
function TransformStream(reader) {
@@ -69149,7 +69239,7 @@ exports.default = ReaderStream;
/***/ }),
-/* 670 */
+/* 671 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69168,9 +69258,9 @@ var __extends = (this && this.__extends) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
-var readdir = __webpack_require__(646);
-var reader_1 = __webpack_require__(659);
-var fs_sync_1 = __webpack_require__(671);
+var readdir = __webpack_require__(647);
+var reader_1 = __webpack_require__(660);
+var fs_sync_1 = __webpack_require__(672);
var ReaderSync = /** @class */ (function (_super) {
__extends(ReaderSync, _super);
function ReaderSync() {
@@ -69230,7 +69320,7 @@ exports.default = ReaderSync;
/***/ }),
-/* 671 */
+/* 672 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69249,8 +69339,8 @@ var __extends = (this && this.__extends) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
-var fsStat = __webpack_require__(664);
-var fs_1 = __webpack_require__(668);
+var fsStat = __webpack_require__(665);
+var fs_1 = __webpack_require__(669);
var FileSystemSync = /** @class */ (function (_super) {
__extends(FileSystemSync, _super);
function FileSystemSync() {
@@ -69296,7 +69386,7 @@ exports.default = FileSystemSync;
/***/ }),
-/* 672 */
+/* 673 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69312,7 +69402,7 @@ exports.flatten = flatten;
/***/ }),
-/* 673 */
+/* 674 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69333,13 +69423,13 @@ exports.merge = merge;
/***/ }),
-/* 674 */
+/* 675 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(16);
-const pathType = __webpack_require__(675);
+const pathType = __webpack_require__(676);
const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0];
@@ -69405,13 +69495,13 @@ module.exports.sync = (input, opts) => {
/***/ }),
-/* 675 */
+/* 676 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(23);
-const pify = __webpack_require__(676);
+const pify = __webpack_require__(677);
function type(fn, fn2, fp) {
if (typeof fp !== 'string') {
@@ -69454,7 +69544,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink');
/***/ }),
-/* 676 */
+/* 677 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -69545,17 +69635,17 @@ module.exports = (obj, opts) => {
/***/ }),
-/* 677 */
+/* 678 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(23);
const path = __webpack_require__(16);
-const fastGlob = __webpack_require__(490);
-const gitIgnore = __webpack_require__(678);
-const pify = __webpack_require__(679);
-const slash = __webpack_require__(680);
+const fastGlob = __webpack_require__(491);
+const gitIgnore = __webpack_require__(679);
+const pify = __webpack_require__(680);
+const slash = __webpack_require__(681);
const DEFAULT_IGNORE = [
'**/node_modules/**',
@@ -69653,7 +69743,7 @@ module.exports.sync = options => {
/***/ }),
-/* 678 */
+/* 679 */
/***/ (function(module, exports) {
// A simple implementation of make-array
@@ -70122,7 +70212,7 @@ module.exports = options => new IgnoreBase(options)
/***/ }),
-/* 679 */
+/* 680 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -70197,7 +70287,7 @@ module.exports = (input, options) => {
/***/ }),
-/* 680 */
+/* 681 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -70215,17 +70305,17 @@ module.exports = input => {
/***/ }),
-/* 681 */
+/* 682 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(16);
const {constants: fsConstants} = __webpack_require__(23);
-const {Buffer} = __webpack_require__(682);
-const CpFileError = __webpack_require__(684);
-const fs = __webpack_require__(686);
-const ProgressEmitter = __webpack_require__(688);
+const {Buffer} = __webpack_require__(683);
+const CpFileError = __webpack_require__(685);
+const fs = __webpack_require__(687);
+const ProgressEmitter = __webpack_require__(689);
const cpFile = (source, destination, options) => {
if (!source || !destination) {
@@ -70379,11 +70469,11 @@ module.exports.sync = (source, destination, options) => {
/***/ }),
-/* 682 */
+/* 683 */
/***/ (function(module, exports, __webpack_require__) {
/* eslint-disable node/no-deprecated-api */
-var buffer = __webpack_require__(683)
+var buffer = __webpack_require__(684)
var Buffer = buffer.Buffer
// alternative to using Object.keys for old browsers
@@ -70447,18 +70537,18 @@ SafeBuffer.allocUnsafeSlow = function (size) {
/***/ }),
-/* 683 */
+/* 684 */
/***/ (function(module, exports) {
module.exports = require("buffer");
/***/ }),
-/* 684 */
+/* 685 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const NestedError = __webpack_require__(685);
+const NestedError = __webpack_require__(686);
class CpFileError extends NestedError {
constructor(message, nested) {
@@ -70472,7 +70562,7 @@ module.exports = CpFileError;
/***/ }),
-/* 685 */
+/* 686 */
/***/ (function(module, exports, __webpack_require__) {
var inherits = __webpack_require__(44);
@@ -70526,15 +70616,15 @@ module.exports = NestedError;
/***/ }),
-/* 686 */
+/* 687 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(22);
const makeDir = __webpack_require__(115);
-const pify = __webpack_require__(687);
-const CpFileError = __webpack_require__(684);
+const pify = __webpack_require__(688);
+const CpFileError = __webpack_require__(685);
const fsP = pify(fs);
@@ -70679,7 +70769,7 @@ if (fs.copyFileSync) {
/***/ }),
-/* 687 */
+/* 688 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -70754,7 +70844,7 @@ module.exports = (input, options) => {
/***/ }),
-/* 688 */
+/* 689 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -70795,12 +70885,12 @@ module.exports = ProgressEmitter;
/***/ }),
-/* 689 */
+/* 690 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const NestedError = __webpack_require__(690);
+const NestedError = __webpack_require__(691);
class CpyError extends NestedError {
constructor(message, nested) {
@@ -70814,7 +70904,7 @@ module.exports = CpyError;
/***/ }),
-/* 690 */
+/* 691 */
/***/ (function(module, exports, __webpack_require__) {
var inherits = __webpack_require__(29).inherits;
@@ -70870,7 +70960,7 @@ module.exports = NestedError;
/***/ }),
-/* 691 */
+/* 692 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json
index dafe73ec7d1d6..34a56615ed43a 100644
--- a/packages/kbn-pm/package.json
+++ b/packages/kbn-pm/package.json
@@ -52,7 +52,7 @@
"ora": "^1.4.0",
"prettier": "^1.18.2",
"read-pkg": "^5.2.0",
- "rxjs": "^6.2.1",
+ "rxjs": "^6.5.3",
"spawn-sync": "^1.0.15",
"string-replace-loader": "^2.2.0",
"strip-ansi": "^4.0.0",
diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json
index 113783f66bc59..8c5358c82208d 100644
--- a/packages/kbn-test/package.json
+++ b/packages/kbn-test/package.json
@@ -25,7 +25,7 @@
"glob": "^7.1.2",
"parse-link-header": "^1.0.1",
"strip-ansi": "^5.2.0",
- "rxjs": "^6.2.1",
+ "rxjs": "^6.5.3",
"tar-fs": "^1.16.3",
"tmp": "^0.1.0",
"xml2js": "^0.4.22",
diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx
index bc723de06f215..3ddbe420ba284 100644
--- a/src/core/public/chrome/ui/header/header.tsx
+++ b/src/core/public/chrome/ui/header/header.tsx
@@ -171,7 +171,7 @@ interface Props {
navLinks$: Rx.Observable;
recentlyAccessed$: Rx.Observable;
forceAppSwitcherNavigation$: Rx.Observable;
- helpExtension$: Rx.Observable;
+ helpExtension$: Rx.Observable;
legacyMode: boolean;
navControlsLeft$: Rx.Observable;
navControlsRight$: Rx.Observable;
diff --git a/src/core/public/chrome/ui/header/header_help_menu.tsx b/src/core/public/chrome/ui/header/header_help_menu.tsx
index e2146f8d65bba..688d76c9d75d9 100644
--- a/src/core/public/chrome/ui/header/header_help_menu.tsx
+++ b/src/core/public/chrome/ui/header/header_help_menu.tsx
@@ -43,7 +43,7 @@ import { HeaderExtension } from './header_extension';
import { ChromeHelpExtension } from '../../chrome_service';
interface Props {
- helpExtension$: Rx.Observable;
+ helpExtension$: Rx.Observable;
intl: InjectedIntl;
kibanaVersion: string;
useDefaultContent?: boolean;
diff --git a/src/core/public/rendering/rendering_service.test.tsx b/src/core/public/rendering/rendering_service.test.tsx
index 317ab5cc8b855..ed835574a32f9 100644
--- a/src/core/public/rendering/rendering_service.test.tsx
+++ b/src/core/public/rendering/rendering_service.test.tsx
@@ -34,7 +34,7 @@ describe('RenderingService#start', () => {
const chrome = chromeServiceMock.createStartContract();
chrome.getHeaderComponent.mockReturnValue(Hello chrome!
);
const overlays = overlayServiceMock.createStartContract();
- overlays.banners.getComponent.mockReturnValue(I'm a banner!
);
+ overlays.banners.getComponent.mockReturnValue(I'm a banner!
);
const injectedMetadata = injectedMetadataServiceMock.createStartContract();
injectedMetadata.getLegacyMode.mockReturnValue(legacyMode);
diff --git a/src/core/server/elasticsearch/elasticsearch_config.test.ts b/src/core/server/elasticsearch/elasticsearch_config.test.ts
index 1a6a8929cd6a0..383ba77f17779 100644
--- a/src/core/server/elasticsearch/elasticsearch_config.test.ts
+++ b/src/core/server/elasticsearch/elasticsearch_config.test.ts
@@ -22,32 +22,33 @@ import { ElasticsearchConfig, config } from './elasticsearch_config';
test('set correct defaults', () => {
const configValue = new ElasticsearchConfig(config.schema.validate({}));
expect(configValue).toMatchInlineSnapshot(`
-ElasticsearchConfig {
- "apiVersion": "master",
- "customHeaders": Object {},
- "healthCheckDelay": "PT2.5S",
- "hosts": Array [
- "http://localhost:9200",
- ],
- "logQueries": false,
- "password": undefined,
- "pingTimeout": "PT30S",
- "requestHeadersWhitelist": Array [
- "authorization",
- ],
- "requestTimeout": "PT30S",
- "shardTimeout": "PT30S",
- "sniffInterval": false,
- "sniffOnConnectionFault": false,
- "sniffOnStart": false,
- "ssl": Object {
- "alwaysPresentCertificate": true,
- "certificateAuthorities": undefined,
- "verificationMode": "full",
- },
- "username": undefined,
-}
-`);
+ ElasticsearchConfig {
+ "apiVersion": "master",
+ "customHeaders": Object {},
+ "healthCheckDelay": "PT2.5S",
+ "hosts": Array [
+ "http://localhost:9200",
+ ],
+ "ignoreVersionMismatch": false,
+ "logQueries": false,
+ "password": undefined,
+ "pingTimeout": "PT30S",
+ "requestHeadersWhitelist": Array [
+ "authorization",
+ ],
+ "requestTimeout": "PT30S",
+ "shardTimeout": "PT30S",
+ "sniffInterval": false,
+ "sniffOnConnectionFault": false,
+ "sniffOnStart": false,
+ "ssl": Object {
+ "alwaysPresentCertificate": true,
+ "certificateAuthorities": undefined,
+ "verificationMode": "full",
+ },
+ "username": undefined,
+ }
+ `);
});
test('#hosts accepts both string and array of strings', () => {
diff --git a/src/core/server/elasticsearch/elasticsearch_config.ts b/src/core/server/elasticsearch/elasticsearch_config.ts
index fb585a8d67262..947a0d27546b1 100644
--- a/src/core/server/elasticsearch/elasticsearch_config.ts
+++ b/src/core/server/elasticsearch/elasticsearch_config.ts
@@ -65,6 +65,7 @@ export const config = {
}),
apiVersion: schema.string({ defaultValue: DEFAULT_API_VERSION }),
healthCheck: schema.object({ delay: schema.duration({ defaultValue: 2500 }) }),
+ ignoreVersionMismatch: schema.boolean({ defaultValue: false }),
}),
};
@@ -74,6 +75,11 @@ export class ElasticsearchConfig {
*/
public readonly healthCheckDelay: Duration;
+ /**
+ * Whether to allow kibana to connect to a non-compatible elasticsearch node.
+ */
+ public readonly ignoreVersionMismatch: boolean;
+
/**
* Version of the Elasticsearch (6.7, 7.1 or `master`) client will be connecting to.
*/
@@ -161,6 +167,7 @@ export class ElasticsearchConfig {
public readonly customHeaders: ElasticsearchConfigType['customHeaders'];
constructor(rawConfig: ElasticsearchConfigType) {
+ this.ignoreVersionMismatch = rawConfig.ignoreVersionMismatch;
this.apiVersion = rawConfig.apiVersion;
this.logQueries = rawConfig.logQueries;
this.hosts = Array.isArray(rawConfig.hosts) ? rawConfig.hosts : [rawConfig.hosts];
diff --git a/src/core/server/http/http_server.test.ts b/src/core/server/http/http_server.test.ts
index f61371c5437e6..acae9d8ff0e70 100644
--- a/src/core/server/http/http_server.test.ts
+++ b/src/core/server/http/http_server.test.ts
@@ -577,45 +577,6 @@ test('exposes route details of incoming request to a route handler', async () =>
});
});
-describe('conditional compression', () => {
- test('disables compression when there is a referer', async () => {
- const { registerRouter, server: innerServer } = await server.setup(config);
-
- const router = new Router('', logger, enhanceWithContext);
- router.get({ path: '/', validate: false }, (context, req, res) =>
- // we need the large body here so that compression would normally be used
- res.ok({ body: 'hello'.repeat(500), headers: { 'Content-Type': 'text/html; charset=UTF-8' } })
- );
- registerRouter(router);
-
- await server.start();
- const response = await supertest(innerServer.listener)
- .get('/')
- .set('accept-encoding', 'gzip')
- .set('referer', 'http://some-other-site/');
-
- expect(response.header).not.toHaveProperty('content-encoding');
- });
-
- test(`enables compression when there isn't a referer`, async () => {
- const { registerRouter, server: innerServer } = await server.setup(config);
-
- const router = new Router('', logger, enhanceWithContext);
- router.get({ path: '/', validate: false }, (context, req, res) =>
- // we need the large body here so that compression will be used
- res.ok({ body: 'hello'.repeat(500), headers: { 'Content-Type': 'text/html; charset=UTF-8' } })
- );
- registerRouter(router);
-
- await server.start();
- const response = await supertest(innerServer.listener)
- .get('/')
- .set('accept-encoding', 'gzip');
-
- expect(response.header).toHaveProperty('content-encoding', 'gzip');
- });
-});
-
describe('setup contract', () => {
describe('#createSessionStorage', () => {
it('creates session storage factory', async () => {
diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts
index d6077200d3c75..3354324c12407 100644
--- a/src/core/server/http/http_server.ts
+++ b/src/core/server/http/http_server.ts
@@ -96,7 +96,6 @@ export class HttpServer {
const basePathService = new BasePath(config.basePath);
this.setupBasePathRewrite(config, basePathService);
- this.setupConditionalCompression();
return {
registerRouter: this.registerRouter.bind(this),
@@ -176,23 +175,6 @@ export class HttpServer {
});
}
- private setupConditionalCompression() {
- if (this.server === undefined) {
- throw new Error('Server is not created yet');
- }
-
- this.server.ext('onRequest', (request, h) => {
- // whenever there is a referrer, don't use compression even if the client supports it
- if (request.info.referrer !== '') {
- this.log.debug(
- `Not using compression because there is a referer: ${request.info.referrer}`
- );
- request.info.acceptEncoding = '';
- }
- return h.continue;
- });
- }
-
private registerOnPostAuth(fn: OnPostAuthHandler) {
if (this.server === undefined) {
throw new Error('Server is not created yet');
diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts
index f1f4da8d0b4d7..c0a6026708af3 100644
--- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts
+++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts
@@ -54,7 +54,7 @@ export async function findLegacyPluginSpecs(settings: unknown, loggerFactory: Lo
invalidDirectoryError$: Observable<{ path: string }>;
invalidPackError$: Observable<{ path: string }>;
otherError$: Observable;
- deprecation$: Observable;
+ deprecation$: Observable<{ spec: LegacyPluginSpec; message: string }>;
invalidVersionSpec$: Observable;
spec$: Observable;
disabledSpec$: Observable;
diff --git a/src/core/server/plugins/discovery/plugins_discovery.ts b/src/core/server/plugins/discovery/plugins_discovery.ts
index 74e9dd709bb23..521d02e487df6 100644
--- a/src/core/server/plugins/discovery/plugins_discovery.ts
+++ b/src/core/server/plugins/discovery/plugins_discovery.ts
@@ -29,7 +29,7 @@ import { PluginsConfig } from '../plugins_config';
import { PluginDiscoveryError } from './plugin_discovery_error';
import { parseManifest } from './plugin_manifest_parser';
-const fsReadDir$ = bindNodeCallback(readdir);
+const fsReadDir$ = bindNodeCallback(readdir);
const fsStat$ = bindNodeCallback(stat);
/**
diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js
index 9941bbd03f5dc..6525590ee96c5 100644
--- a/src/core/server/saved_objects/service/lib/repository.test.js
+++ b/src/core/server/saved_objects/service/lib/repository.test.js
@@ -1377,7 +1377,7 @@ describe('SavedObjectsRepository', () => {
};
await expect(savedObjectsRepository.find(findOpts)).rejects.toMatchInlineSnapshot(`
- [Error: KQLSyntaxError: Expected "(", value, whitespace but "<" found.
+ [Error: KQLSyntaxError: Expected "(", "{", value, whitespace but "<" found.
dashboard.attributes.otherField:<
--------------------------------^: Bad Request]
`);
diff --git a/src/dev/build/build_distributables.js b/src/dev/build/build_distributables.js
index e3fcfd9536c47..eeffc2380f38b 100644
--- a/src/dev/build/build_distributables.js
+++ b/src/dev/build/build_distributables.js
@@ -45,7 +45,6 @@ import {
ExtractNodeBuildsTask,
InstallDependenciesTask,
OptimizeBuildTask,
- PatchNativeModulesTask,
RemovePackageJsonDepsTask,
RemoveWorkspacesTask,
TranspileBabelTask,
@@ -131,7 +130,6 @@ export async function buildDistributables(options) {
* directories and perform platform-specific steps
*/
await run(CreateArchivesSourcesTask);
- await run(PatchNativeModulesTask);
await run(CleanExtraBinScriptsTask);
await run(CleanExtraBrowsersTask);
await run(CleanNodeBuildsTask);
diff --git a/src/dev/build/lib/scan_delete.ts b/src/dev/build/lib/scan_delete.ts
index f1b2a02c11a43..cb4e64ce1b5f9 100644
--- a/src/dev/build/lib/scan_delete.ts
+++ b/src/dev/build/lib/scan_delete.ts
@@ -28,7 +28,7 @@ import { count, map, mergeAll, mergeMap } from 'rxjs/operators';
import { assertAbsolute } from './fs';
const getStat$ = Rx.bindNodeCallback(Fs.stat);
-const getReadDir$ = Rx.bindNodeCallback(Fs.readdir);
+const getReadDir$ = Rx.bindNodeCallback(Fs.readdir);
interface Options {
directory: string;
diff --git a/src/dev/build/tasks/index.js b/src/dev/build/tasks/index.js
index 35c07c9187317..014cdc7ad5ea7 100644
--- a/src/dev/build/tasks/index.js
+++ b/src/dev/build/tasks/index.js
@@ -36,5 +36,4 @@ export * from './transpile_babel_task';
export * from './transpile_scss_task';
export * from './verify_env_task';
export * from './write_sha_sums_task';
-export * from './patch_native_modules_task';
export * from './path_length_task';
diff --git a/src/dev/build/tasks/patch_native_modules_task.js b/src/dev/build/tasks/patch_native_modules_task.js
deleted file mode 100644
index 16290aca04e73..0000000000000
--- a/src/dev/build/tasks/patch_native_modules_task.js
+++ /dev/null
@@ -1,47 +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 install from '@elastic/simple-git/scripts/install';
-import { deleteAll } from '../lib';
-import path from 'path';
-
-async function patchGit(config, log, build, platform) {
- const downloadPath = build.resolvePathForPlatform(platform, '.git_binaries', 'git.tar.gz');
- const destination = build.resolvePathForPlatform(
- platform,
- 'node_modules/@elastic/simple-git/native/git'
- );
- log.debug('Replacing git binaries from ' + downloadPath + ' to ' + destination);
- const p = platform.isWindows() ? 'win32' : platform.getName();
- await deleteAll([destination]);
- await install(p, downloadPath, destination);
- await deleteAll([path.dirname(downloadPath)], log);
-}
-
-export const PatchNativeModulesTask = {
- description: 'Patching platform-specific native modules directories',
- async run(config, log, build) {
- await Promise.all(
- config.getTargetPlatforms().map(async platform => {
- if (!build.isOss()) {
- await patchGit(config, log, build, platform);
- }
- })
- );
- },
-};
diff --git a/src/fixtures/logstash_fields.js b/src/fixtures/logstash_fields.js
index 8299604d3a28c..ab96b69851b71 100644
--- a/src/fixtures/logstash_fields.js
+++ b/src/fixtures/logstash_fields.js
@@ -19,13 +19,13 @@
import { castEsToKbnFieldTypeName } from '../plugins/data/common';
// eslint-disable-next-line max-len
-import { shouldReadFieldFromDocValues } from '../legacy/server/index_patterns/service/lib/field_capabilities/should_read_field_from_doc_values';
+import { shouldReadFieldFromDocValues } from '../plugins/data/server';
function stubbedLogstashFields() {
return [
// |aggregatable
// | |searchable
- // name esType | | |metadata | parent | subType
+ // name esType | | |metadata | subType
['bytes', 'long', true, true, { count: 10 } ],
['ssl', 'boolean', true, true, { count: 20 } ],
['@timestamp', 'date', true, true, { count: 30 } ],
@@ -40,9 +40,9 @@ function stubbedLogstashFields() {
['hashed', 'murmur3', false, true ],
['geo.coordinates', 'geo_point', true, true ],
['extension', 'text', true, true],
- ['extension.keyword', 'keyword', true, true, {}, 'extension', 'multi' ],
+ ['extension.keyword', 'keyword', true, true, {}, { multi: { parent: 'extension' } } ],
['machine.os', 'text', true, true ],
- ['machine.os.raw', 'keyword', true, true, {}, 'machine.os', 'multi' ],
+ ['machine.os.raw', 'keyword', true, true, {}, { multi: { parent: 'machine.os' } } ],
['geo.src', 'keyword', true, true ],
['_id', '_id', true, true ],
['_type', '_type', true, true ],
@@ -61,7 +61,6 @@ function stubbedLogstashFields() {
aggregatable,
searchable,
metadata = {},
- parent = undefined,
subType = undefined,
] = row;
@@ -87,7 +86,6 @@ function stubbedLogstashFields() {
script,
lang,
scripted,
- parent,
subType,
};
});
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/index.ts b/src/legacy/core_plugins/dashboard_embeddable_container/index.ts
index 74682722e9b89..714203de20385 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/index.ts
+++ b/src/legacy/core_plugins/dashboard_embeddable_container/index.ts
@@ -23,7 +23,6 @@ import { resolve } from 'path';
export default function(kibana: any) {
return new kibana.Plugin({
uiExports: {
- hacks: ['plugins/dashboard_embeddable_container/initialize'],
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
},
});
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/index.scss b/src/legacy/core_plugins/dashboard_embeddable_container/public/index.scss
index 88e570d137893..548e85746f866 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/index.scss
+++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/index.scss
@@ -1,6 +1,3 @@
@import 'src/legacy/ui/public/styles/styling_constants';
-@import 'src/legacy/core_plugins/embeddable_api/public/variables';
-@import './np_ready/public/lib/embeddable/grid/index';
-@import './np_ready/public/lib/embeddable/panel/index';
-@import './np_ready/public/lib/embeddable/viewport/index';
+@import '../../../../plugins/dashboard_embeddable_container/public/index';
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/initialize.ts b/src/legacy/core_plugins/dashboard_embeddable_container/public/initialize.ts
index a4bc3cf17026c..9880b336e76e5 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/initialize.ts
+++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/initialize.ts
@@ -16,5 +16,3 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-import './np_ready/public/legacy';
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/index.ts b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/index.ts
index 1dad1b488590e..d8c0de2bce3f4 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/index.ts
+++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/index.ts
@@ -17,13 +17,4 @@
* under the License.
*/
-import { PluginInitializerContext } from '../../../../../../core/public';
-import { DashboardEmbeddableContainerPublicPlugin } from './plugin';
-
-export * from './lib';
-
-export function plugin(initializerContext: PluginInitializerContext) {
- return new DashboardEmbeddableContainerPublicPlugin(initializerContext);
-}
-
-export { DashboardEmbeddableContainerPublicPlugin as Plugin };
+export * from '../../../../../../plugins/dashboard_embeddable_container/public';
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/legacy.ts b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/legacy.ts
index ccb04d8c2e027..9880b336e76e5 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/legacy.ts
+++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/legacy.ts
@@ -16,32 +16,3 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-/* eslint-disable @kbn/eslint/no-restricted-paths */
-import { npSetup, npStart } from 'ui/new_platform';
-import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
-import { ExitFullScreenButton } from 'ui/exit_full_screen';
-/* eslint-enable @kbn/eslint/no-restricted-paths */
-
-import { plugin } from '.';
-import {
- setup as embeddableSetup,
- start as embeddableStart,
-} from '../../../../embeddable_api/public/np_ready/public/legacy';
-
-const pluginInstance = plugin({} as any);
-
-export const setup = pluginInstance.setup(npSetup.core, {
- embeddable: embeddableSetup,
- uiActions: npSetup.plugins.uiActions,
-});
-
-export const start = pluginInstance.start(npStart.core, {
- embeddable: embeddableStart,
- inspector: npStart.plugins.inspector,
- __LEGACY: {
- SavedObjectFinder,
- ExitFullScreenButton,
- },
- uiActions: npStart.plugins.uiActions,
-});
diff --git a/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts b/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts
index c436e1d45c6d8..8d2337264d02f 100644
--- a/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts
+++ b/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts
@@ -18,21 +18,20 @@
*/
import { i18n } from '@kbn/i18n';
-import { Filter } from '@kbn/es-query';
-import { npStart } from 'ui/new_platform';
+import { CoreStart } from 'src/core/public';
import {
IAction,
createAction,
IncompatibleActionError,
} from '../../../../../../plugins/ui_actions/public';
-import { changeTimeFilter, extractTimeFilter, FilterManager } from '../filter_manager';
-import { TimefilterContract } from '../../timefilter';
+import { FilterManager, esFilters } from '../../../../../../plugins/data/public';
+import { TimefilterContract, changeTimeFilter, extractTimeFilter } from '../../timefilter';
import { applyFiltersPopover } from '../apply_filters/apply_filters_popover';
import { IndexPatternsStart } from '../../index_patterns';
export const GLOBAL_APPLY_FILTER_ACTION = 'GLOBAL_APPLY_FILTER_ACTION';
interface ActionContext {
- filters: Filter[];
+ filters: esFilters.Filter[];
timeFieldName?: string;
}
@@ -41,6 +40,7 @@ async function isCompatible(context: ActionContext) {
}
export function createFilterAction(
+ overlays: CoreStart['overlays'],
filterManager: FilterManager,
timeFilter: TimefilterContract,
indexPatternsService: IndexPatternsStart
@@ -63,7 +63,7 @@ export function createFilterAction(
throw new IncompatibleActionError();
}
- let selectedFilters: Filter[] = filters;
+ let selectedFilters: esFilters.Filter[] = filters;
if (selectedFilters.length > 1) {
const indexPatterns = await Promise.all(
@@ -72,8 +72,8 @@ export function createFilterAction(
})
);
- const filterSelectionPromise: Promise = new Promise(resolve => {
- const overlay = npStart.core.overlays.openModal(
+ const filterSelectionPromise: Promise = new Promise(resolve => {
+ const overlay = overlays.openModal(
applyFiltersPopover(
filters,
indexPatterns,
@@ -81,7 +81,7 @@ export function createFilterAction(
overlay.close();
resolve([]);
},
- (filterSelection: Filter[]) => {
+ (filterSelection: esFilters.Filter[]) => {
overlay.close();
resolve(filterSelection);
}
diff --git a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filter_popover_content.tsx b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filter_popover_content.tsx
index 5f7fbc1996433..e9d05d6340e58 100644
--- a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filter_popover_content.tsx
+++ b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filter_popover_content.tsx
@@ -28,19 +28,18 @@ import {
EuiModalHeaderTitle,
EuiSwitch,
} from '@elastic/eui';
-import { Filter } from '@kbn/es-query';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { Component } from 'react';
import { IndexPattern } from '../../index_patterns';
import { getFilterDisplayText } from '../filter_bar/filter_editor/lib/get_filter_display_text';
-import { mapAndFlattenFilters } from '../filter_manager/lib/map_and_flatten_filters';
+import { mapAndFlattenFilters, esFilters } from '../../../../../../plugins/data/public';
import { getDisplayValueFromFilter } from '../filter_bar/filter_editor/lib/get_display_value';
interface Props {
- filters: Filter[];
+ filters: esFilters.Filter[];
indexPatterns: IndexPattern[];
onCancel: () => void;
- onSubmit: (filters: Filter[]) => void;
+ onSubmit: (filters: esFilters.Filter[]) => void;
}
interface State {
@@ -58,7 +57,7 @@ export class ApplyFiltersPopoverContent extends Component {
isFilterSelected: props.filters.map(() => true),
};
}
- private getLabel(filter: Filter) {
+ private getLabel(filter: esFilters.Filter) {
const filterDisplayValue = getDisplayValueFromFilter(filter, this.props.indexPatterns);
return getFilterDisplayText(filter, filterDisplayValue);
}
diff --git a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx
index 0687701429866..41f757e726c40 100644
--- a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx
+++ b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx
@@ -18,15 +18,15 @@
*/
import { EuiModal, EuiOverlayMask } from '@elastic/eui';
-import { Filter } from '@kbn/es-query';
import React, { Component } from 'react';
import { ApplyFiltersPopoverContent } from './apply_filter_popover_content';
import { IndexPattern } from '../../index_patterns/index_patterns';
+import { esFilters } from '../../../../../../plugins/data/public';
interface Props {
- filters: Filter[];
+ filters: esFilters.Filter[];
onCancel: () => void;
- onSubmit: (filters: Filter[]) => void;
+ onSubmit: (filters: esFilters.Filter[]) => void;
indexPatterns: IndexPattern[];
}
@@ -56,9 +56,9 @@ export class ApplyFiltersPopover extends Component {
}
type cancelFunction = () => void;
-type submitFunction = (filters: Filter[]) => void;
+type submitFunction = (filters: esFilters.Filter[]) => void;
export const applyFiltersPopover = (
- filters: Filter[],
+ filters: esFilters.Filter[],
indexPatterns: IndexPattern[],
onCancel: cancelFunction,
onSubmit: submitFunction
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_group.scss b/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_group.scss
index 3c90e18aecd5d..1c47c28097454 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_group.scss
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_group.scss
@@ -11,6 +11,10 @@
margin-top: $euiSizeXS;
}
+.globalFilterBar__addButton {
+ min-height: $euiSizeL + $euiSizeXS; // same height as the badges
+}
+
// sass-lint:disable quotes
.globalFilterGroup__branch {
padding: $euiSizeS $euiSizeM 0 0;
@@ -40,4 +44,3 @@
margin-top: $euiSize * -1;
}
}
-
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_item.scss b/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_item.scss
index caf3b0b796b9e..84538a62ca005 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_item.scss
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_item.scss
@@ -1,5 +1,5 @@
-@import '@elastic/eui/src/components/form/mixins';
@import '@elastic/eui/src/components/form/variables';
+@import '@elastic/eui/src/components/form/mixins';
/**
* 1. Allow wrapping of long filter items
@@ -19,11 +19,17 @@
&:not(.globalFilterItem-isDisabled) {
@include euiFormControlDefaultShadow;
+ box-shadow: #{$euiFormControlBoxShadow}, inset 0 0 0 1px $kbnGlobalFilterItemBorderColor; // Make the actual border more visible
+ }
+
+ &:focus-within {
+ animation: none !important; // Remove focus ring animation otherwise it overrides simulated border via box-shadow
}
}
.globalFilterItem-isDisabled {
- background-color: transparentize($euiColorLightShade, .4);
+ color: $euiColorDarkShade;
+ background-color: transparentize($euiColorLightShade, 0.5);
text-decoration: line-through;
font-weight: $euiFontWeightRegular;
font-style: italic;
@@ -39,12 +45,22 @@
bottom: 0;
left: 0;
width: $euiSizeXS;
- background-color: $euiColorVis0;
+ background-color: $kbnGlobalFilterItemBorderColor;
border-top-left-radius: $euiBorderRadius / 2;
border-bottom-left-radius: $euiBorderRadius / 2;
}
}
+.globalFilterItem-isExcluded {
+ &:not(.globalFilterItem-isDisabled) {
+ box-shadow: #{$euiFormControlBoxShadow}, inset 0 0 0 1px $kbnGlobalFilterItemBorderColorExcluded;
+
+ &::before {
+ background-color: $kbnGlobalFilterItemPinnedColorExcluded;
+ }
+ }
+}
+
.globalFilterItem__editorForm {
padding: $euiSizeM;
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/_index.scss b/src/legacy/core_plugins/data/public/filter/filter_bar/_index.scss
index 3c57b7fe2ca3a..5333aff8b87da 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/_index.scss
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/_index.scss
@@ -1,2 +1,3 @@
+@import 'variables';
@import 'global_filter_group';
@import 'global_filter_item';
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/_variables.scss b/src/legacy/core_plugins/data/public/filter/filter_bar/_variables.scss
new file mode 100644
index 0000000000000..3a9a0df4332c8
--- /dev/null
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/_variables.scss
@@ -0,0 +1,3 @@
+$kbnGlobalFilterItemBorderColor: tintOrShade($euiColorMediumShade, 35%, 20%);
+$kbnGlobalFilterItemBorderColorExcluded: tintOrShade($euiColorDanger, 70%, 50%);
+$kbnGlobalFilterItemPinnedColorExcluded: tintOrShade($euiColorDanger, 30%, 20%);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx
index 066adb1e3275e..333e1e328651d 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx
@@ -18,16 +18,6 @@
*/
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiPopover } from '@elastic/eui';
-import {
- buildEmptyFilter,
- disableFilter,
- enableFilter,
- Filter,
- pinFilter,
- toggleFilterDisabled,
- toggleFilterNegated,
- unpinFilter,
-} from '@kbn/es-query';
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
import classNames from 'classnames';
import React, { useState } from 'react';
@@ -38,10 +28,11 @@ import { FilterEditor } from './filter_editor';
import { FilterItem } from './filter_item';
import { FilterOptions } from './filter_options';
import { useKibana, KibanaContextProvider } from '../../../../../../plugins/kibana_react/public';
+import { esFilters } from '../../../../../../plugins/data/public';
interface Props {
- filters: Filter[];
- onFiltersUpdated?: (filters: Filter[]) => void;
+ filters: esFilters.Filter[];
+ onFiltersUpdated?: (filters: esFilters.Filter[]) => void;
className: string;
indexPatterns: IndexPattern[];
intl: InjectedIntl;
@@ -87,7 +78,7 @@ function FilterBarUI(props: Props) {
return content;
}
- function onFiltersUpdated(filters: Filter[]) {
+ function onFiltersUpdated(filters: esFilters.Filter[]) {
if (props.onFiltersUpdated) {
props.onFiltersUpdated(filters);
}
@@ -112,13 +103,14 @@ function FilterBarUI(props: Props) {
const isPinned = uiSettings!.get('filters:pinnedByDefault');
const [indexPattern] = props.indexPatterns;
const index = indexPattern && indexPattern.id;
- const newFilter = buildEmptyFilter(isPinned, index);
+ const newFilter = esFilters.buildEmptyFilter(isPinned, index);
const button = (
setIsAddFilterPopoverOpen(true)}
data-test-subj="addFilter"
+ className="globalFilterBar__addButton"
>
+{' '}
void;
+ onSubmit: (filter: esFilters.Filter) => void;
onCancel: () => void;
intl: InjectedIntl;
}
@@ -379,7 +379,9 @@ class FilterEditorUI extends Component {
private getFieldFromFilter() {
const indexPattern = this.getIndexPatternFromFilter();
- return indexPattern && getFieldFromFilter(this.props.filter as FieldFilter, indexPattern);
+ return (
+ indexPattern && getFieldFromFilter(this.props.filter as esFilters.FieldFilter, indexPattern)
+ );
}
private getSelectedOperator() {
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts
index 734c5d00e58d5..dbff5096f2287 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts
@@ -17,7 +17,6 @@
* under the License.
*/
-import { FilterStateStore, toggleFilterNegated } from '@kbn/es-query';
import { mockFields, mockIndexPattern } from '../../../../index_patterns';
import { IndexPattern, Field } from '../../../../index';
import {
@@ -42,6 +41,7 @@ import { existsFilter } from './fixtures/exists_filter';
import { phraseFilter } from './fixtures/phrase_filter';
import { phrasesFilter } from './fixtures/phrases_filter';
import { rangeFilter } from './fixtures/range_filter';
+import { esFilters } from '../../../../../../../../plugins/data/public';
jest.mock('ui/new_platform');
@@ -81,7 +81,7 @@ describe('Filter editor utils', () => {
});
it('should return "is not" for phrase filter', () => {
- const negatedPhraseFilter = toggleFilterNegated(phraseFilter);
+ const negatedPhraseFilter = esFilters.toggleFilterNegated(phraseFilter);
const operator = getOperatorFromFilter(negatedPhraseFilter);
expect(operator).not.toBeUndefined();
expect(operator && operator.type).toBe('phrase');
@@ -96,7 +96,7 @@ describe('Filter editor utils', () => {
});
it('should return "is not one of" for negated phrases filter', () => {
- const negatedPhrasesFilter = toggleFilterNegated(phrasesFilter);
+ const negatedPhrasesFilter = esFilters.toggleFilterNegated(phrasesFilter);
const operator = getOperatorFromFilter(negatedPhrasesFilter);
expect(operator).not.toBeUndefined();
expect(operator && operator.type).toBe('phrases');
@@ -111,7 +111,7 @@ describe('Filter editor utils', () => {
});
it('should return "is not between" for negated range filter', () => {
- const negatedRangeFilter = toggleFilterNegated(rangeFilter);
+ const negatedRangeFilter = esFilters.toggleFilterNegated(rangeFilter);
const operator = getOperatorFromFilter(negatedRangeFilter);
expect(operator).not.toBeUndefined();
expect(operator && operator.type).toBe('range');
@@ -126,7 +126,7 @@ describe('Filter editor utils', () => {
});
it('should return "does not exists" for negated exists filter', () => {
- const negatedExistsFilter = toggleFilterNegated(existsFilter);
+ const negatedExistsFilter = esFilters.toggleFilterNegated(existsFilter);
const operator = getOperatorFromFilter(negatedExistsFilter);
expect(operator).not.toBeUndefined();
expect(operator && operator.type).toBe('exists');
@@ -246,7 +246,7 @@ describe('Filter editor utils', () => {
it('should build phrase filters', () => {
const params = 'foo';
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -268,7 +268,7 @@ describe('Filter editor utils', () => {
it('should build phrases filters', () => {
const params = ['foo', 'bar'];
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -290,7 +290,7 @@ describe('Filter editor utils', () => {
it('should build range filters', () => {
const params = { from: 'foo', to: 'qux' };
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -311,7 +311,7 @@ describe('Filter editor utils', () => {
it('should build exists filters', () => {
const params = undefined;
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -332,7 +332,7 @@ describe('Filter editor utils', () => {
it('should include disabled state', () => {
const params = undefined;
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -348,7 +348,7 @@ describe('Filter editor utils', () => {
it('should negate based on operator', () => {
const params = undefined;
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts
index f0628f03c173e..b7d20526a6b92 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts
@@ -18,42 +18,30 @@
*/
import dateMath from '@elastic/datemath';
-import {
- buildExistsFilter,
- buildPhraseFilter,
- buildPhrasesFilter,
- buildRangeFilter,
- FieldFilter,
- Filter,
- FilterMeta,
- FilterStateStore,
- PhraseFilter,
- PhrasesFilter,
- RangeFilter,
-} from '@kbn/es-query';
import { omit } from 'lodash';
import { Ipv4Address } from '../../../../../../../../plugins/kibana_utils/public';
import { Field, IndexPattern, isFilterable } from '../../../../index_patterns';
import { FILTER_OPERATORS, Operator } from './filter_operators';
+import { esFilters } from '../../../../../../../../plugins/data/public';
export function getIndexPatternFromFilter(
- filter: Filter,
+ filter: esFilters.Filter,
indexPatterns: IndexPattern[]
): IndexPattern | undefined {
return indexPatterns.find(indexPattern => indexPattern.id === filter.meta.index);
}
-export function getFieldFromFilter(filter: FieldFilter, indexPattern: IndexPattern) {
+export function getFieldFromFilter(filter: esFilters.FieldFilter, indexPattern: IndexPattern) {
return indexPattern.fields.find(field => field.name === filter.meta.key);
}
-export function getOperatorFromFilter(filter: Filter) {
+export function getOperatorFromFilter(filter: esFilters.Filter) {
return FILTER_OPERATORS.find(operator => {
return filter.meta.type === operator.type && filter.meta.negate === operator.negate;
});
}
-export function getQueryDslFromFilter(filter: Filter) {
+export function getQueryDslFromFilter(filter: esFilters.Filter) {
return omit(filter, ['$state', 'meta']);
}
@@ -67,16 +55,16 @@ export function getOperatorOptions(field: Field) {
});
}
-export function getFilterParams(filter: Filter) {
+export function getFilterParams(filter: esFilters.Filter) {
switch (filter.meta.type) {
case 'phrase':
- return (filter as PhraseFilter).meta.params.query;
+ return (filter as esFilters.PhraseFilter).meta.params.query;
case 'phrases':
- return (filter as PhrasesFilter).meta.params;
+ return (filter as esFilters.PhrasesFilter).meta.params;
case 'range':
return {
- from: (filter as RangeFilter).meta.params.gte,
- to: (filter as RangeFilter).meta.params.lt,
+ from: (filter as esFilters.RangeFilter).meta.params.gte,
+ to: (filter as esFilters.RangeFilter).meta.params.lt,
};
}
}
@@ -133,8 +121,8 @@ export function buildFilter(
disabled: boolean,
params: any,
alias: string | null,
- store: FilterStateStore
-): Filter {
+ store: esFilters.FilterStateStore
+): esFilters.Filter {
const filter = buildBaseFilter(indexPattern, field, operator, params);
filter.meta.alias = alias;
filter.meta.negate = operator.negate;
@@ -148,17 +136,17 @@ function buildBaseFilter(
field: Field,
operator: Operator,
params: any
-): Filter {
+): esFilters.Filter {
switch (operator.type) {
case 'phrase':
- return buildPhraseFilter(field, params, indexPattern);
+ return esFilters.buildPhraseFilter(field, params, indexPattern);
case 'phrases':
- return buildPhrasesFilter(field, params, indexPattern);
+ return esFilters.buildPhrasesFilter(field, params, indexPattern);
case 'range':
const newParams = { gte: params.from, lt: params.to };
- return buildRangeFilter(field, newParams, indexPattern);
+ return esFilters.buildRangeFilter(field, newParams, indexPattern);
case 'exists':
- return buildExistsFilter(field, indexPattern);
+ return esFilters.buildExistsFilter(field, indexPattern);
default:
throw new Error(`Unknown operator type: ${operator.type}`);
}
@@ -170,10 +158,10 @@ export function buildCustomFilter(
disabled: boolean,
negate: boolean,
alias: string | null,
- store: FilterStateStore
-): Filter {
- const meta: FilterMeta = { index, type: 'custom', disabled, negate, alias };
- const filter: Filter = { ...queryDsl, meta };
+ store: esFilters.FilterStateStore
+): esFilters.Filter {
+ const meta: esFilters.FilterMeta = { index, type: 'custom', disabled, negate, alias };
+ const filter: esFilters.Filter = { ...queryDsl, meta };
filter.$state = { store };
return filter;
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts
index a17f767006f3e..5af97818f9bfb 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { ExistsFilter, FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../../plugins/data/public';
-export const existsFilter: ExistsFilter = {
+export const existsFilter: esFilters.ExistsFilter = {
meta: {
index: 'logstash-*',
negate: false,
@@ -29,6 +29,6 @@ export const existsFilter: ExistsFilter = {
alias: null,
},
$state: {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
},
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts
index 77bb8e06c801a..b6c8b9905e6b3 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { FilterStateStore, PhraseFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../../plugins/data/public';
-export const phraseFilter: PhraseFilter = {
+export const phraseFilter: esFilters.PhraseFilter = {
meta: {
negate: false,
index: 'logstash-*',
@@ -33,6 +33,6 @@ export const phraseFilter: PhraseFilter = {
},
},
$state: {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
},
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts
index e86c3ee1318e3..2e2ba4f798bdd 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { FilterStateStore, PhrasesFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../../plugins/data/public';
-export const phrasesFilter: PhrasesFilter = {
+export const phrasesFilter: esFilters.PhrasesFilter = {
meta: {
index: 'logstash-*',
type: 'phrases',
@@ -31,6 +31,6 @@ export const phrasesFilter: PhrasesFilter = {
alias: null,
},
$state: {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
},
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts
index 46a5181450fea..c6438e30ecec6 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { FilterStateStore, RangeFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../../plugins/data/public';
-export const rangeFilter: RangeFilter = {
+export const rangeFilter: esFilters.RangeFilter = {
meta: {
index: 'logstash-*',
negate: false,
@@ -34,7 +34,7 @@ export const rangeFilter: RangeFilter = {
},
},
$state: {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
},
range: {},
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_display_value.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_display_value.ts
index 551b99d01b7da..d8af7b3e97ad2 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_display_value.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_display_value.ts
@@ -18,7 +18,7 @@
*/
import { get } from 'lodash';
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../plugins/data/public';
import { IndexPattern } from '../../../../index_patterns/index_patterns';
import { Field } from '../../../../index_patterns/fields';
import { getIndexPatternFromFilter } from './filter_editor_utils';
@@ -33,7 +33,10 @@ function getValueFormatter(indexPattern?: IndexPattern, key?: string) {
return format;
}
-export function getDisplayValueFromFilter(filter: Filter, indexPatterns: IndexPattern[]): string {
+export function getDisplayValueFromFilter(
+ filter: esFilters.Filter,
+ indexPatterns: IndexPattern[]
+): string {
const indexPattern = getIndexPatternFromFilter(filter, indexPatterns);
if (typeof filter.meta.value === 'function') {
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.ts
deleted file mode 100644
index 73ee1a69a2ce3..0000000000000
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.ts
+++ /dev/null
@@ -1,53 +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 { Filter } from '@kbn/es-query';
-import { i18n } from '@kbn/i18n';
-import { existsOperator, isOneOfOperator } from './filter_operators';
-
-export function getFilterDisplayText(filter: Filter, filterDisplayName: string) {
- const prefix = filter.meta.negate
- ? ` ${i18n.translate('data.filter.filterBar.negatedFilterPrefix', {
- defaultMessage: 'NOT ',
- })}`
- : '';
-
- if (filter.meta.alias !== null) {
- return `${prefix}${filter.meta.alias}`;
- }
-
- switch (filter.meta.type) {
- case 'exists':
- return `${prefix}${filter.meta.key} ${existsOperator.message}`;
- case 'geo_bounding_box':
- return `${prefix}${filter.meta.key}: ${filterDisplayName}`;
- case 'geo_polygon':
- return `${prefix}${filter.meta.key}: ${filterDisplayName}`;
- case 'phrase':
- return `${prefix}${filter.meta.key}: ${filterDisplayName}`;
- case 'phrases':
- return `${prefix}${filter.meta.key} ${isOneOfOperator.message} ${filterDisplayName}`;
- case 'query_string':
- return `${prefix}${filterDisplayName}`;
- case 'range':
- return `${prefix}${filter.meta.key}: ${filterDisplayName}`;
- default:
- return `${prefix}${JSON.stringify(filter.query)}`;
- }
-}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.tsx
new file mode 100644
index 0000000000000..21abcd8510046
--- /dev/null
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.tsx
@@ -0,0 +1,102 @@
+/*
+ * 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 } from 'react';
+import { EuiTextColor } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { existsOperator, isOneOfOperator } from './filter_operators';
+import { esFilters } from '../../../../../../../../plugins/data/public';
+
+export function getFilterDisplayText(filter: esFilters.Filter, filterDisplayName: string) {
+ const prefixText = filter.meta.negate
+ ? ` ${i18n.translate('data.filter.filterBar.negatedFilterPrefix', {
+ defaultMessage: 'NOT ',
+ })}`
+ : '';
+ const prefix =
+ filter.meta.negate && !filter.meta.disabled ? (
+ {prefixText}
+ ) : (
+ prefixText
+ );
+
+ if (filter.meta.alias !== null) {
+ return `${prefix}${filter.meta.alias}`;
+ }
+
+ switch (filter.meta.type) {
+ case 'exists':
+ return (
+
+ {prefix}
+ {filter.meta.key} {existsOperator.message}
+
+ );
+ case 'geo_bounding_box':
+ return (
+
+ {prefix}
+ {filter.meta.key}: {filterDisplayName}
+
+ );
+ case 'geo_polygon':
+ return (
+
+ {prefix}
+ {filter.meta.key}: {filterDisplayName}
+
+ );
+ case 'phrase':
+ return (
+
+ {prefix}
+ {filter.meta.key}: {filterDisplayName}
+
+ );
+ case 'phrases':
+ return (
+
+ {prefix}
+ {filter.meta.key} {isOneOfOperator.message} {filterDisplayName}
+
+ );
+ case 'query_string':
+ return (
+
+ {prefix}
+ {filterDisplayName}
+
+ );
+ case 'range':
+ case 'phrase':
+ return (
+
+ {prefix}
+ {filter.meta.key}: {filterDisplayName}
+
+ );
+ default:
+ return (
+
+ {prefix}
+ {JSON.stringify(filter.query)}
+
+ );
+ }
+}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx
index 2e98cbd306e9c..50c1672333801 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx
@@ -18,13 +18,6 @@
*/
import { EuiContextMenu, EuiPopover } from '@elastic/eui';
-import {
- Filter,
- isFilterPinned,
- toggleFilterDisabled,
- toggleFilterNegated,
- toggleFilterPinned,
-} from '@kbn/es-query';
import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
import classNames from 'classnames';
import React, { Component } from 'react';
@@ -33,13 +26,14 @@ import { IndexPattern } from '../../index_patterns';
import { FilterEditor } from './filter_editor';
import { FilterView } from './filter_view';
import { getDisplayValueFromFilter } from './filter_editor/lib/get_display_value';
+import { esFilters } from '../../../../../../plugins/data/public';
interface Props {
id: string;
- filter: Filter;
+ filter: esFilters.Filter;
indexPatterns: IndexPattern[];
className?: string;
- onUpdate: (filter: Filter) => void;
+ onUpdate: (filter: esFilters.Filter) => void;
onRemove: () => void;
intl: InjectedIntl;
uiSettings: UiSettingsClientContract;
@@ -62,7 +56,7 @@ class FilterItemUI extends Component {
'globalFilterItem',
{
'globalFilterItem-isDisabled': disabled,
- 'globalFilterItem-isPinned': isFilterPinned(filter),
+ 'globalFilterItem-isPinned': esFilters.isFilterPinned(filter),
'globalFilterItem-isExcluded': negate,
},
this.props.className
@@ -91,7 +85,7 @@ class FilterItemUI extends Component {
id: 0,
items: [
{
- name: isFilterPinned(filter)
+ name: esFilters.isFilterPinned(filter)
? this.props.intl.formatMessage({
id: 'data.filter.filterBar.unpinFilterButtonLabel',
defaultMessage: 'Unpin',
@@ -209,23 +203,23 @@ class FilterItemUI extends Component {
});
};
- private onSubmit = (filter: Filter) => {
+ private onSubmit = (filter: esFilters.Filter) => {
this.closePopover();
this.props.onUpdate(filter);
};
private onTogglePinned = () => {
- const filter = toggleFilterPinned(this.props.filter);
+ const filter = esFilters.toggleFilterPinned(this.props.filter);
this.props.onUpdate(filter);
};
private onToggleNegated = () => {
- const filter = toggleFilterNegated(this.props.filter);
+ const filter = esFilters.toggleFilterNegated(this.props.filter);
this.props.onUpdate(filter);
};
private onToggleDisabled = () => {
- const filter = toggleFilterDisabled(this.props.filter);
+ const filter = esFilters.toggleFilterDisabled(this.props.filter);
this.props.onUpdate(filter);
};
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_view/index.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_view/index.tsx
index a7ea23efce49e..6421691c4ef41 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_view/index.tsx
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_view/index.tsx
@@ -17,14 +17,14 @@
* under the License.
*/
-import { EuiBadge } from '@elastic/eui';
-import { Filter, isFilterPinned } from '@kbn/es-query';
+import { EuiBadge, useInnerText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { SFC } from 'react';
import { getFilterDisplayText } from '../filter_editor/lib/get_filter_display_text';
+import { esFilters } from '../../../../../../../plugins/data/public';
interface Props {
- filter: Filter;
+ filter: esFilters.Filter;
displayName: string;
[propName: string]: any;
}
@@ -36,12 +36,15 @@ export const FilterView: SFC = ({
displayName,
...rest
}: Props) => {
+ const [ref, innerText] = useInnerText();
+ const displayText = {getFilterDisplayText(filter, displayName)} ;
+
let title = i18n.translate('data.filter.filterBar.moreFilterActionsMessage', {
- defaultMessage: 'Filter: {displayText}. Select for more filter actions.',
- values: { displayText: getFilterDisplayText(filter, displayName) },
+ defaultMessage: 'Filter: {innerText}. Select for more filter actions.',
+ values: { innerText },
});
- if (isFilterPinned(filter)) {
+ if (esFilters.isFilterPinned(filter)) {
title = `${i18n.translate('data.filter.filterBar.pinnedFilterPrefix', {
defaultMessage: 'Pinned',
})} ${title}`;
@@ -72,7 +75,7 @@ export const FilterView: SFC = ({
})}
{...rest}
>
- {getFilterDisplayText(filter, displayName)}
+ {displayText}
);
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts
index d1cad9a812399..08d5955d3fae9 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts
@@ -19,12 +19,11 @@
import sinon from 'sinon';
-import { FilterStateStore } from '@kbn/es-query';
import { FilterStateManager } from './filter_state_manager';
import { StubState } from './test_helpers/stub_state';
import { getFilter } from './test_helpers/get_stub_filter';
-import { FilterManager } from './filter_manager';
+import { FilterManager, esFilters } from '../../../../../../plugins/data/public';
import { coreMock } from '../../../../../../core/public/mocks';
const setupMock = coreMock.createSetup();
@@ -59,7 +58,7 @@ describe('filter_state_manager', () => {
});
test('should NOT watch state until both app and global state are defined', done => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
globalStateStub.filters.push(f1);
setTimeout(() => {
@@ -72,8 +71,8 @@ describe('filter_state_manager', () => {
appStateStub.save = sinon.stub();
globalStateStub.save = sinon.stub();
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.setFilters([f1, f2]);
@@ -101,33 +100,37 @@ describe('filter_state_manager', () => {
});
test('should update filter manager global filters', done => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- globalStateStub.filters.push(f1);
-
- setTimeout(() => {
+ const updateSubscription = filterManager.getUpdates$().subscribe(() => {
expect(filterManager.getGlobalFilters()).toHaveLength(1);
+ if (updateSubscription) {
+ updateSubscription.unsubscribe();
+ }
done();
- }, 100);
- });
-
- test('should update filter manager app filters', done => {
- expect(filterManager.getAppFilters()).toHaveLength(0);
+ });
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- appStateStub.filters.push(f1);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, true, true, 'age', 34);
+ globalStateStub.filters.push(f1);
+ });
- setTimeout(() => {
+ test('should update filter manager app filter', done => {
+ const updateSubscription = filterManager.getUpdates$().subscribe(() => {
expect(filterManager.getAppFilters()).toHaveLength(1);
+ if (updateSubscription) {
+ updateSubscription.unsubscribe();
+ }
done();
- }, 100);
+ });
+
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ appStateStub.filters.push(f1);
});
test('should update URL when filter manager filters are set', () => {
appStateStub.save = sinon.stub();
globalStateStub.save = sinon.stub();
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.setFilters([f1, f2]);
@@ -139,8 +142,8 @@ describe('filter_state_manager', () => {
appStateStub.save = sinon.stub();
globalStateStub.save = sinon.stub();
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.addFilters([f1, f2]);
@@ -156,7 +159,7 @@ describe('filter_state_manager', () => {
** And triggers *another* filter manager update.
*/
test('should NOT re-trigger filter manager', done => {
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.setFilters([f1]);
const setFiltersSpy = sinon.spy(filterManager, 'setFilters');
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts
index 06f91e35db96e..61821b7ad45e9 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts
@@ -17,11 +17,9 @@
* under the License.
*/
-import { FilterStateStore } from '@kbn/es-query';
-
import _ from 'lodash';
import { State } from 'ui/state_management/state';
-import { FilterManager } from './filter_manager';
+import { FilterManager, esFilters } from '../../../../../../plugins/data/public';
type GetAppStateFunc = () => State | undefined | null;
@@ -73,8 +71,8 @@ export class FilterStateManager {
const newGlobalFilters = _.cloneDeep(globalFilters);
const newAppFilters = _.cloneDeep(appFilters);
- FilterManager.setFiltersStore(newAppFilters, FilterStateStore.APP_STATE);
- FilterManager.setFiltersStore(newGlobalFilters, FilterStateStore.GLOBAL_STATE);
+ FilterManager.setFiltersStore(newAppFilters, esFilters.FilterStateStore.APP_STATE);
+ FilterManager.setFiltersStore(newGlobalFilters, esFilters.FilterStateStore.GLOBAL_STATE);
this.filterManager.setFilters(newGlobalFilters.concat(newAppFilters));
}, 10);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/index.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/index.ts
index ac533eaaf89ea..ebb622783c3d1 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/index.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_manager/index.ts
@@ -17,10 +17,4 @@
* under the License.
*/
-export { FilterManager } from './filter_manager';
export { FilterStateManager } from './filter_state_manager';
-
-export { uniqFilters } from './lib/uniq_filters';
-export { extractTimeFilter } from './lib/extract_time_filter';
-export { changeTimeFilter } from './lib/change_time_filter';
-export { onlyDisabledFiltersChanged } from './lib/only_disabled';
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/dedup_filters.test.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/lib/dedup_filters.test.ts
deleted file mode 100644
index 75bd9d5dfbd81..0000000000000
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/dedup_filters.test.ts
+++ /dev/null
@@ -1,79 +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 { Filter, buildRangeFilter, FilterStateStore, buildQueryFilter } from '@kbn/es-query';
-import { dedupFilters } from './dedup_filters';
-
-describe('filter manager utilities', () => {
- describe('dedupFilters(existing, filters)', () => {
- test('should return only filters which are not in the existing', () => {
- const existing: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index'),
- buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
- ];
- const filters: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index'),
- buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
- ];
- const results = dedupFilters(existing, filters);
-
- expect(results).toContain(filters[0]);
- expect(results).not.toContain(filters[1]);
- });
-
- test('should ignore the disabled attribute when comparing ', () => {
- const existing: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index'),
- {
- ...buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
- meta: { disabled: true, negate: false, alias: null },
- },
- ];
- const filters: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index'),
- buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
- ];
- const results = dedupFilters(existing, filters);
-
- expect(results).toContain(filters[0]);
- expect(results).not.toContain(filters[1]);
- });
-
- test('should ignore $state attribute', () => {
- const existing: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index'),
- {
- ...buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
- $state: { store: FilterStateStore.APP_STATE },
- },
- ];
- const filters: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index'),
- {
- ...buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
- $state: { store: FilterStateStore.GLOBAL_STATE },
- },
- ];
- const results = dedupFilters(existing, filters);
-
- expect(results).toContain(filters[0]);
- expect(results).not.toContain(filters[1]);
- });
- });
-});
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_stub_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_stub_filter.ts
index 20d9e236f49be..5238efe5efa59 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_stub_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_stub_filter.ts
@@ -17,15 +17,15 @@
* under the License.
*/
-import { Filter, FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../plugins/data/public';
export function getFilter(
- store: FilterStateStore,
+ store: esFilters.FilterStateStore,
disabled: boolean,
negated: boolean,
queryKey: string,
queryValue: any
-): Filter {
+): esFilters.Filter {
return {
$state: {
store,
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_state.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_state.ts
index ab92016d1b9ab..f0a4bdef0229d 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_state.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_state.ts
@@ -19,11 +19,11 @@
import sinon from 'sinon';
-import { Filter } from '@kbn/es-query';
import { State } from 'ui/state_management/state';
+import { esFilters } from '../../../../../../../plugins/data/public';
export class StubState implements State {
- filters: Filter[];
+ filters: esFilters.Filter[];
save: sinon.SinonSpy;
constructor() {
diff --git a/src/legacy/core_plugins/data/public/filter/index.tsx b/src/legacy/core_plugins/data/public/filter/index.tsx
index cda7350ecadef..005c4904a4f39 100644
--- a/src/legacy/core_plugins/data/public/filter/index.tsx
+++ b/src/legacy/core_plugins/data/public/filter/index.tsx
@@ -17,8 +17,6 @@
* under the License.
*/
-export * from './filter_service';
-
export { FilterBar } from './filter_bar';
export { ApplyFiltersPopover } from './apply_filters';
diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts
index cb3869ff57711..502ca206e8e12 100644
--- a/src/legacy/core_plugins/data/public/index.ts
+++ b/src/legacy/core_plugins/data/public/index.ts
@@ -43,14 +43,7 @@ export { SearchBar, SearchBarProps, SavedQueryAttributes, SavedQuery } from './s
/** @public static code */
export * from '../common';
-export {
- FilterManager,
- FilterStateManager,
- uniqFilters,
- extractTimeFilter,
- changeTimeFilter,
- onlyDisabledFiltersChanged,
-} from './filter/filter_manager';
+export { FilterStateManager } from './filter/filter_manager';
export {
CONTAINS_SPACES,
getFromSavedObject,
@@ -69,4 +62,11 @@ export {
mockIndexPattern,
} from './index_patterns';
-export { TimeHistoryContract, TimefilterContract, getTime, InputTimeRange } from './timefilter';
+export {
+ TimeHistoryContract,
+ TimefilterContract,
+ getTime,
+ InputTimeRange,
+ extractTimeFilter,
+ changeTimeFilter,
+} from './timefilter';
diff --git a/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts b/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts
index 4097f5429a80f..dc5023795bf19 100644
--- a/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts
+++ b/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts
@@ -30,6 +30,11 @@ import { getNotifications } from '../services';
import { getKbnFieldType } from '../../../../../../plugins/data/public';
+interface FieldSubType {
+ multi?: { parent: string };
+ nested?: { path: string };
+}
+
export type FieldSpec = Record;
export interface FieldType {
name: string;
@@ -47,8 +52,7 @@ export interface FieldType {
visualizable?: boolean;
readFromDocValues?: boolean;
scripted?: boolean;
- parent?: string;
- subType?: string;
+ subType?: FieldSubType;
displayName?: string;
format?: any;
}
@@ -68,8 +72,7 @@ export class Field implements FieldType {
sortable?: boolean;
visualizable?: boolean;
scripted?: boolean;
- parent?: string;
- subType?: string;
+ subType?: FieldSubType;
displayName?: string;
format: any;
routes: Record = {
@@ -165,7 +168,6 @@ export class Field implements FieldType {
obj.writ('conflictDescriptions');
// multi info
- obj.fact('parent');
obj.fact('subType');
return obj.create();
diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts
index d445e2e58cd54..4767b6d3a3ca7 100644
--- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts
+++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts
@@ -29,7 +29,7 @@ import { fieldFormats } from 'ui/registry/field_formats';
import { createIndexPatternCache } from './_pattern_cache';
import { IndexPattern } from './index_pattern';
-import { IndexPatternsApiClient } from './index_patterns_api_client';
+import { IndexPatternsApiClient, GetFieldsOptions } from './index_patterns_api_client';
const indexPatternCache = createIndexPatternCache();
@@ -93,6 +93,14 @@ export class IndexPatterns {
});
};
+ getFieldsForTimePattern = (options: GetFieldsOptions = {}) => {
+ return this.apiClient.getFieldsForTimePattern(options);
+ };
+
+ getFieldsForWildcard = (options: GetFieldsOptions = {}) => {
+ return this.apiClient.getFieldsForWildcard(options);
+ };
+
clearCache = (id?: string) => {
this.savedObjectsCache = null;
if (id) {
diff --git a/src/legacy/core_plugins/data/public/legacy.ts b/src/legacy/core_plugins/data/public/legacy.ts
index e151726a6d702..b1d838aed992d 100644
--- a/src/legacy/core_plugins/data/public/legacy.ts
+++ b/src/legacy/core_plugins/data/public/legacy.ts
@@ -35,18 +35,13 @@
*/
import { npSetup, npStart } from 'ui/new_platform';
-import { LegacyDependenciesPlugin } from './shim/legacy_dependencies_plugin';
import { plugin } from '.';
const dataPlugin = plugin();
-const legacyPlugin = new LegacyDependenciesPlugin();
-export const setup = dataPlugin.setup(npSetup.core, {
- __LEGACY: legacyPlugin.setup(),
-});
+export const setup = dataPlugin.setup(npSetup.core);
export const start = dataPlugin.start(npStart.core, {
data: npStart.plugins.data,
uiActions: npSetup.plugins.uiActions,
- __LEGACY: legacyPlugin.start(),
});
diff --git a/src/legacy/core_plugins/data/public/mocks.ts b/src/legacy/core_plugins/data/public/mocks.ts
index 2a82927bb3ebf..4a7fe8efa4068 100644
--- a/src/legacy/core_plugins/data/public/mocks.ts
+++ b/src/legacy/core_plugins/data/public/mocks.ts
@@ -17,14 +17,12 @@
* under the License.
*/
-import { filterServiceMock } from './filter/filter_service.mock';
import { indexPatternsServiceMock } from './index_patterns/index_patterns_service.mock';
import { queryServiceMock } from './query/query_service.mock';
import { timefilterServiceMock } from './timefilter/timefilter_service.mock';
function createDataSetupMock() {
return {
- filter: filterServiceMock.createSetupContract(),
indexPatterns: indexPatternsServiceMock.createSetupContract(),
query: queryServiceMock.createSetupContract(),
timefilter: timefilterServiceMock.createSetupContract(),
diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts
index 2b634e54e5cbf..03c9b0e93309d 100644
--- a/src/legacy/core_plugins/data/public/plugin.ts
+++ b/src/legacy/core_plugins/data/public/plugin.ts
@@ -20,13 +20,9 @@
import { CoreSetup, CoreStart, Plugin } from 'kibana/public';
import { SearchService, SearchStart, createSearchBar, StatetfulSearchBarProps } from './search';
import { QueryService, QuerySetup } from './query';
-import { FilterService, FilterSetup, FilterStart } from './filter';
import { TimefilterService, TimefilterSetup } from './timefilter';
import { IndexPatternsService, IndexPatternsSetup, IndexPatternsStart } from './index_patterns';
-import {
- LegacyDependenciesPluginSetup,
- LegacyDependenciesPluginStart,
-} from './shim/legacy_dependencies_plugin';
+import { Storage, IStorageWrapper } from '../../../../../src/plugins/kibana_utils/public';
import { DataPublicPluginStart } from '../../../../plugins/data/public';
import { initLegacyModule } from './shim/legacy_module';
import { IUiActionsSetup } from '../../../../plugins/ui_actions/public';
@@ -36,19 +32,9 @@ import {
} from './filter/action/apply_filter_action';
import { APPLY_FILTER_TRIGGER } from '../../../../plugins/embeddable/public';
-/**
- * Interface for any dependencies on other plugins' `setup` contracts.
- *
- * @internal
- */
-export interface DataPluginSetupDependencies {
- __LEGACY: LegacyDependenciesPluginSetup;
-}
-
export interface DataPluginStartDependencies {
data: DataPublicPluginStart;
uiActions: IUiActionsSetup;
- __LEGACY: LegacyDependenciesPluginStart;
}
/**
@@ -60,7 +46,6 @@ export interface DataSetup {
query: QuerySetup;
timefilter: TimefilterSetup;
indexPatterns: IndexPatternsSetup;
- filter: FilterSetup;
}
/**
@@ -72,7 +57,6 @@ export interface DataStart {
query: QuerySetup;
timefilter: TimefilterSetup;
indexPatterns: IndexPatternsStart;
- filter: FilterStart;
search: SearchStart;
ui: {
SearchBar: React.ComponentType;
@@ -90,42 +74,35 @@ export interface DataStart {
* in the setup/start interfaces. The remaining items exported here are either types,
* or static code.
*/
-export class DataPlugin
- implements
- Plugin {
- // Exposed services, sorted alphabetically
- private readonly filter: FilterService = new FilterService();
+
+export class DataPlugin implements Plugin {
private readonly indexPatterns: IndexPatternsService = new IndexPatternsService();
private readonly query: QueryService = new QueryService();
private readonly search: SearchService = new SearchService();
private readonly timefilter: TimefilterService = new TimefilterService();
private setupApi!: DataSetup;
+ private storage!: IStorageWrapper;
- public setup(core: CoreSetup, { __LEGACY }: DataPluginSetupDependencies): DataSetup {
+ public setup(core: CoreSetup): DataSetup {
const { uiSettings } = core;
+ this.storage = new Storage(window.localStorage);
+
const timefilterService = this.timefilter.setup({
uiSettings,
- store: __LEGACY.storage,
- });
- const filterService = this.filter.setup({
- uiSettings,
+ storage: this.storage,
});
this.setupApi = {
indexPatterns: this.indexPatterns.setup(),
query: this.query.setup(),
timefilter: timefilterService,
- filter: filterService,
};
return this.setupApi;
}
- public start(
- core: CoreStart,
- { __LEGACY, data, uiActions }: DataPluginStartDependencies
- ): DataStart {
+ public start(core: CoreStart, { data, uiActions }: DataPluginStartDependencies): DataStart {
const { uiSettings, http, notifications, savedObjects } = core;
const indexPatternsService = this.indexPatterns.start({
@@ -140,14 +117,14 @@ export class DataPlugin
const SearchBar = createSearchBar({
core,
data,
- store: __LEGACY.storage,
+ storage: this.storage,
timefilter: this.setupApi.timefilter,
- filterManager: this.setupApi.filter.filterManager,
});
uiActions.registerAction(
createFilterAction(
- this.setupApi.filter.filterManager,
+ core.overlays,
+ data.query.filterManager,
this.setupApi.timefilter.timefilter,
indexPatternsService
)
@@ -167,7 +144,6 @@ export class DataPlugin
public stop() {
this.indexPatterns.stop();
- this.filter.stop();
this.query.stop();
this.search.stop();
this.timefilter.stop();
diff --git a/src/legacy/core_plugins/data/public/query/persisted_log/persisted_log.ts b/src/legacy/core_plugins/data/public/query/persisted_log/persisted_log.ts
index e0e6a0d0c44e4..553b0bf5ef7e0 100644
--- a/src/legacy/core_plugins/data/public/query/persisted_log/persisted_log.ts
+++ b/src/legacy/core_plugins/data/public/query/persisted_log/persisted_log.ts
@@ -20,7 +20,7 @@
import _ from 'lodash';
import * as Rx from 'rxjs';
import { map } from 'rxjs/operators';
-import { Storage } from '../../types';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
const defaultIsDuplicate = (oldItem: any, newItem: any) => {
return _.isEqual(oldItem, newItem);
@@ -37,12 +37,12 @@ export class PersistedLog {
public maxLength?: number;
public filterDuplicates?: boolean;
public isDuplicate: (oldItem: T, newItem: T) => boolean;
- public storage: Storage;
+ public storage: IStorageWrapper;
public items: T[];
private update$ = new Rx.BehaviorSubject(undefined);
- constructor(name: string, options: PersistedLogOptions = {}, storage: Storage) {
+ constructor(name: string, options: PersistedLogOptions = {}, storage: IStorageWrapper) {
this.name = name;
this.maxLength =
typeof options.maxLength === 'string'
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap
index 286e60cca9712..5dc8702411783 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap
+++ b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap
@@ -304,12 +304,12 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto
"update": [MockFunction],
},
},
- "store": Object {
+ "storage": Object {
"clear": [MockFunction],
"get": [MockFunction],
"remove": [MockFunction],
"set": [MockFunction],
- "store": Object {
+ "storage": Object {
"clear": [MockFunction],
"getItem": [MockFunction],
"key": [MockFunction],
@@ -349,7 +349,7 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto
}
}
>
-
-
-
-
+
+
@@ -1418,12 +1418,12 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1
"update": [MockFunction],
},
},
- "store": Object {
+ "storage": Object {
"clear": [MockFunction],
"get": [MockFunction],
"remove": [MockFunction],
"set": [MockFunction],
- "store": Object {
+ "storage": Object {
"clear": [MockFunction],
"getItem": [MockFunction],
"key": [MockFunction],
@@ -1463,7 +1463,7 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1
}
}
>
-
-
-
-
+
+
@@ -2529,12 +2529,12 @@ exports[`QueryBarInput Should render the given query 1`] = `
"update": [MockFunction],
},
},
- "store": Object {
+ "storage": Object {
"clear": [MockFunction],
"get": [MockFunction],
"remove": [MockFunction],
"set": [MockFunction],
- "store": Object {
+ "storage": Object {
"clear": [MockFunction],
"getItem": [MockFunction],
"key": [MockFunction],
@@ -2574,7 +2574,7 @@ exports[`QueryBarInput Should render the given query 1`] = `
}
}
>
-
-
-
-
+
+
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.tsx
index f1249da997dfe..3edb689ca2bfe 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.tsx
+++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.test.tsx
@@ -58,7 +58,7 @@ const createMockWebStorage = () => ({
});
const createMockStorage = () => ({
- store: createMockWebStorage(),
+ storage: createMockWebStorage(),
get: jest.fn(),
set: jest.fn(),
remove: jest.fn(),
@@ -80,7 +80,7 @@ const mockIndexPattern = {
],
} as IndexPattern;
-function wrapQueryBarInputInContext(testProps: any, store?: any) {
+function wrapQueryBarInputInContext(testProps: any, storage?: any) {
const defaultOptions = {
screenTitle: 'Another Screen',
intl: null as any,
@@ -89,7 +89,7 @@ function wrapQueryBarInputInContext(testProps: any, store?: any) {
const services = {
...startMock,
appName: testProps.appName || 'test',
- store: store || createMockStorage(),
+ storage: storage || createMockStorage(),
};
return (
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx
index a57018b118185..9f03f7fd30778 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx
+++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx
@@ -21,11 +21,19 @@ import { Component } from 'react';
import React from 'react';
import { i18n } from '@kbn/i18n';
-import { EuiFieldText, EuiOutsideClickDetector, PopoverAnchorPosition } from '@elastic/eui';
-
-import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
+import {
+ EuiFieldText,
+ EuiOutsideClickDetector,
+ PopoverAnchorPosition,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiButton,
+ EuiLink,
+} from '@elastic/eui';
+
+import { InjectedIntl, injectI18n, FormattedMessage } from '@kbn/i18n/react';
import { debounce, compact, isEqual } from 'lodash';
-
+import { Toast } from 'src/core/public';
import {
AutocompleteSuggestion,
AutocompleteSuggestionType,
@@ -302,20 +310,13 @@ export class QueryBarInputUI extends Component {
}
};
- private selectSuggestion = ({
- type,
- text,
- start,
- end,
- }: {
- type: AutocompleteSuggestionType;
- text: string;
- start: number;
- end: number;
- }) => {
+ private selectSuggestion = (suggestion: AutocompleteSuggestion) => {
if (!this.inputRef) {
return;
}
+ const { type, text, start, end, cursorIndex } = suggestion;
+
+ this.handleNestedFieldSyntaxNotification(suggestion);
const query = this.getQueryString();
const { selectionStart, selectionEnd } = this.inputRef;
@@ -328,12 +329,75 @@ export class QueryBarInputUI extends Component {
this.onQueryStringChange(newQueryString);
+ this.setState({
+ selectionStart: start + (cursorIndex ? cursorIndex : text.length),
+ selectionEnd: start + (cursorIndex ? cursorIndex : text.length),
+ });
+
if (type === recentSearchType) {
this.setState({ isSuggestionsVisible: false, index: null });
this.onSubmit({ query: newQueryString, language: this.props.query.language });
}
};
+ private handleNestedFieldSyntaxNotification = (suggestion: AutocompleteSuggestion) => {
+ if (
+ 'field' in suggestion &&
+ suggestion.field.subType &&
+ suggestion.field.subType.nested &&
+ !this.services.storage.get('kibana.KQLNestedQuerySyntaxInfoOptOut')
+ ) {
+ const { notifications, docLinks } = this.services;
+
+ const onKQLNestedQuerySyntaxInfoOptOut = (toast: Toast) => {
+ if (!this.services.storage) return;
+ this.services.storage.set('kibana.KQLNestedQuerySyntaxInfoOptOut', true);
+ notifications!.toasts.remove(toast);
+ };
+
+ if (notifications && docLinks) {
+ const toast = notifications.toasts.add({
+ title: this.props.intl.formatMessage({
+ id: 'data.query.queryBar.KQLNestedQuerySyntaxInfoTitle',
+ defaultMessage: 'KQL nested query syntax',
+ }),
+ text: (
+
+
+
+
+
+ ),
+ }}
+ />
+
+
+
+ onKQLNestedQuerySyntaxInfoOptOut(toast)}>
+
+
+
+
+
+ ),
+ });
+ }
+ }
+ };
+
private increaseLimit = () => {
this.setState({
suggestionLimit: this.state.suggestionLimit + 50,
@@ -365,7 +429,7 @@ export class QueryBarInputUI extends Component {
body: JSON.stringify({ opt_in: language === 'kuery' }),
});
- this.services.store.set('kibana.userQueryLanguage', language);
+ this.services.storage.set('kibana.userQueryLanguage', language);
const newQuery = { query: '', language };
this.onChange(newQuery);
@@ -387,10 +451,10 @@ export class QueryBarInputUI extends Component {
};
private initPersistedLog = () => {
- const { uiSettings, store, appName } = this.services;
+ const { uiSettings, storage, appName } = this.services;
this.persistedLog = this.props.persistedLog
? this.props.persistedLog
- : getQueryLog(uiSettings, store, appName, this.props.query.language);
+ : getQueryLog(uiSettings, storage, appName, this.props.query.language);
};
public onMouseEnterSuggestion = (index: number) => {
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.test.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.test.tsx
index 7ab191062e32d..7281eea956fbf 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.test.tsx
+++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.test.tsx
@@ -79,7 +79,7 @@ const createMockWebStorage = () => ({
});
const createMockStorage = () => ({
- store: createMockWebStorage(),
+ storage: createMockWebStorage(),
get: jest.fn(),
set: jest.fn(),
remove: jest.fn(),
@@ -112,7 +112,7 @@ function wrapQueryBarTopRowInContext(testProps: any) {
const services = {
...startMock,
appName: 'discover',
- store: createMockStorage(),
+ storage: createMockStorage(),
};
return (
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx
index 9a846ab82f47c..d2953621d86d1 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx
+++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx
@@ -21,7 +21,7 @@ import dateMath from '@elastic/datemath';
import { doesKueryExpressionHaveLuceneSyntaxError } from '@kbn/es-query';
import classNames from 'classnames';
-import React, { useState, useEffect } from 'react';
+import React, { useState } from 'react';
import {
EuiButton,
@@ -73,17 +73,15 @@ function QueryBarTopRowUI(props: Props) {
const [isDateRangeInvalid, setIsDateRangeInvalid] = useState(false);
const kibana = useKibana();
- const { uiSettings, notifications, store, appName, docLinks } = kibana.services;
+ const { uiSettings, notifications, storage, appName, docLinks } = kibana.services;
const kueryQuerySyntaxLink: string = docLinks!.links.query.kueryQuerySyntax;
const queryLanguage = props.query && props.query.language;
- let persistedLog: PersistedLog | undefined;
-
- useEffect(() => {
- if (!props.query) return;
- persistedLog = getQueryLog(uiSettings!, store, appName, props.query.language);
- }, [queryLanguage]);
+ const persistedLog: PersistedLog | undefined = React.useMemo(
+ () => (queryLanguage ? getQueryLog(uiSettings!, storage, appName, queryLanguage) : undefined),
+ [queryLanguage]
+ );
function onClickSubmitButton(event: React.MouseEvent) {
if (persistedLog && props.query) {
@@ -211,7 +209,7 @@ function QueryBarTopRowUI(props: Props) {
}
function shouldRenderQueryInput(): boolean {
- return Boolean(props.showQueryInput && props.indexPatterns && props.query && store);
+ return Boolean(props.showQueryInput && props.indexPatterns && props.query && storage);
}
function renderUpdateButton() {
@@ -293,7 +291,7 @@ function QueryBarTopRowUI(props: Props) {
if (
language === 'kuery' &&
typeof query === 'string' &&
- (!store || !store.get('kibana.luceneSyntaxWarningOptOut')) &&
+ (!storage || !storage.get('kibana.luceneSyntaxWarningOptOut')) &&
doesKueryExpressionHaveLuceneSyntaxError(query)
) {
const toast = notifications!.toasts.addWarning({
@@ -337,8 +335,8 @@ function QueryBarTopRowUI(props: Props) {
}
function onLuceneSyntaxWarningOptOut(toast: Toast) {
- if (!store) return;
- store.set('kibana.luceneSyntaxWarningOptOut', true);
+ if (!storage) return;
+ storage.set('kibana.luceneSyntaxWarningOptOut', true);
notifications!.toasts.remove(toast);
}
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts b/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts
index 8b26e14c6ed7b..f78eb5e07f189 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts
+++ b/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts
@@ -18,12 +18,12 @@
*/
import { UiSettingsClientContract } from 'src/core/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { PersistedLog } from '../../persisted_log';
-import { Storage } from '../../../types';
export function getQueryLog(
uiSettings: UiSettingsClientContract,
- store: Storage,
+ storage: IStorageWrapper,
appName: string,
language: string
) {
@@ -33,6 +33,6 @@ export function getQueryLog(
maxLength: uiSettings.get('history:limit'),
filterDuplicates: true,
},
- store
+ storage
);
}
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx
index d801f8a69e2d6..12cea46f158c1 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx
@@ -19,30 +19,29 @@
import React, { useState, useEffect } from 'react';
import { Subscription } from 'rxjs';
-import { Filter } from '@kbn/es-query';
import { CoreStart } from 'src/core/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
-import { Storage } from '../../../types';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public';
import { TimefilterSetup } from '../../../timefilter';
-import { FilterManager, SearchBar } from '../../../';
+import { SearchBar } from '../../../';
import { SearchBarOwnProps } from '.';
+import { esFilters } from '../../../../../../../plugins/data/public';
interface StatefulSearchBarDeps {
core: CoreStart;
data: DataPublicPluginStart;
- store: Storage;
+ storage: IStorageWrapper;
timefilter: TimefilterSetup;
- filterManager: FilterManager;
}
export type StatetfulSearchBarProps = SearchBarOwnProps & {
appName: string;
};
-const defaultFiltersUpdated = (filterManager: FilterManager) => {
- return (filters: Filter[]) => {
- filterManager.setFilters(filters);
+const defaultFiltersUpdated = (data: DataPublicPluginStart) => {
+ return (filters: esFilters.Filter[]) => {
+ data.query.filterManager.setFilters(filters);
};
};
@@ -55,16 +54,11 @@ const defaultOnRefreshChange = (timefilter: TimefilterSetup) => {
};
};
-export function createSearchBar({
- core,
- store,
- timefilter,
- filterManager,
- data,
-}: StatefulSearchBarDeps) {
+export function createSearchBar({ core, storage, timefilter, data }: StatefulSearchBarDeps) {
// App name should come from the core application service.
// Until it's available, we'll ask the user to provide it for the pre-wired component.
return (props: StatetfulSearchBarProps) => {
+ const { filterManager } = data.query;
const tfRefreshInterval = timefilter.timefilter.getRefreshInterval();
const fmFilters = filterManager.getFilters();
const [refreshInterval, setRefreshInterval] = useState(tfRefreshInterval.value);
@@ -113,7 +107,7 @@ export function createSearchBar({
services={{
appName: props.appName,
data,
- store,
+ storage,
...core,
}}
>
@@ -124,7 +118,7 @@ export function createSearchBar({
refreshInterval={refreshInterval}
isRefreshPaused={refreshPaused}
filters={filters}
- onFiltersUpdated={defaultFiltersUpdated(filterManager)}
+ onFiltersUpdated={defaultFiltersUpdated(data)}
onRefreshChange={defaultOnRefreshChange(timefilter)}
{...props}
/>
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/save_query_form.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/save_query_form.tsx
index 6fd5274d09ec6..7a9786f5f9ce8 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/save_query_form.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/save_query_form.tsx
@@ -83,7 +83,7 @@ export const SaveQueryForm: FunctionComponent = ({
setSavedQueries(sortedAllSavedQueries);
};
fetchQueries();
- }, []);
+ }, [savedQueryService]);
const savedQueryDescriptionText = i18n.translate(
'data.search.searchBar.savedQueryDescriptionText',
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/saved_query_management_component.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/saved_query_management_component.tsx
index b2e47e8b4e850..b73b8edb39e54 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/saved_query_management_component.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/saved_query_management_component.tsx
@@ -29,6 +29,7 @@ import {
EuiPagination,
EuiText,
EuiSpacer,
+ EuiIcon,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
@@ -75,7 +76,7 @@ export const SavedQueryManagementComponent: FunctionComponent = ({
if (isOpen) {
fetchCountAndSavedQueries();
}
- }, [isOpen, activePage]);
+ }, [isOpen, activePage, savedQueryService]);
const goToPage = (pageNumber: number) => {
setActivePage(pageNumber);
@@ -116,8 +117,6 @@ export const SavedQueryManagementComponent: FunctionComponent = ({
const savedQueryPopoverButton = (
{
setIsOpen(!isOpen);
}}
@@ -129,7 +128,8 @@ export const SavedQueryManagementComponent: FunctionComponent = ({
})}
data-test-subj="saved-query-management-popover-button"
>
- #
+
+
);
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx
index 73e81a38572c3..9b77ec369c55b 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx
@@ -33,14 +33,14 @@ const timefilterSetupMock = timefilterServiceMock.createSetupContract();
jest.mock('../../../../../data/public', () => {
return {
- FilterBar: () =>
,
- QueryBarInput: () =>
,
+ FilterBar: () =>
,
+ QueryBarInput: () =>
,
};
});
jest.mock('../../../query/query_bar', () => {
return {
- QueryBarTopRow: () =>
,
+ QueryBarTopRow: () =>
,
};
});
@@ -56,7 +56,7 @@ const createMockWebStorage = () => ({
});
const createMockStorage = () => ({
- store: createMockWebStorage(),
+ storage: createMockWebStorage(),
get: jest.fn(),
set: jest.fn(),
remove: jest.fn(),
@@ -95,7 +95,7 @@ function wrapSearchBarInContext(testProps: any) {
savedObjects: startMock.savedObjects,
notifications: startMock.notifications,
http: startMock.http,
- store: createMockStorage(),
+ storage: createMockStorage(),
};
return (
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx
index a03019da4e0d7..d3a26239e1006 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx
@@ -18,7 +18,6 @@
*/
import { compact } from 'lodash';
-import { Filter } from '@kbn/es-query';
import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
import classNames from 'classnames';
import React, { Component } from 'react';
@@ -39,14 +38,15 @@ import {
KibanaReactContextValue,
} from '../../../../../../../plugins/kibana_react/public';
import { IDataPluginServices } from '../../../types';
+import { esFilters } from '../../../../../../../plugins/data/public';
interface SearchBarInjectedDeps {
kibana: KibanaReactContextValue;
intl: InjectedIntl;
timeHistory: TimeHistoryContract;
// Filter bar
- onFiltersUpdated?: (filters: Filter[]) => void;
- filters?: Filter[];
+ onFiltersUpdated?: (filters: esFilters.Filter[]) => void;
+ filters?: esFilters.Filter[];
// Date picker
dateRangeFrom?: string;
dateRangeTo?: string;
@@ -368,7 +368,7 @@ class SearchBarUI extends Component {
onLoad={this.onLoadSavedQuery}
savedQueryService={this.savedQueryService}
onClearSavedQuery={this.props.onClearSavedQuery}
- >
+ />
);
let queryBar;
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/index.tsx b/src/legacy/core_plugins/data/public/search/search_bar/index.tsx
index 0c677bea98536..ebde9d60b0b51 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/index.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/index.tsx
@@ -17,9 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { RefreshInterval, TimeRange } from 'src/plugins/data/public';
import { Query } from '../../query/query_bar';
+import { esFilters } from '../../../../../../plugins/data/public';
export * from './components';
@@ -36,6 +36,6 @@ export interface SavedQueryAttributes {
title: string;
description: string;
query: Query;
- filters?: Filter[];
+ filters?: esFilters.Filter[];
timefilter?: SavedQueryTimeFilter;
}
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/lib/saved_query_service.test.ts b/src/legacy/core_plugins/data/public/search/search_bar/lib/saved_query_service.test.ts
index ac5fdb7fe99d5..415da8a2c32cc 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/lib/saved_query_service.test.ts
+++ b/src/legacy/core_plugins/data/public/search/search_bar/lib/saved_query_service.test.ts
@@ -19,7 +19,7 @@
import { SavedQueryAttributes } from '../index';
import { createSavedQueryService } from './saved_query_service';
-import { FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../plugins/data/public';
const savedQueryAttributes: SavedQueryAttributes = {
title: 'foo',
@@ -43,7 +43,7 @@ const savedQueryAttributesWithFilters: SavedQueryAttributes = {
filters: [
{
query: { match_all: {} },
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: {
disabled: false,
negate: false,
diff --git a/src/legacy/core_plugins/data/public/shim/legacy_module.ts b/src/legacy/core_plugins/data/public/shim/legacy_module.ts
index 54f513d07215d..b0ed3d43a4c8c 100644
--- a/src/legacy/core_plugins/data/public/shim/legacy_module.ts
+++ b/src/legacy/core_plugins/data/public/shim/legacy_module.ts
@@ -25,9 +25,6 @@ import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
import { npStart } from 'ui/new_platform';
import { FilterBar, ApplyFiltersPopover } from '../filter';
-
-// @ts-ignore
-import { mapAndFlattenFilters } from '../filter/filter_manager/lib/map_and_flatten_filters';
import { IndexPatterns } from '../index_patterns/index_patterns';
/** @internal */
diff --git a/src/legacy/core_plugins/data/public/timefilter/index.ts b/src/legacy/core_plugins/data/public/timefilter/index.ts
index 17564801cf148..a6260e782c12f 100644
--- a/src/legacy/core_plugins/data/public/timefilter/index.ts
+++ b/src/legacy/core_plugins/data/public/timefilter/index.ts
@@ -23,3 +23,5 @@ export * from './types';
export { Timefilter, TimefilterContract } from './timefilter';
export { TimeHistory, TimeHistoryContract } from './time_history';
export { getTime } from './get_time';
+export { changeTimeFilter } from './lib/change_time_filter';
+export { extractTimeFilter } from './lib/extract_time_filter';
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/change_time_filter.test.ts b/src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.test.ts
similarity index 87%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/change_time_filter.test.ts
rename to src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.test.ts
index 2e397ff931bb6..df3e33060b01f 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/change_time_filter.test.ts
+++ b/src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.test.ts
@@ -16,10 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { RangeFilter } from '@kbn/es-query';
import { changeTimeFilter } from './change_time_filter';
import { TimeRange } from 'src/plugins/data/public';
-import { timefilterServiceMock } from '../../../timefilter/timefilter_service.mock';
+import { timefilterServiceMock } from '../timefilter_service.mock';
+import { esFilters } from '../../../../../../plugins/data/public';
const timefilterMock = timefilterServiceMock.createSetupContract();
const timefilter = timefilterMock.timefilter;
@@ -42,7 +42,7 @@ describe('changeTimeFilter()', () => {
test('should change the timefilter to match the range gt/lt', () => {
const filter: any = { range: { '@timestamp': { gt, lt } } };
- changeTimeFilter(timefilter, filter as RangeFilter);
+ changeTimeFilter(timefilter, filter as esFilters.RangeFilter);
const { to, from } = timefilter.getTime();
@@ -52,7 +52,7 @@ describe('changeTimeFilter()', () => {
test('should change the timefilter to match the range gte/lte', () => {
const filter: any = { range: { '@timestamp': { gte: gt, lte: lt } } };
- changeTimeFilter(timefilter, filter as RangeFilter);
+ changeTimeFilter(timefilter, filter as esFilters.RangeFilter);
const { to, from } = timefilter.getTime();
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/change_time_filter.ts b/src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.ts
similarity index 83%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/change_time_filter.ts
rename to src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.ts
index 8cd1ce5ba6c84..7943aab3c151f 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/change_time_filter.ts
+++ b/src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.ts
@@ -19,10 +19,10 @@
import moment from 'moment';
import { keys } from 'lodash';
-import { RangeFilter } from '@kbn/es-query';
-import { TimefilterContract } from '../../../timefilter';
+import { TimefilterContract } from '../timefilter';
+import { esFilters } from '../../../../../../plugins/data/public';
-export function convertRangeFilterToTimeRange(filter: RangeFilter) {
+export function convertRangeFilterToTimeRange(filter: esFilters.RangeFilter) {
const key = keys(filter.range)[0];
const values = filter.range[key];
@@ -32,6 +32,6 @@ export function convertRangeFilterToTimeRange(filter: RangeFilter) {
};
}
-export function changeTimeFilter(timeFilter: TimefilterContract, filter: RangeFilter) {
+export function changeTimeFilter(timeFilter: TimefilterContract, filter: esFilters.RangeFilter) {
timeFilter.setTime(convertRangeFilterToTimeRange(filter));
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/extract_time_filter.test.ts b/src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.test.ts
similarity index 63%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/extract_time_filter.test.ts
rename to src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.test.ts
index d55c9babeed79..981c50844c4f3 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/extract_time_filter.test.ts
+++ b/src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.test.ts
@@ -17,15 +17,23 @@
* under the License.
*/
-import { Filter, buildRangeFilter, buildQueryFilter, buildPhraseFilter } from '@kbn/es-query';
import { extractTimeFilter } from './extract_time_filter';
+import { esFilters } from '../../../../../../plugins/data/public';
describe('filter manager utilities', () => {
describe('extractTimeFilter()', () => {
test('should detect timeFilter', async () => {
- const filters: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'logstash-*'),
- buildRangeFilter({ name: 'time' }, { gt: 1388559600000, lt: 1388646000000 }, 'logstash-*'),
+ const filters: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'logstash-*',
+ ''
+ ),
+ esFilters.buildRangeFilter(
+ { name: 'time' },
+ { gt: 1388559600000, lt: 1388646000000 },
+ 'logstash-*'
+ ),
];
const result = await extractTimeFilter('time', filters);
@@ -34,9 +42,13 @@ describe('filter manager utilities', () => {
});
test("should not return timeFilter when name doesn't match", async () => {
- const filters: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'logstash-*'),
- buildRangeFilter({ name: '@timestamp' }, { from: 1, to: 2 }, 'logstash-*'),
+ const filters: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'logstash-*',
+ ''
+ ),
+ esFilters.buildRangeFilter({ name: '@timestamp' }, { from: 1, to: 2 }, 'logstash-*', ''),
];
const result = await extractTimeFilter('time', filters);
@@ -45,9 +57,13 @@ describe('filter manager utilities', () => {
});
test('should not return a non range filter, even when names match', async () => {
- const filters: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'logstash-*'),
- buildPhraseFilter({ name: 'time' }, 'banana', 'logstash-*'),
+ const filters: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'logstash-*',
+ ''
+ ),
+ esFilters.buildPhraseFilter({ name: 'time' }, 'banana', 'logstash-*'),
];
const result = await extractTimeFilter('time', filters);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/extract_time_filter.ts b/src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.ts
similarity index 82%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/extract_time_filter.ts
rename to src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.ts
index 22bda5b21295e..4281610cb63e4 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/extract_time_filter.ts
+++ b/src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.ts
@@ -18,13 +18,13 @@
*/
import { keys, partition } from 'lodash';
-import { Filter, isRangeFilter, RangeFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
-export function extractTimeFilter(timeFieldName: string, filters: Filter[]) {
- const [timeRangeFilter, restOfFilters] = partition(filters, (obj: Filter) => {
+export function extractTimeFilter(timeFieldName: string, filters: esFilters.Filter[]) {
+ const [timeRangeFilter, restOfFilters] = partition(filters, (obj: esFilters.Filter) => {
let key;
- if (isRangeFilter(obj)) {
+ if (esFilters.isRangeFilter(obj)) {
key = keys(obj.range)[0];
}
@@ -33,6 +33,6 @@ export function extractTimeFilter(timeFieldName: string, filters: Filter[]) {
return {
restOfFilters,
- timeRangeFilter: timeRangeFilter[0] as RangeFilter | undefined,
+ timeRangeFilter: timeRangeFilter[0] as esFilters.RangeFilter | undefined,
};
}
diff --git a/src/legacy/core_plugins/data/public/timefilter/time_history.ts b/src/legacy/core_plugins/data/public/timefilter/time_history.ts
index 22778d1adea3c..36ad1a4427a47 100644
--- a/src/legacy/core_plugins/data/public/timefilter/time_history.ts
+++ b/src/legacy/core_plugins/data/public/timefilter/time_history.ts
@@ -19,13 +19,13 @@
import moment from 'moment';
import { TimeRange } from 'src/plugins/data/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { PersistedLog } from '../query/persisted_log';
-import { Storage } from '../types';
export class TimeHistory {
private history: PersistedLog;
- constructor(store: Storage) {
+ constructor(storage: IStorageWrapper) {
const historyOptions = {
maxLength: 10,
filterDuplicates: true,
@@ -33,7 +33,7 @@ export class TimeHistory {
return oldItem.from === newItem.from && oldItem.to === newItem.to;
},
};
- this.history = new PersistedLog('kibana.timepicker.timeHistory', historyOptions, store);
+ this.history = new PersistedLog('kibana.timepicker.timeHistory', historyOptions, storage);
}
add(time: TimeRange) {
diff --git a/src/legacy/core_plugins/data/public/timefilter/timefilter_service.ts b/src/legacy/core_plugins/data/public/timefilter/timefilter_service.ts
index cda9b93ef08aa..831ccebedc9cc 100644
--- a/src/legacy/core_plugins/data/public/timefilter/timefilter_service.ts
+++ b/src/legacy/core_plugins/data/public/timefilter/timefilter_service.ts
@@ -18,8 +18,8 @@
*/
import { UiSettingsClientContract } from 'src/core/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { TimeHistory, Timefilter, TimeHistoryContract, TimefilterContract } from './index';
-import { Storage } from '../types';
/**
* Filter Service
@@ -28,16 +28,16 @@ import { Storage } from '../types';
export interface TimeFilterServiceDependencies {
uiSettings: UiSettingsClientContract;
- store: Storage;
+ storage: IStorageWrapper;
}
export class TimefilterService {
- public setup({ uiSettings, store }: TimeFilterServiceDependencies): TimefilterSetup {
+ public setup({ uiSettings, storage }: TimeFilterServiceDependencies): TimefilterSetup {
const timefilterConfig = {
timeDefaults: uiSettings.get('timepicker:timeDefaults'),
refreshIntervalDefaults: uiSettings.get('timepicker:refreshIntervalDefaults'),
};
- const history = new TimeHistory(store);
+ const history = new TimeHistory(storage);
const timefilter = new Timefilter(timefilterConfig, history);
return {
diff --git a/src/legacy/core_plugins/data/public/types.ts b/src/legacy/core_plugins/data/public/types.ts
index 2c02a9b764755..b6c9c47cc0ae6 100644
--- a/src/legacy/core_plugins/data/public/types.ts
+++ b/src/legacy/core_plugins/data/public/types.ts
@@ -19,13 +19,7 @@
import { UiSettingsClientContract, CoreStart } from 'src/core/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
-
-export interface Storage {
- get: (key: string) => any;
- set: (key: string, value: any) => void;
- remove: (key: string) => any;
- clear: () => void;
-}
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
export interface IDataPluginServices extends Partial {
appName: string;
@@ -33,6 +27,6 @@ export interface IDataPluginServices extends Partial {
savedObjects: CoreStart['savedObjects'];
notifications: CoreStart['notifications'];
http: CoreStart['http'];
- store: Storage;
+ storage: IStorageWrapper;
data: DataPublicPluginStart;
}
diff --git a/src/legacy/core_plugins/elasticsearch/index.js b/src/legacy/core_plugins/elasticsearch/index.js
index ed6e2d7f7f1c8..f92f920d1afb7 100644
--- a/src/legacy/core_plugins/elasticsearch/index.js
+++ b/src/legacy/core_plugins/elasticsearch/index.js
@@ -98,10 +98,14 @@ export default function (kibana) {
createProxy(server);
// Set up the health check service and start it.
- const { start, waitUntilReady } = healthCheck(this, server, esConfig.healthCheckDelay.asMilliseconds());
+ const { start, waitUntilReady } = healthCheck(
+ this,
+ server,
+ esConfig.healthCheckDelay.asMilliseconds(),
+ esConfig.ignoreVersionMismatch
+ );
server.expose('waitUntilReady', waitUntilReady);
start();
- }
+ },
});
-
}
diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js b/src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js
index baf728262aad1..a31c7830f8d5c 100644
--- a/src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js
+++ b/src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js
@@ -105,6 +105,51 @@ describe('plugins/elasticsearch', () => {
}
});
+ it('does not throw on outdated nodes, if `ignoreVersionMismatch` is enabled in development mode', async () => {
+ // set config values
+ server.config = () => ({
+ get: name => {
+ switch (name) {
+ case 'env.dev':
+ return true;
+ default:
+ throw new Error(`Unknown option "${name}"`);
+ }
+ },
+ });
+
+ // 5.0.0 ES is too old to work with a 5.1.0 version of Kibana.
+ setNodes('5.1.0', '5.2.0', '5.0.0');
+
+ const ignoreVersionMismatch = true;
+ const result = await ensureEsVersion(server, KIBANA_VERSION, ignoreVersionMismatch);
+ expect(result).to.be(true);
+ });
+
+ it('throws an error if `ignoreVersionMismatch` is enabled in production mode', async () => {
+ // set config values
+ server.config = () => ({
+ get: name => {
+ switch (name) {
+ case 'env.dev':
+ return false;
+ default:
+ throw new Error(`Unknown option "${name}"`);
+ }
+ },
+ });
+
+ // 5.0.0 ES is too old to work with a 5.1.0 version of Kibana.
+ setNodes('5.1.0', '5.2.0', '5.0.0');
+
+ try {
+ const ignoreVersionMismatch = true;
+ await ensureEsVersion(server, KIBANA_VERSION, ignoreVersionMismatch);
+ } catch (e) {
+ expect(e).to.be.a(Error);
+ }
+ });
+
it('fails if that single node is a client node', async () => {
setNodes(
'5.1.0',
diff --git a/src/legacy/core_plugins/elasticsearch/lib/ensure_es_version.js b/src/legacy/core_plugins/elasticsearch/lib/ensure_es_version.js
index 95c7db36d5fb4..cb3ed1886b4a1 100644
--- a/src/legacy/core_plugins/elasticsearch/lib/ensure_es_version.js
+++ b/src/legacy/core_plugins/elasticsearch/lib/ensure_es_version.js
@@ -36,7 +36,7 @@ import isEsCompatibleWithKibana from './is_es_compatible_with_kibana';
*/
const lastWarnedNodesForServer = new WeakMap();
-export function ensureEsVersion(server, kibanaVersion) {
+export function ensureEsVersion(server, kibanaVersion, ignoreVersionMismatch = false) {
const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin');
server.logWithMetadata(['plugin', 'debug'], 'Checking Elasticsearch version');
@@ -102,7 +102,7 @@ export function ensureEsVersion(server, kibanaVersion) {
}
}
- if (incompatibleNodes.length) {
+ if (incompatibleNodes.length && !shouldIgnoreVersionMismatch(server, ignoreVersionMismatch)) {
const incompatibleNodeNames = getHumanizedNodeNames(incompatibleNodes);
throw new Error(
`This version of Kibana requires Elasticsearch v` +
@@ -114,3 +114,12 @@ export function ensureEsVersion(server, kibanaVersion) {
return true;
});
}
+
+function shouldIgnoreVersionMismatch(server, ignoreVersionMismatch) {
+ const isDevMode = server.config().get('env.dev');
+ if(!isDevMode && ignoreVersionMismatch) {
+ throw new Error(`Option "elasticsearch.ignoreVersionMismatch" can only be used in development mode`);
+ }
+
+ return isDevMode && ignoreVersionMismatch;
+}
diff --git a/src/legacy/core_plugins/elasticsearch/lib/health_check.js b/src/legacy/core_plugins/elasticsearch/lib/health_check.js
index 1b05d51b02494..ac8e6caab9496 100644
--- a/src/legacy/core_plugins/elasticsearch/lib/health_check.js
+++ b/src/legacy/core_plugins/elasticsearch/lib/health_check.js
@@ -21,7 +21,7 @@ import Bluebird from 'bluebird';
import kibanaVersion from './kibana_version';
import { ensureEsVersion } from './ensure_es_version';
-export default function (plugin, server, requestDelay) {
+export default function (plugin, server, requestDelay, ignoreVersionMismatch) {
plugin.status.yellow('Waiting for Elasticsearch');
function waitUntilReady() {
@@ -31,7 +31,7 @@ export default function (plugin, server, requestDelay) {
}
function check() {
- return ensureEsVersion(server, kibanaVersion.get())
+ return ensureEsVersion(server, kibanaVersion.get(), ignoreVersionMismatch)
.then(() => plugin.status.green('Ready'))
.catch(err => plugin.status.red(err));
}
diff --git a/src/legacy/core_plugins/embeddable_api/public/index.scss b/src/legacy/core_plugins/embeddable_api/public/index.scss
index b4e170e6cb65c..3f1977b909c31 100644
--- a/src/legacy/core_plugins/embeddable_api/public/index.scss
+++ b/src/legacy/core_plugins/embeddable_api/public/index.scss
@@ -1,5 +1,3 @@
@import 'src/legacy/ui/public/styles/styling_constants';
-@import './variables';
-@import '../../../../plugins/embeddable/public/lib/panel/index';
-@import '../../../../plugins/embeddable/public/lib/panel/panel_header/index';
+@import '../../../../plugins/embeddable/public/index';
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.tsx b/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.tsx
index 8359663610f29..208bdbe5d0288 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.tsx
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.tsx
@@ -21,7 +21,7 @@ import { useRef, useEffect, useState } from 'react';
import React from 'react';
import classNames from 'classnames';
import { EuiLoadingChart, EuiProgress } from '@elastic/eui';
-import { ExpressionAST, IExpressionLoaderParams, IInterpreterErrorResult } from './types';
+import { ExpressionAST, IExpressionLoaderParams } from './types';
import { ExpressionLoader } from './loader';
// Accept all options of the runner as props except for the
@@ -35,7 +35,7 @@ export interface ExpressionRendererProps extends IExpressionLoaderParams {
interface State {
isEmpty: boolean;
isLoading: boolean;
- error: null | Error;
+ error: null | { message: string };
}
export type ExpressionRenderer = React.FC;
@@ -57,6 +57,7 @@ export const ExpressionRendererImplementation = ({
const [state, setState] = useState({ ...defaultState });
// Re-fetch data automatically when the inputs change
+ /* eslint-disable react-hooks/exhaustive-deps */
useEffect(() => {
if (handlerRef.current) {
handlerRef.current.update(expression, options);
@@ -68,6 +69,7 @@ export const ExpressionRendererImplementation = ({
options.variables,
options.disableCaching,
]);
+ /* eslint-enable react-hooks/exhaustive-deps */
// Initialize the loader only once
useEffect(() => {
@@ -80,7 +82,7 @@ export const ExpressionRendererImplementation = ({
}
setState(prevState => ({ ...prevState, isLoading: true }));
});
- handlerRef.current.render$.subscribe((item: number | IInterpreterErrorResult) => {
+ handlerRef.current.render$.subscribe(item => {
if (!handlerRef.current) {
return;
}
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts
index 36917bf4e8384..a3caa1c47b150 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts
@@ -23,7 +23,7 @@ import { ExpressionDataHandler } from './execute';
import { fromExpression } from '@kbn/interpreter/common';
import { IInterpreterRenderHandlers } from './types';
import { Observable } from 'rxjs';
-import { ExpressionAST } from '../../../../../../plugins/expressions/common';
+import { ExpressionAST } from '../../../../../../plugins/expressions/public';
const element: HTMLElement = null as any;
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/mocks.tsx b/src/legacy/core_plugins/expressions/public/np_ready/public/mocks.tsx
index 1a2f473f4c9a1..b17cd454b65ea 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/mocks.tsx
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/mocks.tsx
@@ -39,6 +39,11 @@ const createExpressionsSetupMock = (): ExpressionsSetup => {
types: {
register: () => {},
} as any,
+ getExecutor: () => ({
+ interpreter: {
+ interpretAst: () => {},
+ },
+ }),
},
};
};
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/plugin.ts
index ec70248694990..d2c6c14c17de1 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/plugin.ts
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/plugin.ts
@@ -19,9 +19,10 @@
/* eslint-disable */
import { npSetup } from 'ui/new_platform';
-import { ExpressionsSetupContract } from '../../../../../../plugins/expressions/public/expressions/expressions_service';
/* eslint-enable */
+import { ExpressionsSetup } from '../../../../../../plugins/expressions/public';
+
import {
CoreSetup,
CoreStart,
@@ -32,7 +33,7 @@ import {
Start as InspectorStart,
Setup as InspectorSetup,
} from '../../../../../../plugins/inspector/public';
-import { IInterpreter } from './types';
+import { ExpressionInterpreter } from './types';
import { setInterpreter, setInspector, setRenderersRegistry } from './services';
import { ExpressionRendererImplementation } from './expression_renderer';
import { ExpressionLoader, loader } from './loader';
@@ -47,7 +48,7 @@ export interface ExpressionsStartDeps {
inspector: InspectorStart;
}
-export type ExpressionsSetup = ExpressionsSetupContract;
+export { ExpressionsSetup };
export type ExpressionsStart = ReturnType;
export class ExpressionsPublicPlugin
@@ -61,7 +62,7 @@ export class ExpressionsPublicPlugin
// eslint-disable-next-line
const { getInterpreter } = require('../../../../interpreter/public/interpreter');
getInterpreter()
- .then(({ interpreter }: { interpreter: IInterpreter }) => {
+ .then(({ interpreter }: { interpreter: ExpressionInterpreter }) => {
setInterpreter(interpreter);
})
.catch((e: Error) => {
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/render.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/render.ts
index f67b4c2d8e272..8475325a2c625 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/render.ts
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/render.ts
@@ -23,17 +23,22 @@ import { share } from 'rxjs/operators';
import { event, RenderId, Data, IInterpreterRenderHandlers } from './types';
import { getRenderersRegistry } from './services';
+interface RenderError {
+ type: 'error';
+ error: { type?: string; message: string };
+}
+
export type IExpressionRendererExtraHandlers = Record;
export class ExpressionRenderHandler {
- render$: Observable;
+ render$: Observable;
update$: Observable;
events$: Observable;
private element: HTMLElement;
private destroyFn?: any;
private renderCount: number = 0;
- private renderSubject: Rx.Subject;
+ private renderSubject: Rx.Subject;
private eventsSubject: Rx.Subject;
private updateSubject: Rx.Subject;
private handlers: IInterpreterRenderHandlers;
@@ -104,7 +109,7 @@ export class ExpressionRenderHandler {
try {
// Rendering is asynchronous, completed by handlers.done()
getRenderersRegistry()
- .get(data.as)
+ .get(data.as)!
.render(this.element, data.value, { ...this.handlers, ...extraHandlers });
} catch (e) {
this.renderSubject.next({
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/services.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/services.ts
index ae2a7955233d1..5c357b5dcd2bb 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/services.ts
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/services.ts
@@ -17,13 +17,15 @@
* under the License.
*/
+import { ExpressionInterpreter } from './types';
import { createGetterSetter } from '../../../../../../plugins/kibana_utils/public';
-import { IInterpreter } from './types';
import { Start as IInspector } from '../../../../../../plugins/inspector/public';
import { ExpressionsSetup } from './plugin';
export const [getInspector, setInspector] = createGetterSetter('Inspector');
-export const [getInterpreter, setInterpreter] = createGetterSetter('Interpreter');
+export const [getInterpreter, setInterpreter] = createGetterSetter(
+ 'Interpreter'
+);
export const [getRenderersRegistry, setRenderersRegistry] = createGetterSetter<
ExpressionsSetup['__LEGACY']['renderers']
>('Renderers registry');
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts
index 0390440298c55..9d7b4fb6d0480 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts
@@ -17,80 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { TimeRange } from '../../../../../../plugins/data/public';
import { Adapters } from '../../../../../../plugins/inspector/public';
import { Query } from '../../../../../../plugins/data/public';
-import { ExpressionAST } from '../../../../../../plugins/expressions/common';
-export { ExpressionAST, TimeRange, Adapters, Filter, Query };
-
-export type RenderId = number;
-export type Data = any;
-export type event = any;
-export type Context = object;
-
-export interface SearchContext {
- type: 'kibana_context';
- filters?: Filter[];
- query?: Query;
- timeRange?: TimeRange;
-}
-
-export type IGetInitialContext = () => SearchContext | Context;
-
-export interface IExpressionLoaderParams {
- searchContext?: SearchContext;
- context?: Context;
- variables?: Record;
- disableCaching?: boolean;
- customFunctions?: [];
- customRenderers?: [];
- extraHandlers?: Record;
-}
-
-export interface IInterpreterHandlers {
- getInitialContext: IGetInitialContext;
- inspectorAdapters?: Adapters;
- abortSignal?: AbortSignal;
-}
-
-export interface IInterpreterErrorResult {
- type: 'error';
- error: { message: string; name: string; stack: string };
-}
-
-export interface IInterpreterSuccessResult {
- type: string;
- as?: string;
- value?: unknown;
- error?: unknown;
-}
-
-export type IInterpreterResult = IInterpreterSuccessResult & IInterpreterErrorResult;
-
-export interface IInterpreterRenderHandlers {
- // Done increments the number of rendering successes
- done: () => void;
- onDestroy: (fn: () => void) => void;
- reload: () => void;
- update: (params: any) => void;
- event: (event: event) => void;
-}
-
-export interface IInterpreterRenderFunction {
- name: string;
- displayName: string;
- help: string;
- validate: () => void;
- reuseDomNode: boolean;
- render: (domNode: Element, data: T, handlers: IInterpreterRenderHandlers) => void | Promise;
-}
-
-export interface IInterpreter {
- interpretAst(
- ast: ExpressionAST,
- context: Context,
- handlers: IInterpreterHandlers
- ): Promise;
-}
+export { TimeRange, Adapters, Query };
+export * from '../../../../../../plugins/expressions/public';
diff --git a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.js b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.js
index 9f0ed1dfb5097..65b1d41fa8239 100644
--- a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.js
+++ b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.js
@@ -20,12 +20,8 @@
import _ from 'lodash';
import { FilterManager } from './filter_manager.js';
import {
- buildPhraseFilter,
- buildPhrasesFilter,
- getPhraseFilterField,
- getPhraseFilterValue,
- isPhraseFilter,
-} from '@kbn/es-query';
+ esFilters,
+} from '../../../../../../plugins/data/public';
export class PhraseFilterManager extends FilterManager {
constructor(controlId, fieldName, indexPattern, queryFilter) {
@@ -43,12 +39,12 @@ export class PhraseFilterManager extends FilterManager {
createFilter(phrases) {
let newFilter;
if (phrases.length === 1) {
- newFilter = buildPhraseFilter(
+ newFilter = esFilters.buildPhraseFilter(
this.indexPattern.fields.getByName(this.fieldName),
phrases[0],
this.indexPattern);
} else {
- newFilter = buildPhrasesFilter(
+ newFilter = esFilters.buildPhrasesFilter(
this.indexPattern.fields.getByName(this.fieldName),
phrases,
this.indexPattern);
@@ -107,12 +103,12 @@ export class PhraseFilterManager extends FilterManager {
}
// single phrase filter
- if (isPhraseFilter(kbnFilter)) {
- if (getPhraseFilterField(kbnFilter) !== this.fieldName) {
+ if (esFilters.isPhraseFilter(kbnFilter)) {
+ if (esFilters.getPhraseFilterField(kbnFilter) !== this.fieldName) {
return;
}
- return getPhraseFilterValue(kbnFilter);
+ return esFilters.getPhraseFilterValue(kbnFilter);
}
// single phrase filter from bool filter
diff --git a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.js b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.js
index 1c8f5e2aa5a3e..3a232fd8b543d 100644
--- a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.js
+++ b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import { FilterManager } from './filter_manager.js';
-import { buildRangeFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
// Convert slider value into ES range filter
function toRange(sliderValue) {
@@ -55,7 +55,7 @@ export class RangeFilterManager extends FilterManager {
* @return {object} range filter
*/
createFilter(value) {
- const newFilter = buildRangeFilter(
+ const newFilter = esFilters.buildRangeFilter(
this.indexPattern.fields.getByName(this.fieldName),
toRange(value),
this.indexPattern);
diff --git a/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.js b/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.js
index 44c68c84579c6..86fe6db9b0778 100644
--- a/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.js
+++ b/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.js
@@ -26,6 +26,7 @@ import {
import { PhraseFilterManager } from './filter_manager/phrase_filter_manager';
import { createSearchSource } from './create_search_source';
import { i18n } from '@kbn/i18n';
+import { npStart } from 'ui/new_platform';
import chrome from 'ui/chrome';
import { start as data } from '../../../../core_plugins/data/public/legacy';
@@ -187,9 +188,10 @@ export async function listControlFactory(controlParams, useTimeFilter, SearchSou
// ignore not found error and return control so it can be displayed in disabled state.
}
+ const { filterManager } = npStart.plugins.data.query;
return new ListControl(
controlParams,
- new PhraseFilterManager(controlParams.id, controlParams.fieldName, indexPattern, data.filter.filterManager),
+ new PhraseFilterManager(controlParams.id, controlParams.fieldName, indexPattern, filterManager),
useTimeFilter,
SearchSource,
);
diff --git a/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.test.js b/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.test.js
index d5c23c2c1c855..b40a9f8e6efd4 100644
--- a/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.test.js
+++ b/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.test.js
@@ -24,6 +24,28 @@ jest.mock('ui/timefilter', () => ({
createFilter: jest.fn(),
}));
+jest.mock('ui/new_platform', () => ({
+ npStart: {
+ plugins: {
+ data: {
+ query: {
+ filterManager: {
+ fieldName: 'myNumberField',
+ getIndexPattern: () => ({
+ fields: { getByName: name => {
+ const fields = { myField: { name: 'myField' } };
+ return fields[name];
+ } }
+ }),
+ getAppFilters: jest.fn().mockImplementation(() => ([])),
+ getGlobalFilters: jest.fn().mockImplementation(() => ([])),
+ }
+ }
+ }
+ },
+ },
+}));
+
jest.mock('../../../../core_plugins/data/public/legacy', () => ({
start: {
indexPatterns: {
@@ -36,19 +58,6 @@ jest.mock('../../../../core_plugins/data/public/legacy', () => ({
}),
}
},
- filter: {
- filterManager: {
- fieldName: 'myNumberField',
- getIndexPattern: () => ({
- fields: { getByName: name => {
- const fields = { myField: { name: 'myField' } };
- return fields[name];
- } }
- }),
- getAppFilters: jest.fn().mockImplementation(() => ([])),
- getGlobalFilters: jest.fn().mockImplementation(() => ([])),
- }
- }
}
}));
diff --git a/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.js b/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.js
index efb208bd80045..2a05a1224aab9 100644
--- a/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.js
+++ b/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.js
@@ -27,6 +27,7 @@ import { RangeFilterManager } from './filter_manager/range_filter_manager';
import { createSearchSource } from './create_search_source';
import { i18n } from '@kbn/i18n';
import { start as data } from '../../../../core_plugins/data/public/legacy';
+import { npStart } from 'ui/new_platform';
const minMaxAgg = (field) => {
const aggBody = {};
@@ -106,9 +107,10 @@ export async function rangeControlFactory(controlParams, useTimeFilter, SearchSo
} catch (err) {
// ignore not found error and return control so it can be displayed in disabled state.
}
+ const { filterManager } = npStart.plugins.data.query;
return new RangeControl(
controlParams,
- new RangeFilterManager(controlParams.id, controlParams.fieldName, indexPattern, data.filter.filterManager),
+ new RangeFilterManager(controlParams.id, controlParams.fieldName, indexPattern, filterManager),
useTimeFilter,
SearchSource,
);
diff --git a/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.test.js b/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.test.js
index c746d116c70b2..3e6d6a49a1118 100644
--- a/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.test.js
+++ b/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.test.js
@@ -32,6 +32,28 @@ jest.mock('ui/timefilter', () => ({
createFilter: jest.fn(),
}));
+jest.mock('ui/new_platform', () => ({
+ npStart: {
+ plugins: {
+ data: {
+ query: {
+ filterManager: {
+ fieldName: 'myNumberField',
+ getIndexPattern: () => ({
+ fields: { getByName: name => {
+ const fields = { myNumberField: { name: 'myNumberField' } };
+ return fields[name];
+ }
+ } }),
+ getAppFilters: jest.fn().mockImplementation(() => ([])),
+ getGlobalFilters: jest.fn().mockImplementation(() => ([])),
+ }
+ }
+ }
+ },
+ },
+}));
+
jest.mock('../../../../core_plugins/data/public/legacy', () => ({
start: {
indexPatterns: {
@@ -44,19 +66,6 @@ jest.mock('../../../../core_plugins/data/public/legacy', () => ({
} }),
}
},
- filter: {
- filterManager: {
- fieldName: 'myNumberField',
- getIndexPattern: () => ({
- fields: { getByName: name => {
- const fields = { myNumberField: { name: 'myNumberField' } };
- return fields[name];
- }
- } }),
- getAppFilters: jest.fn().mockImplementation(() => ([])),
- getGlobalFilters: jest.fn().mockImplementation(() => ([])),
- }
- }
}
}));
diff --git a/src/legacy/core_plugins/input_control_vis/public/vis_controller.js b/src/legacy/core_plugins/input_control_vis/public/vis_controller.js
index 1edf5652a76c5..792ff3fe85479 100644
--- a/src/legacy/core_plugins/input_control_vis/public/vis_controller.js
+++ b/src/legacy/core_plugins/input_control_vis/public/vis_controller.js
@@ -23,7 +23,7 @@ import { I18nContext } from 'ui/i18n';
import { InputControlVis } from './components/vis/input_control_vis';
import { controlFactory } from './control/control_factory';
import { getLineageMap } from './lineage';
-import { start as data } from '../../../core_plugins/data/public/legacy';
+import { npStart } from 'ui/new_platform';
import { SearchSource } from '../../../ui/public/courier/search_source/search_source';
class VisController {
@@ -34,7 +34,7 @@ class VisController {
this.queryBarUpdateHandler = this.updateControlsFromKbn.bind(this);
- this.filterManager = data.filter.filterManager;
+ this.filterManager = npStart.plugins.data.query.filterManager;
this.updateSubsciption = this.filterManager.getUpdates$()
.subscribe(this.queryBarUpdateHandler);
}
diff --git a/src/legacy/core_plugins/interpreter/common/index.ts b/src/legacy/core_plugins/interpreter/common/index.ts
index 0251faa69fccf..8a54741e9d3e1 100644
--- a/src/legacy/core_plugins/interpreter/common/index.ts
+++ b/src/legacy/core_plugins/interpreter/common/index.ts
@@ -36,7 +36,8 @@ export {
PointSeriesColumn,
PointSeriesColumnName,
Render,
+ ExpressionTypeStyle,
Style,
Type,
-} from '../../../../plugins/expressions/common';
+} from '../../../../plugins/expressions/public';
export const API_ROUTE = '/api/interpreter';
diff --git a/src/legacy/core_plugins/interpreter/common/lib/fonts.ts b/src/legacy/core_plugins/interpreter/common/lib/fonts.ts
index cdf3d4c16f3b5..1594f42abf2eb 100644
--- a/src/legacy/core_plugins/interpreter/common/lib/fonts.ts
+++ b/src/legacy/core_plugins/interpreter/common/lib/fonts.ts
@@ -17,135 +17,5 @@
* under the License.
*/
-/**
- * This type contains a unions of all supported font labels, or the the name of
- * the font the user would see in a UI.
- */
-export type FontLabel = typeof fonts[number]['label'];
-
-/**
- * This type contains a union of all supported font values, equivalent to the CSS
- * `font-value` property.
- */
-export type FontValue = typeof fonts[number]['value'];
-
-/**
- * An interface representing a font in Canvas, with a textual label and the CSS
- * `font-value`.
- */
-export interface Font {
- label: FontLabel;
- value: FontValue;
-}
-
-// This function allows one to create a strongly-typed font for inclusion in
-// the font collection. As a result, the values and labels are known to the
-// type system, preventing one from specifying a non-existent font at build
-// time.
-function createFont<
- RawFont extends { value: RawFontValue; label: RawFontLabel },
- RawFontValue extends string,
- RawFontLabel extends string
->(font: RawFont) {
- return font;
-}
-
-export const americanTypewriter = createFont({
- label: 'American Typewriter',
- value: "'American Typewriter', 'Courier New', Courier, Monaco, mono",
-});
-
-export const arial = createFont({ label: 'Arial', value: 'Arial, sans-serif' });
-
-export const baskerville = createFont({
- label: 'Baskerville',
- value: "Baskerville, Georgia, Garamond, 'Times New Roman', Times, serif",
-});
-
-export const bookAntiqua = createFont({
- label: 'Book Antiqua',
- value: "'Book Antiqua', Georgia, Garamond, 'Times New Roman', Times, serif",
-});
-
-export const brushScript = createFont({
- label: 'Brush Script',
- value: "'Brush Script MT', 'Comic Sans', sans-serif",
-});
-
-export const chalkboard = createFont({
- label: 'Chalkboard',
- value: "Chalkboard, 'Comic Sans', sans-serif",
-});
-
-export const didot = createFont({
- label: 'Didot',
- value: "Didot, Georgia, Garamond, 'Times New Roman', Times, serif",
-});
-
-export const futura = createFont({
- label: 'Futura',
- value: 'Futura, Impact, Helvetica, Arial, sans-serif',
-});
-
-export const gillSans = createFont({
- label: 'Gill Sans',
- value:
- "'Gill Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, Arial, sans-serif",
-});
-
-export const helveticaNeue = createFont({
- label: 'Helvetica Neue',
- value: "'Helvetica Neue', Helvetica, Arial, sans-serif",
-});
-
-export const hoeflerText = createFont({
- label: 'Hoefler Text',
- value: "'Hoefler Text', Garamond, Georgia, 'Times New Roman', Times, serif",
-});
-
-export const lucidaGrande = createFont({
- label: 'Lucida Grande',
- value: "'Lucida Grande', 'Lucida Sans Unicode', Lucida, Verdana, Helvetica, Arial, sans-serif",
-});
-
-export const myriad = createFont({
- label: 'Myriad',
- value: 'Myriad, Helvetica, Arial, sans-serif',
-});
-
-export const openSans = createFont({
- label: 'Open Sans',
- value: "'Open Sans', Helvetica, Arial, sans-serif",
-});
-
-export const optima = createFont({
- label: 'Optima',
- value: "Optima, 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, Arial, sans-serif",
-});
-
-export const palatino = createFont({
- label: 'Palatino',
- value: "Palatino, 'Book Antiqua', Georgia, Garamond, 'Times New Roman', Times, serif",
-});
-
-/**
- * A collection of supported fonts.
- */
-export const fonts = [
- americanTypewriter,
- arial,
- baskerville,
- bookAntiqua,
- brushScript,
- chalkboard,
- didot,
- futura,
- gillSans,
- helveticaNeue,
- hoeflerText,
- lucidaGrande,
- myriad,
- openSans,
- optima,
- palatino,
-];
+// eslint-disable-next-line
+export * from '../../../../../plugins/expressions/public/fonts';
diff --git a/src/legacy/core_plugins/interpreter/init.ts b/src/legacy/core_plugins/interpreter/init.ts
index fc93346f28024..f09ffd4697e74 100644
--- a/src/legacy/core_plugins/interpreter/init.ts
+++ b/src/legacy/core_plugins/interpreter/init.ts
@@ -25,7 +25,7 @@ import { register, registryFactory, Registry, Fn } from '@kbn/interpreter/common
// @ts-ignore
import { routes } from './server/routes';
-import { typeSpecs as types } from '../../../plugins/expressions/common';
+import { typeSpecs as types } from '../../../plugins/expressions/public';
import { Type } from './common';
import { Legacy } from '../../../../kibana';
diff --git a/src/legacy/core_plugins/interpreter/public/functions/clog.ts b/src/legacy/core_plugins/interpreter/public/functions/clog.ts
index 586584b498ac7..65362fe363374 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/clog.ts
+++ b/src/legacy/core_plugins/interpreter/public/functions/clog.ts
@@ -17,19 +17,5 @@
* under the License.
*/
-import { ExpressionFunction } from '../../types';
-
-const name = 'clog';
-
-type Context = any;
-type ClogExpressionFunction = ExpressionFunction;
-
-export const clog = (): ClogExpressionFunction => ({
- name,
- args: {},
- help: 'Outputs the context to the console',
- fn: context => {
- console.log(context); // eslint-disable-line no-console
- return context;
- },
-});
+// eslint-disable-next-line
+export * from '../../../../../plugins/expressions/public/functions/clog';
diff --git a/src/legacy/core_plugins/interpreter/public/functions/esaggs.ts b/src/legacy/core_plugins/interpreter/public/functions/esaggs.ts
index 6fcfde0a5b06b..d232a97c3c34c 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/esaggs.ts
+++ b/src/legacy/core_plugins/interpreter/public/functions/esaggs.ts
@@ -19,18 +19,12 @@
import { get, has } from 'lodash';
import { i18n } from '@kbn/i18n';
-// @ts-ignore
import { AggConfigs } from 'ui/agg_types/agg_configs';
import { createFormat } from 'ui/visualize/loader/pipeline_helpers/utilities';
import chrome from 'ui/chrome';
-
-// need to get rid of angular from these
-// @ts-ignore
import { TimeRange } from 'src/plugins/data/public';
import { SearchSource } from '../../../../ui/public/courier/search_source';
-// @ts-ignore
import { FilterBarQueryFilterProvider } from '../../../../ui/public/filter_manager/query_filter';
-
import { buildTabularInspectorData } from '../../../../ui/public/inspector/build_tabular_inspector_data';
import {
getRequestInspectorStats,
@@ -39,12 +33,15 @@ import {
import { calculateObjectHash } from '../../../../ui/public/vis/lib/calculate_object_hash';
import { getTime } from '../../../../ui/public/timefilter';
import { RequestHandlerParams } from '../../../../ui/public/visualize/loader/embedded_visualize_handler';
-// @ts-ignore
-import { tabifyAggResponse } from '../../../../ui/public/agg_response/tabify/tabify';
import { KibanaContext, KibanaDatatable } from '../../common';
import { ExpressionFunction, KibanaDatatableColumn } from '../../types';
import { start as data } from '../../../data/public/legacy';
+// @ts-ignore
+import { tabifyAggResponse } from '../../../../ui/public/agg_response/tabify/tabify';
+// @ts-ignore
+import { SearchSourceProvider } from '../../../../ui/public/courier/search_source';
+
const name = 'esaggs';
type Context = KibanaContext | null;
diff --git a/src/legacy/core_plugins/interpreter/public/functions/font.ts b/src/legacy/core_plugins/interpreter/public/functions/font.ts
index 5cd5add318e26..2f3bc1ff37e2c 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/font.ts
+++ b/src/legacy/core_plugins/interpreter/public/functions/font.ts
@@ -17,161 +17,5 @@
* under the License.
*/
-// @ts-ignore no @typed def
-import inlineStyle from 'inline-style';
-import { i18n } from '@kbn/i18n';
-import { openSans } from '../../common/lib/fonts';
-import { ExpressionFunction } from '../../types';
-import {
- CSSStyle,
- FontFamily,
- FontStyle,
- FontWeight,
- Style,
- TextAlignment,
- TextDecoration,
-} from '../types';
-
-interface Arguments {
- align?: TextAlignment;
- color?: string;
- family?: FontFamily;
- italic?: boolean;
- lHeight?: number | null;
- size?: number;
- underline?: boolean;
- weight?: FontWeight;
-}
-
-export function font(): ExpressionFunction<'font', null, Arguments, Style> {
- return {
- name: 'font',
- aliases: [],
- type: 'style',
- help: i18n.translate('interpreter.functions.fontHelpText', {
- defaultMessage: 'Create a font style.',
- }),
- context: {
- types: ['null'],
- },
- args: {
- align: {
- default: 'left',
- help: i18n.translate('interpreter.functions.font.args.alignHelpText', {
- defaultMessage: 'The horizontal text alignment.',
- }),
- options: Object.values(TextAlignment),
- types: ['string'],
- },
- color: {
- help: i18n.translate('interpreter.functions.font.args.colorHelpText', {
- defaultMessage: 'The text color.',
- }),
- types: ['string'],
- },
- family: {
- default: `"${openSans.value}"`,
- help: i18n.translate('interpreter.functions.font.args.familyHelpText', {
- defaultMessage: 'An acceptable {css} web font string',
- values: {
- css: 'CSS',
- },
- }),
- types: ['string'],
- },
- italic: {
- default: false,
- help: i18n.translate('interpreter.functions.font.args.italicHelpText', {
- defaultMessage: 'Italicize the text?',
- }),
- options: [true, false],
- types: ['boolean'],
- },
- lHeight: {
- default: null,
- aliases: ['lineHeight'],
- help: i18n.translate('interpreter.functions.font.args.lHeightHelpText', {
- defaultMessage: 'The line height in pixels',
- }),
- types: ['number', 'null'],
- },
- size: {
- default: 14,
- help: i18n.translate('interpreter.functions.font.args.sizeHelpText', {
- defaultMessage: 'The font size in pixels',
- }),
- types: ['number'],
- },
- underline: {
- default: false,
- help: i18n.translate('interpreter.functions.font.args.underlineHelpText', {
- defaultMessage: 'Underline the text?',
- }),
- options: [true, false],
- types: ['boolean'],
- },
- weight: {
- default: 'normal',
- help: i18n.translate('interpreter.functions.font.args.weightHelpText', {
- defaultMessage: 'The font weight. For example, {list}, or {end}.',
- values: {
- list: Object.values(FontWeight)
- .slice(0, -1)
- .map(weight => `\`"${weight}"\``)
- .join(', '),
- end: `\`"${Object.values(FontWeight).slice(-1)[0]}"\``,
- },
- }),
- options: Object.values(FontWeight),
- types: ['string'],
- },
- },
- fn: (_context, args) => {
- if (!Object.values(FontWeight).includes(args.weight!)) {
- throw new Error(
- i18n.translate('interpreter.functions.font.invalidFontWeightErrorMessage', {
- defaultMessage: "Invalid font weight: '{weight}'",
- values: {
- weight: args.weight,
- },
- })
- );
- }
- if (!Object.values(TextAlignment).includes(args.align!)) {
- throw new Error(
- i18n.translate('interpreter.functions.font.invalidTextAlignmentErrorMessage', {
- defaultMessage: "Invalid text alignment: '{align}'",
- values: {
- align: args.align,
- },
- })
- );
- }
-
- // the line height shouldn't ever be lower than the size, and apply as a
- // pixel setting
- const lineHeight = args.lHeight != null ? `${args.lHeight}px` : '1';
-
- const spec: CSSStyle = {
- fontFamily: args.family,
- fontWeight: args.weight,
- fontStyle: args.italic ? FontStyle.ITALIC : FontStyle.NORMAL,
- textDecoration: args.underline ? TextDecoration.UNDERLINE : TextDecoration.NONE,
- textAlign: args.align,
- fontSize: `${args.size}px`, // apply font size as a pixel setting
- lineHeight, // apply line height as a pixel setting
- };
-
- // conditionally apply styles based on input
- if (args.color) {
- spec.color = args.color;
- }
-
- return {
- type: 'style',
- spec,
- css: inlineStyle(spec),
- };
- },
- };
-}
+// eslint-disable-next-line
+export * from '../../../../../plugins/expressions/public/functions/font';
diff --git a/src/legacy/core_plugins/interpreter/public/functions/index.ts b/src/legacy/core_plugins/interpreter/public/functions/index.ts
deleted file mode 100644
index d86f033acb3d1..0000000000000
--- a/src/legacy/core_plugins/interpreter/public/functions/index.ts
+++ /dev/null
@@ -1,38 +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 { clog } from './clog';
-import { esaggs } from './esaggs';
-import { font } from './font';
-import { kibana } from './kibana';
-import { kibanaContext } from './kibana_context';
-import { range } from './range';
-import { visualization } from './visualization';
-import { visDimension } from './vis_dimension';
-
-export const functions = [
- clog,
- esaggs,
- font,
- kibana,
- kibanaContext,
- range,
- visualization,
- visDimension,
-];
diff --git a/src/legacy/core_plugins/interpreter/public/functions/kibana.ts b/src/legacy/core_plugins/interpreter/public/functions/kibana.ts
index c027b220ad0d0..7da284d9672a5 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/kibana.ts
+++ b/src/legacy/core_plugins/interpreter/public/functions/kibana.ts
@@ -17,47 +17,5 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
-import { ExpressionFunction, KibanaContext } from '../../types';
-
-export type ExpressionFunctionKibana = ExpressionFunction<
- 'kibana',
- KibanaContext | null,
- object,
- KibanaContext
->;
-
-export const kibana = (): ExpressionFunctionKibana => ({
- name: 'kibana',
- type: 'kibana_context',
-
- context: {
- types: ['kibana_context', 'null'],
- },
-
- help: i18n.translate('interpreter.functions.kibana.help', {
- defaultMessage: 'Gets kibana global context',
- }),
- args: {},
- fn(context, args, handlers) {
- const initialContext = handlers.getInitialContext ? handlers.getInitialContext() : {};
-
- if (context && context.query) {
- initialContext.query = initialContext.query.concat(context.query);
- }
-
- if (context && context.filters) {
- initialContext.filters = initialContext.filters.concat(context.filters);
- }
-
- const timeRange = initialContext.timeRange || (context ? context.timeRange : undefined);
-
- return {
- ...context,
- type: 'kibana_context',
- query: initialContext.query,
- filters: initialContext.filters,
- timeRange,
- };
- },
-});
+// eslint-disable-next-line
+export * from '../../../../../plugins/expressions/public/functions/kibana';
diff --git a/src/legacy/core_plugins/interpreter/public/functions/range.ts b/src/legacy/core_plugins/interpreter/public/functions/range.ts
index 8ae07dd82a22c..322bda983a8ff 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/range.ts
+++ b/src/legacy/core_plugins/interpreter/public/functions/range.ts
@@ -17,48 +17,5 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
-import { KibanaDatatable, Range } from '../../types';
-import { ExpressionFunction } from '../../types';
-
-const name = 'range';
-
-type Context = KibanaDatatable | null;
-
-interface Arguments {
- from: number;
- to: number;
-}
-
-type Return = Range; // imported from type
-
-export const range = (): ExpressionFunction => ({
- name,
- help: i18n.translate('interpreter.function.range.help', {
- defaultMessage: 'Generates range object',
- }),
- type: 'range',
- args: {
- from: {
- types: ['number'],
- help: i18n.translate('interpreter.function.range.from.help', {
- defaultMessage: 'Start of range',
- }),
- required: true,
- },
- to: {
- types: ['number'],
- help: i18n.translate('interpreter.function.range.to.help', {
- defaultMessage: 'End of range',
- }),
- required: true,
- },
- },
- fn: (context, args) => {
- return {
- type: 'range',
- from: args.from,
- to: args.to,
- };
- },
-});
+// eslint-disable-next-line
+export * from '../../../../../plugins/visualizations/public/expression_functions/range';
diff --git a/src/legacy/core_plugins/interpreter/public/functions/vis_dimension.ts b/src/legacy/core_plugins/interpreter/public/functions/vis_dimension.ts
index 4190a597b0120..d4ebeeb5267e1 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/vis_dimension.ts
+++ b/src/legacy/core_plugins/interpreter/public/functions/vis_dimension.ts
@@ -17,73 +17,5 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
-import { ExpressionFunction, KibanaDatatable } from '../../types';
-
-const name = 'visdimension';
-
-type Context = KibanaDatatable | null;
-
-interface Arguments {
- accessor: string | number;
- format?: string;
- formatParams?: string;
-}
-
-type Return = any;
-
-export const visDimension = (): ExpressionFunction => ({
- name: 'visdimension',
- help: i18n.translate('interpreter.function.visDimension.help', {
- defaultMessage: 'Generates visConfig dimension object',
- }),
- type: 'vis_dimension',
- context: {
- types: ['kibana_datatable'],
- },
- args: {
- accessor: {
- types: ['string', 'number'],
- aliases: ['_'],
- help: i18n.translate('interpreter.function.visDimension.accessor.help', {
- defaultMessage: 'Column in your dataset to use (either column index or column name)',
- }),
- },
- format: {
- types: ['string'],
- default: 'string',
- help: i18n.translate('interpreter.function.visDimension.format.help', {
- defaultMessage: 'Format',
- }),
- },
- formatParams: {
- types: ['string'],
- default: '"{}"',
- help: i18n.translate('interpreter.function.visDimension.formatParams.help', {
- defaultMessage: 'Format params',
- }),
- },
- },
- fn: (context, args) => {
- const accessor =
- typeof args.accessor === 'number'
- ? args.accessor
- : context!.columns.find(c => c.id === args.accessor);
- if (accessor === undefined) {
- throw new Error(
- i18n.translate('interpreter.function.visDimension.error.accessor', {
- defaultMessage: 'Column name provided is invalid',
- })
- );
- }
-
- return {
- type: 'vis_dimension',
- accessor,
- format: {
- id: args.format,
- params: JSON.parse(args.formatParams!),
- },
- };
- },
-});
+// eslint-disable-next-line
+export * from '../../../../../plugins/visualizations/public/expression_functions/vis_dimension';
diff --git a/src/legacy/core_plugins/interpreter/public/interpreter.test.ts b/src/legacy/core_plugins/interpreter/public/interpreter.test.ts
deleted file mode 100644
index 429a943c3ff36..0000000000000
--- a/src/legacy/core_plugins/interpreter/public/interpreter.test.ts
+++ /dev/null
@@ -1,120 +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.
- */
-
-jest.mock('ui/new_platform', () => ({
- npSetup: {
- core: {
- http: {},
- injectedMetadata: {
- getKibanaVersion: () => '8.0.0',
- getBasePath: () => '/lol',
- },
- },
- },
-}));
-jest.mock('uiExports/interpreter');
-
-jest.mock('@kbn/interpreter/common', () => ({
- register: jest.fn(),
- registryFactory: jest.fn(),
-}));
-
-const mockExecutor = {
- interpreter: {
- interpretAst: jest.fn(),
- },
-};
-jest.mock('./lib/interpreter', () => ({
- initializeExecutor: jest.fn().mockReturnValue(Promise.resolve(mockExecutor)),
-}));
-
-jest.mock('./registries', () => ({
- registries: {
- browserFunctions: jest.fn(),
- renderers: jest.fn(),
- types: jest.fn(),
- },
-}));
-
-jest.mock('../../../ui/public/new_platform');
-jest.mock('./functions', () => ({ functions: [{}, {}, {}] }));
-jest.mock('./renderers/visualization', () => ({ visualization: {} }));
-
-describe('interpreter/interpreter', () => {
- let getInterpreter: any;
- let interpretAst: any;
- let initializeExecutor: any;
-
- beforeEach(() => {
- jest.clearAllMocks();
- jest.resetModules();
- getInterpreter = require('./interpreter').getInterpreter;
- interpretAst = require('./interpreter').interpretAst;
- initializeExecutor = require('./lib/interpreter').initializeExecutor;
- });
-
- describe('getInterpreter', () => {
- it('initializes interpreter', async () => {
- await getInterpreter();
- expect(initializeExecutor).toHaveBeenCalledTimes(1);
- });
-
- it('only initializes interpreter once', async () => {
- await getInterpreter();
- await getInterpreter();
- expect(initializeExecutor).toHaveBeenCalledTimes(1);
- });
-
- it('resolves', async () => {
- await expect(getInterpreter()).resolves;
- });
-
- it('resolves with interpreter object', async () => {
- const interpreter = await getInterpreter();
- await expect(Object.keys(interpreter)).toEqual(['interpreter']);
- });
- });
-
- describe('interpretAst', () => {
- it('resolves', async () => {
- const params = [{}];
- await expect(interpretAst(...params)).resolves;
- });
-
- it('initializes interpreter if needed', async () => {
- const params = [{}];
- await interpretAst(...params);
- expect(initializeExecutor).toHaveBeenCalledTimes(1);
- });
-
- it('calls interpreter.interpretAst with the provided params', async () => {
- const params = [{}];
- await interpretAst(...params);
- expect(mockExecutor.interpreter.interpretAst).toHaveBeenCalledTimes(1);
- expect(mockExecutor.interpreter.interpretAst).toHaveBeenCalledWith({}, undefined, undefined);
- });
-
- it('calls interpreter.interpretAst each time', async () => {
- const params = [{}];
- await interpretAst(...params);
- await interpretAst(...params);
- expect(mockExecutor.interpreter.interpretAst).toHaveBeenCalledTimes(2);
- });
- });
-});
diff --git a/src/legacy/core_plugins/interpreter/public/interpreter.ts b/src/legacy/core_plugins/interpreter/public/interpreter.ts
index 1f0f8141345d2..a337f7e4ebfea 100644
--- a/src/legacy/core_plugins/interpreter/public/interpreter.ts
+++ b/src/legacy/core_plugins/interpreter/public/interpreter.ts
@@ -20,38 +20,42 @@
import 'uiExports/interpreter';
// @ts-ignore
import { register, registryFactory } from '@kbn/interpreter/common';
-import {
- initializeExecutor,
- ExpressionExecutor,
- ExpressionInterpretWithHandlers,
-} from './lib/interpreter';
+import { npSetup } from 'ui/new_platform';
import { registries } from './registries';
-import { functions } from './functions';
import { visualization } from './renderers/visualization';
-import { typeSpecs } from '../../../../plugins/expressions/common';
+import {
+ ExpressionInterpretWithHandlers,
+ ExpressionExecutor,
+} from '../../../../plugins/expressions/public';
+import { esaggs as esaggsFn } from './functions/esaggs';
+import { visualization as visualizationFn } from './functions/visualization';
// Expose kbnInterpreter.register(specs) and kbnInterpreter.registries() globally so that plugins
// can register without a transpile step.
+// TODO: This will be left behind in then legacy platform?
(global as any).kbnInterpreter = Object.assign(
(global as any).kbnInterpreter || {},
registryFactory(registries)
);
-register(registries, {
- types: typeSpecs,
- browserFunctions: functions,
- renderers: [visualization],
-});
+// TODO: This needs to be moved to `data` plugin Search service.
+registries.browserFunctions.register(esaggsFn);
-let executorPromise: Promise | undefined;
+// TODO: This needs to be moved to `visualizations` plugin.
+registries.browserFunctions.register(visualizationFn);
+registries.renderers.register(visualization);
+// TODO: This function will be left behind in the legacy platform.
+let executorPromise: Promise | undefined;
export const getInterpreter = async () => {
if (!executorPromise) {
- executorPromise = initializeExecutor();
+ const executor = npSetup.plugins.expressions.__LEGACY.getExecutor();
+ executorPromise = Promise.resolve(executor);
}
return await executorPromise;
};
+// TODO: This function will be left behind in the legacy platform.
export const interpretAst: ExpressionInterpretWithHandlers = async (ast, context, handlers) => {
const { interpreter } = await getInterpreter();
return await interpreter.interpretAst(ast, context, handlers);
diff --git a/src/legacy/core_plugins/interpreter/public/lib/create_handlers.ts b/src/legacy/core_plugins/interpreter/public/lib/create_handlers.ts
index 46e85411c5895..c14272fbf8def 100644
--- a/src/legacy/core_plugins/interpreter/public/lib/create_handlers.ts
+++ b/src/legacy/core_plugins/interpreter/public/lib/create_handlers.ts
@@ -17,8 +17,5 @@
* under the License.
*/
-export function createHandlers() {
- return {
- environment: 'client',
- };
-}
+// eslint-disable-next-line
+export * from '../../../../../plugins/expressions/public/create_handlers';
diff --git a/src/legacy/core_plugins/interpreter/public/lib/interpreter.ts b/src/legacy/core_plugins/interpreter/public/lib/interpreter.ts
deleted file mode 100644
index 399ecc5950268..0000000000000
--- a/src/legacy/core_plugins/interpreter/public/lib/interpreter.ts
+++ /dev/null
@@ -1,51 +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 { ExpressionInterpret } from 'src/plugins/expressions/common/expressions/interpreter_provider';
-import { interpreterProvider } from '../../common';
-import { createHandlers } from './create_handlers';
-import { registries } from '../registries';
-import { FunctionHandlers } from '../../types';
-
-export type ExpressionInterpretWithHandlers = (
- ast: Parameters[0],
- context: Parameters[1],
- handlers: FunctionHandlers
-) => ReturnType;
-
-export interface ExpressionInterpreter {
- interpretAst: ExpressionInterpretWithHandlers;
-}
-
-export interface ExpressionExecutor {
- interpreter: ExpressionInterpreter;
-}
-
-export async function initializeExecutor(): Promise {
- const interpretAst: ExpressionInterpretWithHandlers = async (ast, context, handlers) => {
- const interpret = await interpreterProvider({
- types: registries.types.toJS(),
- handlers: { ...handlers, ...createHandlers() },
- functions: registries.browserFunctions.toJS(),
- });
- return interpret(ast, context);
- };
-
- return { interpreter: { interpretAst } };
-}
diff --git a/src/legacy/core_plugins/interpreter/public/types/style.ts b/src/legacy/core_plugins/interpreter/public/types/style.ts
index fd22b9bae2e95..7386048a4ae04 100644
--- a/src/legacy/core_plugins/interpreter/public/types/style.ts
+++ b/src/legacy/core_plugins/interpreter/public/types/style.ts
@@ -17,120 +17,10 @@
* under the License.
*/
-import { FontLabel } from '../../common/lib/fonts';
-export { FontLabel as FontFamily, FontValue } from '../../common/lib/fonts';
-
-/**
- * Enum of supported CSS `background-repeat` properties.
- */
-export enum BackgroundRepeat {
- REPEAT = 'repeat',
- REPEAT_NO = 'no-repeat',
- REPEAT_X = 'repeat-x',
- REPEAT_Y = 'repeat-y',
- ROUND = 'round',
- SPACE = 'space',
-}
-
-/**
- * Enum of supported CSS `background-size` properties.
- */
-export enum BackgroundSize {
- AUTO = 'auto',
- CONTAIN = 'contain',
- COVER = 'cover',
-}
-
-/**
- * Enum of supported CSS `font-style` properties.
- */
-export enum FontStyle {
- ITALIC = 'italic',
- NORMAL = 'normal',
-}
-
-/**
- * Enum of supported CSS `font-weight` properties.
- */
-export enum FontWeight {
- NORMAL = 'normal',
- BOLD = 'bold',
- BOLDER = 'bolder',
- LIGHTER = 'lighter',
- ONE = '100',
- TWO = '200',
- THREE = '300',
- FOUR = '400',
- FIVE = '500',
- SIX = '600',
- SEVEN = '700',
- EIGHT = '800',
- NINE = '900',
-}
-
-/**
- * Enum of supported CSS `overflow` properties.
- */
-export enum Overflow {
- AUTO = 'auto',
- HIDDEN = 'hidden',
- SCROLL = 'scroll',
- VISIBLE = 'visible',
-}
-
-/**
- * Enum of supported CSS `text-align` properties.
- */
-export enum TextAlignment {
- CENTER = 'center',
- JUSTIFY = 'justify',
- LEFT = 'left',
- RIGHT = 'right',
-}
-
-/**
- * Enum of supported CSS `text-decoration` properties.
- */
-export enum TextDecoration {
- NONE = 'none',
- UNDERLINE = 'underline',
-}
-
-/**
- * Represents the various style properties that can be applied to an element.
- */
-export interface CSSStyle {
- color?: string;
- fill?: string;
- fontFamily?: FontLabel;
- fontSize?: string;
- fontStyle?: FontStyle;
- fontWeight?: FontWeight;
- lineHeight?: number | string;
- textAlign?: TextAlignment;
- textDecoration?: TextDecoration;
-}
-
-/**
- * Represents an object containing style information for a Container.
- */
-export interface ContainerStyle {
- border: string | null;
- borderRadius: string | null;
- padding: string | null;
- backgroundColor: string | null;
- backgroundImage: string | null;
- backgroundSize: BackgroundSize;
- backgroundRepeat: BackgroundRepeat;
- opacity: number | null;
- overflow: Overflow;
-}
-
-/**
- * An object that represents style information, typically CSS.
- */
-export interface Style {
- type: 'style';
- spec: CSSStyle;
- css: string;
-}
+/* eslint-disable */
+export * from '../../../../../plugins/expressions/public/types/style';
+export {
+ FontLabel as FontFamily,
+ FontValue,
+} from '../../../../../plugins/expressions/public/fonts';
+/* eslint-enable */
diff --git a/src/legacy/core_plugins/interpreter/test_helpers.ts b/src/legacy/core_plugins/interpreter/test_helpers.ts
index 1f39a8271367c..0e34f42b01544 100644
--- a/src/legacy/core_plugins/interpreter/test_helpers.ts
+++ b/src/legacy/core_plugins/interpreter/test_helpers.ts
@@ -17,17 +17,5 @@
* under the License.
*/
-import { mapValues } from 'lodash';
-import { AnyExpressionFunction, FunctionHandlers } from './types';
-
-// Takes a function spec and passes in default args,
-// overriding with any provided args.
-export const functionWrapper = (fnSpec: () => T) => {
- const spec = fnSpec();
- const defaultArgs = mapValues(spec.args, argSpec => argSpec.default);
- return (
- context: object | null,
- args: Record = {},
- handlers: FunctionHandlers = {}
- ) => spec.fn(context, { ...defaultArgs, ...args }, handlers);
-};
+// eslint-disable-next-line
+export * from '../../../plugins/expressions/public/functions/tests/utils';
diff --git a/src/legacy/core_plugins/interpreter/types/arguments.ts b/src/legacy/core_plugins/interpreter/types/arguments.ts
index 3e17166a7c434..35566381d010d 100644
--- a/src/legacy/core_plugins/interpreter/types/arguments.ts
+++ b/src/legacy/core_plugins/interpreter/types/arguments.ts
@@ -17,4 +17,5 @@
* under the License.
*/
-export * from '../../../../plugins/expressions/common/expressions/types/arguments';
+// eslint-disable-next-line
+export * from '../../../../plugins/expressions/public/types/arguments';
diff --git a/src/legacy/core_plugins/interpreter/types/common.ts b/src/legacy/core_plugins/interpreter/types/common.ts
index dce984a0bd556..99a7d2dc92f06 100644
--- a/src/legacy/core_plugins/interpreter/types/common.ts
+++ b/src/legacy/core_plugins/interpreter/types/common.ts
@@ -17,4 +17,5 @@
* under the License.
*/
-export * from '../../../../plugins/expressions/common/expressions/types/common';
+// eslint-disable-next-line
+export * from '../../../../plugins/expressions/public/types/common';
diff --git a/src/legacy/core_plugins/interpreter/types/functions.ts b/src/legacy/core_plugins/interpreter/types/functions.ts
index 789bb29990cb4..9a99a78281a0c 100644
--- a/src/legacy/core_plugins/interpreter/types/functions.ts
+++ b/src/legacy/core_plugins/interpreter/types/functions.ts
@@ -17,4 +17,5 @@
* under the License.
*/
-export * from '../../../../plugins/expressions/common/expressions/types/functions';
+// eslint-disable-next-line
+export * from '../../../../plugins/expressions/public/types/functions';
diff --git a/src/legacy/core_plugins/interpreter/types/index.ts b/src/legacy/core_plugins/interpreter/types/index.ts
index c178bee26a7cd..6cefc47a678d4 100644
--- a/src/legacy/core_plugins/interpreter/types/index.ts
+++ b/src/legacy/core_plugins/interpreter/types/index.ts
@@ -17,4 +17,4 @@
* under the License.
*/
-export * from '../../../../plugins/expressions/common';
+export * from '../../../../plugins/expressions/public';
diff --git a/src/legacy/core_plugins/interpreter/types/types.ts b/src/legacy/core_plugins/interpreter/types/types.ts
index d3f1cb3987b00..aacb63eaace0c 100644
--- a/src/legacy/core_plugins/interpreter/types/types.ts
+++ b/src/legacy/core_plugins/interpreter/types/types.ts
@@ -17,4 +17,5 @@
* under the License.
*/
-export * from '../../../../plugins/expressions/common/expressions/types';
+// eslint-disable-next-line
+export * from '../../../../plugins/expressions/public/types';
diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx b/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx
index 1d979f82d39d8..045e8093124a6 100644
--- a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx
+++ b/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx
@@ -100,6 +100,7 @@ export function DocViewTableRow({
* Justification for dangerouslySetInnerHTML:
* We just use values encoded by our field formatters
*/
+ // eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: value as string }}
/>
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/number_input.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/number_input.tsx
index 282c2e6a356bf..b614e00ba8cd0 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/number_input.tsx
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/number_input.tsx
@@ -34,6 +34,12 @@ interface NumberInputOptionProps {
setValue: (paramName: ParamName, value: number | '') => void;
}
+/**
+ * Do not use this component anymore.
+ * Please, use NumberInputOption in 'required_number_input.tsx'.
+ * It is required for compatibility with TS 3.7.0
+ * This should be removed in the future
+ */
function NumberInputOption({
disabled,
error,
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/required_number_input.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/required_number_input.tsx
new file mode 100644
index 0000000000000..7b62016c4e502
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/required_number_input.tsx
@@ -0,0 +1,87 @@
+/*
+ * 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, useCallback, ChangeEvent } from 'react';
+import { EuiFormRow, EuiFieldNumber } from '@elastic/eui';
+import { useValidation } from './utils';
+
+interface NumberInputOptionProps {
+ disabled?: boolean;
+ error?: ReactNode;
+ isInvalid?: boolean;
+ label?: React.ReactNode;
+ max?: number;
+ min?: number;
+ paramName: ParamName;
+ step?: number;
+ value: number | null;
+ 'data-test-subj'?: string;
+ setValue(paramName: ParamName, value: number | null): void;
+ setValidity(paramName: ParamName, isValid: boolean): void;
+}
+
+/**
+ * Use only this component instead of NumberInputOption in 'number_input.tsx'.
+ * It is required for compatibility with TS 3.7.0
+ *
+ * @param {number} props.value Should be numeric only
+ */
+function NumberInputOption({
+ disabled,
+ error,
+ isInvalid,
+ label,
+ max,
+ min,
+ paramName,
+ step,
+ value,
+ setValue,
+ setValidity,
+ 'data-test-subj': dataTestSubj,
+}: NumberInputOptionProps) {
+ const isValid = value !== null;
+ useValidation(setValidity, paramName, isValid);
+
+ const onChange = useCallback(
+ (ev: ChangeEvent) =>
+ setValue(paramName, isNaN(ev.target.valueAsNumber) ? null : ev.target.valueAsNumber),
+ [setValue, paramName]
+ );
+
+ return (
+
+
+
+ );
+}
+
+export { NumberInputOption };
diff --git a/packages/kbn-es-query/src/filters/lib/phrases_filter.ts b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/utils.ts
similarity index 68%
rename from packages/kbn-es-query/src/filters/lib/phrases_filter.ts
rename to src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/utils.ts
index 213afb409a0a6..d51631106dda7 100644
--- a/packages/kbn-es-query/src/filters/lib/phrases_filter.ts
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/utils.ts
@@ -17,16 +17,18 @@
* under the License.
*/
-import { Filter, FilterMeta } from './meta_filter';
+import { useEffect } from 'react';
-export type PhrasesFilterMeta = FilterMeta & {
- params: string[]; // The unformatted values
- field?: string;
-};
+function useValidation(
+ setValidity: (paramName: ParamName, isValid: boolean) => void,
+ paramName: ParamName,
+ isValid: boolean
+) {
+ useEffect(() => {
+ setValidity(paramName, isValid);
-export type PhrasesFilter = Filter & {
- meta: PhrasesFilterMeta;
-};
+ return () => setValidity(paramName, true);
+ }, [isValid, paramName, setValidity]);
+}
-export const isPhrasesFilter = (filter: any): filter is PhrasesFilter =>
- filter && filter.meta.type === 'phrases';
+export { useValidation };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx
index 8e3f66d12b9bd..ed3b52b83c234 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx
@@ -21,13 +21,12 @@ import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { VisOptionsProps } from 'ui/vis/editors/default';
-import { BasicOptions, SwitchOption } from '../../common';
+import { BasicOptions, SwitchOption, ValidationVisOptionsProps } from '../../common';
import { GridPanel } from './grid_panel';
import { ThresholdPanel } from './threshold_panel';
import { BasicVislibParams } from '../../../types';
-function PointSeriesOptions(props: VisOptionsProps) {
+function PointSeriesOptions(props: ValidationVisOptionsProps) {
const { stateParams, setValue, vis } = props;
return (
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx
index 49e56e377a8d5..591ad2eb3a001 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx
@@ -21,11 +21,16 @@ import { EuiPanel, EuiTitle, EuiColorPicker, EuiFormRow, EuiSpacer } from '@elas
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { VisOptionsProps } from 'ui/vis/editors/default';
-import { NumberInputOption, SelectOption, SwitchOption } from '../../common';
+import { SelectOption, SwitchOption, ValidationVisOptionsProps } from '../../common';
+import { NumberInputOption } from '../../common/required_number_input';
import { BasicVislibParams } from '../../../types';
-function ThresholdPanel({ stateParams, setValue, vis }: VisOptionsProps) {
+function ThresholdPanel({
+ stateParams,
+ setValue,
+ setMultipleValidity,
+ vis,
+}: ValidationVisOptionsProps) {
const setThresholdLine = useCallback(
(
paramName: T,
@@ -39,6 +44,12 @@ function ThresholdPanel({ stateParams, setValue, vis }: VisOptionsProps
+ setMultipleValidity(`thresholdLine__${paramName}`, isValid),
+ [setMultipleValidity]
+ );
+
return (
@@ -72,6 +83,7 @@ function ThresholdPanel({ stateParams, setValue, vis }: VisOptionsProps
) => (
+
+ ),
},
];
}
diff --git a/src/legacy/core_plugins/kibana/migrations/migrations.js b/src/legacy/core_plugins/kibana/migrations/migrations.js
index 9f3561f39101d..e024e98acb343 100644
--- a/src/legacy/core_plugins/kibana/migrations/migrations.js
+++ b/src/legacy/core_plugins/kibana/migrations/migrations.js
@@ -460,6 +460,31 @@ function migrateFiltersAggQueryStringQueries(doc) {
}
+function migrateSubTypeAndParentFieldProperties(doc) {
+ if (!doc.attributes.fields) return doc;
+
+ const fieldsString = doc.attributes.fields;
+ const fields = JSON.parse(fieldsString);
+ const migratedFields = fields.map(field => {
+ if (field.subType === 'multi') {
+ return {
+ ...omit(field, 'parent'),
+ subType: { multi: { parent: field.parent } }
+ };
+ }
+
+ return field;
+ });
+
+ return {
+ ...doc,
+ attributes: {
+ ...doc.attributes,
+ fields: JSON.stringify(migratedFields),
+ }
+ };
+}
+
const executeMigrations720 = flow(
migratePercentileRankAggregation,
migrateDateHistogramAggregation
@@ -490,6 +515,9 @@ export const migrations = {
doc.attributes.typeMeta = doc.attributes.typeMeta || undefined;
return doc;
},
+ '7.6.0': flow(
+ migrateSubTypeAndParentFieldProperties
+ )
},
visualization: {
/**
diff --git a/src/legacy/core_plugins/kibana/migrations/migrations.test.js b/src/legacy/core_plugins/kibana/migrations/migrations.test.js
index 5368169d6dd6d..14f1e8c80e349 100644
--- a/src/legacy/core_plugins/kibana/migrations/migrations.test.js
+++ b/src/legacy/core_plugins/kibana/migrations/migrations.test.js
@@ -56,6 +56,29 @@ Object {
`);
});
});
+
+ describe('7.6.0', function () {
+ const migrate = doc => migrations['index-pattern']['7.6.0'](doc);
+
+ it('should remove the parent property and update the subType prop on every field that has them', () => {
+ const input = {
+ attributes: {
+ title: 'test',
+ // eslint-disable-next-line max-len
+ fields: '[{"name":"customer_name","type":"string","esTypes":["text"],"count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"customer_name.keyword","type":"string","esTypes":["keyword"],"count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":"multi","parent":"customer_name"}]',
+ },
+ };
+ const expected = {
+ attributes: {
+ title: 'test',
+ // eslint-disable-next-line max-len
+ fields: '[{"name":"customer_name","type":"string","esTypes":["text"],"count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"customer_name.keyword","type":"string","esTypes":["keyword"],"count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true,"subType":{"multi":{"parent":"customer_name"}}}]',
+ },
+ };
+
+ expect(migrate(input)).toEqual(expected);
+ });
+ });
});
describe('visualization', () => {
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx
index 7a0398e86a60d..5fa3a938ed9df 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx
@@ -35,7 +35,6 @@ import {
} from 'ui/state_management/app_state';
import { KbnUrl } from 'ui/url/kbn_url';
-import { Filter } from '@kbn/es-query';
import { TimeRange } from 'src/plugins/data/public';
import { IndexPattern } from 'ui/index_patterns';
import { IPrivate } from 'ui/private';
@@ -46,6 +45,7 @@ import { Subscription } from 'rxjs';
import { ViewMode } from '../../../embeddable_api/public/np_ready/public';
import { SavedObjectDashboard } from './saved_dashboard/saved_dashboard';
import { DashboardAppState, SavedDashboardPanel, ConfirmModalFn } from './types';
+import { esFilters } from '../../../../../../src/plugins/data/public';
import { DashboardAppController } from './dashboard_app_controller';
@@ -55,7 +55,7 @@ export interface DashboardAppScope extends ng.IScope {
screenTitle: string;
model: {
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
timeRestore: boolean;
title: string;
description: string;
@@ -81,9 +81,9 @@ export interface DashboardAppScope extends ng.IScope {
isPaused: boolean;
refreshInterval: any;
}) => void;
- onFiltersUpdated: (filters: Filter[]) => void;
+ onFiltersUpdated: (filters: esFilters.Filter[]) => void;
onCancelApplyFilters: () => void;
- onApplyFilters: (filters: Filter[]) => void;
+ onApplyFilters: (filters: esFilters.Filter[]) => void;
onQuerySaved: (savedQuery: SavedQuery) => void;
onSavedQueryUpdated: (savedQuery: SavedQuery) => void;
onClearSavedQuery: () => void;
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx
index abf7b22a6e48c..64c7560947681 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx
@@ -48,7 +48,6 @@ import {
} from 'ui/state_management/app_state';
import { KbnUrl } from 'ui/url/kbn_url';
-import { Filter } from '@kbn/es-query';
import { IndexPattern } from 'ui/index_patterns';
import { IPrivate } from 'ui/private';
import { Query, SavedQuery } from 'src/legacy/core_plugins/data/public';
@@ -59,6 +58,7 @@ import { npStart } from 'ui/new_platform';
import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
import { extractTimeFilter, changeTimeFilter } from '../../../data/public';
import { start as data } from '../../../data/public/legacy';
+import { esFilters } from '../../../../../plugins/data/public';
import {
DashboardContainer,
@@ -514,7 +514,7 @@ export class DashboardAppController {
}
);
- $scope.$watch('appState.$newFilters', (filters: Filter[] = []) => {
+ $scope.$watch('appState.$newFilters', (filters: esFilters.Filter[] = []) => {
if (filters.length === 1) {
$scope.onApplyFilters(filters);
}
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts
index 7c1fc771de349..8ffabe5add1c3 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts
@@ -20,7 +20,6 @@
import { i18n } from '@kbn/i18n';
import _ from 'lodash';
-import { Filter } from '@kbn/es-query';
import { stateMonitorFactory, StateMonitor } from 'ui/state_management/state_monitor_factory';
import { Timefilter } from 'ui/timefilter';
import { AppStateClass as TAppStateClass } from 'ui/state_management/app_state';
@@ -29,6 +28,7 @@ import { Moment } from 'moment';
import { DashboardContainer } from 'src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public';
import { ViewMode } from '../../../../../../src/plugins/embeddable/public';
+import { esFilters } from '../../../../../../src/plugins/data/public';
import { Query } from '../../../data/public';
import { getAppStateDefaults, migrateAppState } from './lib';
@@ -50,7 +50,7 @@ export class DashboardStateManager {
public lastSavedDashboardFilters: {
timeTo?: string | Moment;
timeFrom?: string | Moment;
- filterBars: Filter[];
+ filterBars: esFilters.Filter[];
query: Query;
};
private stateDefaults: DashboardAppStateDefaults;
@@ -303,7 +303,7 @@ export class DashboardStateManager {
return this.savedDashboard.timeRestore;
}
- public getLastSavedFilterBars(): Filter[] {
+ public getLastSavedFilterBars(): esFilters.Filter[] {
return this.lastSavedDashboardFilters.filterBars;
}
@@ -461,7 +461,7 @@ export class DashboardStateManager {
* Applies the current filter state to the dashboard.
* @param filter An array of filter bar filters.
*/
- public applyFilters(query: Query, filters: Filter[]) {
+ public applyFilters(query: Query, filters: esFilters.Filter[]) {
this.appState.query = query;
this.savedDashboard.searchSource.setField('query', query);
this.savedDashboard.searchSource.setField('filter', filters);
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/lib/filter_utils.ts b/src/legacy/core_plugins/kibana/public/dashboard/lib/filter_utils.ts
index 1fd50081c58bd..19a0c32210737 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/lib/filter_utils.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/lib/filter_utils.ts
@@ -19,7 +19,7 @@
import _ from 'lodash';
import moment, { Moment } from 'moment';
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
/**
* @typedef {Object} QueryFilter
@@ -65,9 +65,9 @@ export class FilterUtils {
* @param filters {Array.}
* @returns {Array.}
*/
- public static cleanFiltersForComparison(filters: Filter[]) {
+ public static cleanFiltersForComparison(filters: esFilters.Filter[]) {
return _.map(filters, filter => {
- const f: Partial = _.omit(filter, ['$$hashKey', '$state']);
+ const f: Partial = _.omit(filter, ['$$hashKey', '$state']);
if (f.meta) {
// f.meta.value is the value displayed in the filter bar.
// It may also be loaded differently and shouldn't be used in this comparison.
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.test.ts
index 1f503ee675407..ae3edae3b85d6 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.test.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.test.ts
@@ -18,12 +18,12 @@
*/
import { moveFiltersToQuery, Pre600FilterQuery } from './move_filters_to_query';
-import { Filter, FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
-const filter: Filter = {
+const filter: esFilters.Filter = {
meta: { disabled: false, negate: false, alias: '' },
query: {},
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
};
const queryFilter: Pre600FilterQuery = {
@@ -38,7 +38,7 @@ test('Migrates an old filter query into the query field', () => {
expect(newSearchSource).toEqual({
filter: [
{
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: {
alias: '',
disabled: false,
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.ts b/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.ts
index 153bdeba9d35f..8522495b9dedb 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.ts
@@ -18,7 +18,7 @@
*/
import { Query } from 'src/legacy/core_plugins/data/public';
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
export interface Pre600FilterQuery {
// pre 6.0.0 global query:queryString:options were stored per dashboard and would
@@ -30,18 +30,18 @@ export interface Pre600FilterQuery {
export interface SearchSourcePre600 {
// I encountered at least one export from 7.0.0-alpha that was missing the filter property in here.
// The maps data in esarchives actually has it, but I don't know how/when they created it.
- filter?: Array;
+ filter?: Array;
}
export interface SearchSource730 {
- filter: Filter[];
+ filter: esFilters.Filter[];
query: Query;
highlightAll?: boolean;
version?: boolean;
}
-function isQueryFilter(filter: Filter | { query: unknown }): filter is Pre600FilterQuery {
- return filter.query && !(filter as Filter).meta;
+function isQueryFilter(filter: esFilters.Filter | { query: unknown }): filter is Pre600FilterQuery {
+ return filter.query && !(filter as esFilters.Filter).meta;
}
export function moveFiltersToQuery(
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.d.ts b/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.d.ts
index 1231ca28ed014..5b860b0a2cc7c 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.d.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.d.ts
@@ -19,10 +19,9 @@
import { SearchSource } from 'ui/courier';
import { SavedObject } from 'ui/saved_objects/saved_object';
-import moment from 'moment';
import { RefreshInterval } from 'src/plugins/data/public';
import { Query } from 'src/legacy/core_plugins/data/public';
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
export interface SavedObjectDashboard extends SavedObject {
id?: string;
@@ -41,5 +40,5 @@ export interface SavedObjectDashboard extends SavedObject {
destroy: () => void;
refreshInterval?: RefreshInterval;
getQuery(): Query;
- getFilters(): Filter[];
+ getFilters(): esFilters.Filter[];
}
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/types.ts b/src/legacy/core_plugins/kibana/public/dashboard/types.ts
index ccccc89004e36..5aaca7b62094f 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/types.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/types.ts
@@ -18,7 +18,6 @@
*/
import { AppState } from 'ui/state_management/app_state';
-import { Filter } from '@kbn/es-query';
import { Query } from 'src/legacy/core_plugins/data/public';
import { AppState as TAppState } from 'ui/state_management/app_state';
import { ViewMode } from 'src/plugins/embeddable/public';
@@ -30,6 +29,7 @@ import {
RawSavedDashboardPanel640To720,
RawSavedDashboardPanel730ToLatest,
} from './migrations/types';
+import { esFilters } from '../../../../../plugins/data/public';
export type NavAction = (anchorElement?: any) => void;
@@ -110,7 +110,7 @@ export interface DashboardAppStateParameters {
useMargins: boolean;
};
query: Query | string;
- filters: Filter[];
+ filters: esFilters.Filter[];
viewMode: ViewMode;
savedQuery?: string;
}
diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts
index 268f176f2c61e..3314bbbf189c4 100644
--- a/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts
@@ -17,7 +17,6 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { IndexPatterns, IndexPattern, getServices } from '../../../kibana_services';
import { reverseSortDir, SortDirection } from './utils/sorting';
import { extractNanos, convertIsoToMillis } from './utils/date_conversion';
@@ -25,6 +24,7 @@ import { fetchHitsInInterval } from './utils/fetch_hits_in_interval';
import { generateIntervals } from './utils/generate_intervals';
import { getEsQuerySearchAfter } from './utils/get_es_query_search_after';
import { getEsQuerySort } from './utils/get_es_query_sort';
+import { esFilters } from '../../../../../../../../plugins/data/public';
export type SurrDocType = 'successors' | 'predecessors';
export interface EsHitRecord {
@@ -67,7 +67,7 @@ function fetchContextProvider(indexPatterns: IndexPatterns) {
tieBreakerField: string,
sortDir: SortDirection,
size: number,
- filters: Filter[]
+ filters: esFilters.Filter[]
) {
if (typeof anchor !== 'object' || anchor === null) {
return [];
@@ -112,7 +112,7 @@ function fetchContextProvider(indexPatterns: IndexPatterns) {
return documents;
}
- async function createSearchSource(indexPattern: IndexPattern, filters: Filter[]) {
+ async function createSearchSource(indexPattern: IndexPattern, filters: esFilters.Filter[]) {
return new SearchSource()
.setParent(false)
.setField('index', indexPattern)
diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx
index 6ce987028c197..3edcda8c3bea9 100644
--- a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx
+++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx
@@ -34,7 +34,7 @@ export function ToolBarPagerButtons(props: Props) {
disabled={!props.hasPreviousPage}
data-test-subj="btnPrevPage"
>
-
+
-
+
);
diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_row.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_row.js
index 355d9defbb63d..6f5a94442e977 100644
--- a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_row.js
+++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_row.js
@@ -26,10 +26,10 @@ import { noWhiteSpace } from '../../../../../common/utils/no_white_space';
import openRowHtml from './table_row/open.html';
import detailsHtml from './table_row/details.html';
import { getServices } from '../../../kibana_services';
-import { disableFilter } from '@kbn/es-query';
import { dispatchRenderComplete } from '../../../../../../../../plugins/kibana_utils/public';
import cellTemplateHtml from '../components/table_row/cell.html';
import truncateByHeightTemplateHtml from '../components/table_row/truncate_by_height.html';
+import { esFilters } from '../../../../../../../../plugins/data/public';
const module = getServices().uiModules.get('app/discover');
@@ -117,7 +117,7 @@ module.directive('kbnTableRow', function ($compile, $httpParamSerializer, kbnUrl
const hash = $httpParamSerializer({
_a: rison.encode({
columns: $scope.columns,
- filters: ($scope.filters || []).map(disableFilter),
+ filters: ($scope.filters || []).map(esFilters.disableFilter),
}),
});
return `${path}?${hash}`;
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss
index 6960c7101fa10..fe13ac2fafa01 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss
@@ -27,3 +27,11 @@
padding-left: $euiSizeXS;
margin-left: $euiSizeXS;
}
+
+.dscFieldSearch__filterWrapper {
+ flex-grow: 0;
+}
+
+.dscFieldSearch__formWrapper {
+ padding: $euiSizeM;
+}
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.test.tsx b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.test.tsx
index 2655d28af985b..c207585499483 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.test.tsx
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.test.tsx
@@ -17,54 +17,123 @@
* under the License.
*/
import React from 'react';
+import { act } from 'react-dom/test-utils';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
// @ts-ignore
import { findTestSubject } from '@elastic/eui/lib/test';
-import { DiscoverFieldSearch } from './discover_field_search';
+import { DiscoverFieldSearch, Props } from './discover_field_search';
+import { EuiButtonGroupProps } from '@elastic/eui';
+import { ReactWrapper } from 'enzyme';
describe('DiscoverFieldSearch', () => {
- function mountComponent() {
- const props = {
- onChange: jest.fn(),
- onShowFilter: jest.fn(),
- showFilter: false,
- filtersActive: 0,
- value: 'test',
- };
- const comp = mountWithIntl( );
- const input = findTestSubject(comp, 'fieldFilterSearchInput');
- const btn = findTestSubject(comp, 'toggleFieldFilterButton');
- return { comp, input, btn, props };
+ const defaultProps = {
+ onChange: jest.fn(),
+ value: 'test',
+ types: ['any', 'string', '_source'],
+ };
+
+ function mountComponent(props?: Props) {
+ const compProps = props || defaultProps;
+ const comp = mountWithIntl( );
+ return comp;
+ }
+
+ function findButtonGroup(component: ReactWrapper, id: string) {
+ return component.find(`[data-test-subj="${id}ButtonGroup"]`).first();
}
test('enter value', () => {
- const { input, props } = mountComponent();
+ const component = mountComponent();
+ const input = findTestSubject(component, 'fieldFilterSearchInput');
input.simulate('change', { target: { value: 'new filter' } });
- expect(props.onChange).toBeCalledTimes(1);
+ expect(defaultProps.onChange).toBeCalledTimes(1);
});
- // this should work, but doesn't, have to do some research
- test('click toggle filter button', () => {
- const { btn, props } = mountComponent();
+ test('change in active filters should change facet selection and call onChange', () => {
+ const onChange = jest.fn();
+ const component = mountComponent({ ...defaultProps, ...{ onChange } });
+ let btn = findTestSubject(component, 'toggleFieldFilterButton');
+ expect(btn.hasClass('euiFacetButton--isSelected')).toBeFalsy();
btn.simulate('click');
- expect(props.onShowFilter).toBeCalledTimes(1);
+ const aggregatableButtonGroup = findButtonGroup(component, 'aggregatable');
+ act(() => {
+ // @ts-ignore
+ (aggregatableButtonGroup.props() as EuiButtonGroupProps).onChange('aggregatable-true', null);
+ });
+ component.update();
+ btn = findTestSubject(component, 'toggleFieldFilterButton');
+ expect(btn.hasClass('euiFacetButton--isSelected')).toBe(true);
+ expect(onChange).toBeCalledWith('aggregatable', true);
});
- test('change showFilter value should change aria label', () => {
- const { comp } = mountComponent();
- let btn = findTestSubject(comp, 'toggleFieldFilterButton');
- expect(btn.prop('aria-label')).toEqual('Show field filter settings');
- comp.setProps({ showFilter: true });
- btn = findTestSubject(comp, 'toggleFieldFilterButton');
- expect(btn.prop('aria-label')).toEqual('Hide field filter settings');
+ test('change in active filters should change filters count', () => {
+ const component = mountComponent();
+ let btn = findTestSubject(component, 'toggleFieldFilterButton');
+ btn.simulate('click');
+ btn = findTestSubject(component, 'toggleFieldFilterButton');
+ const badge = btn.find('.euiNotificationBadge');
+ // no active filters
+ expect(badge.text()).toEqual('0');
+ // change value of aggregatable select
+ const aggregatableButtonGroup = findButtonGroup(component, 'aggregatable');
+ act(() => {
+ // @ts-ignore
+ (aggregatableButtonGroup.props() as EuiButtonGroupProps).onChange('aggregatable-true', null);
+ });
+ component.update();
+ expect(badge.text()).toEqual('1');
+ // change value of searchable select
+ const searchableButtonGroup = findButtonGroup(component, 'searchable');
+ act(() => {
+ // @ts-ignore
+ (searchableButtonGroup.props() as EuiButtonGroupProps).onChange('searchable-true', null);
+ });
+ component.update();
+ expect(badge.text()).toEqual('2');
+ // change value of searchable select
+ act(() => {
+ // @ts-ignore
+ (searchableButtonGroup.props() as EuiButtonGroupProps).onChange('searchable-any', null);
+ });
+ component.update();
+ expect(badge.text()).toEqual('1');
});
- test('change filtersActive should change facet selection', () => {
- const { comp } = mountComponent();
- let btn = findTestSubject(comp, 'toggleFieldFilterButton');
- expect(btn.hasClass('euiFacetButton--isSelected')).toBeFalsy();
- comp.setProps({ filtersActive: 3 });
- btn = findTestSubject(comp, 'toggleFieldFilterButton');
- expect(btn.hasClass('euiFacetButton--isSelected')).toBe(true);
+ test('change in missing fields switch should not change filter count', () => {
+ const component = mountComponent();
+ const btn = findTestSubject(component, 'toggleFieldFilterButton');
+ btn.simulate('click');
+ const badge = btn.find('.euiNotificationBadge');
+ expect(badge.text()).toEqual('0');
+ const missingSwitch = findTestSubject(component, 'missingSwitch');
+ missingSwitch.simulate('change', { target: { value: false } });
+ expect(badge.text()).toEqual('0');
+ });
+
+ test('change in filters triggers onChange', () => {
+ const onChange = jest.fn();
+ const component = mountComponent({ ...defaultProps, ...{ onChange } });
+ const btn = findTestSubject(component, 'toggleFieldFilterButton');
+ btn.simulate('click');
+ const aggregtableButtonGroup = findButtonGroup(component, 'aggregatable');
+ const missingSwitch = findTestSubject(component, 'missingSwitch');
+ act(() => {
+ // @ts-ignore
+ (aggregtableButtonGroup.props() as EuiButtonGroupProps).onChange('aggregatable-true', null);
+ });
+ missingSwitch.simulate('change', { target: { value: false } });
+ expect(onChange).toBeCalledTimes(2);
+ });
+
+ test('change in type filters triggers onChange with appropriate value', () => {
+ const onChange = jest.fn();
+ const component = mountComponent({ ...defaultProps, ...{ onChange } });
+ const btn = findTestSubject(component, 'toggleFieldFilterButton');
+ btn.simulate('click');
+ const typeSelector = findTestSubject(component, 'typeSelect');
+ typeSelector.simulate('change', { target: { value: 'string' } });
+ expect(onChange).toBeCalledWith('type', 'string');
+ typeSelector.simulate('change', { target: { value: 'any' } });
+ expect(onChange).toBeCalledWith('type', 'any');
});
});
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.tsx b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.tsx
index f748cdae1b4fc..f0685c4357c5a 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.tsx
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.tsx
@@ -16,61 +16,234 @@
* specific language governing permissions and limitations
* under the License.
*/
-import React from 'react';
+import React, { OptionHTMLAttributes, ReactNode, useState } from 'react';
import { i18n } from '@kbn/i18n';
-import { EuiFacetButton, EuiFieldSearch, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui';
+import {
+ EuiFacetButton,
+ EuiFieldSearch,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiIcon,
+ EuiPopover,
+ EuiPopoverFooter,
+ EuiPopoverTitle,
+ EuiSelect,
+ EuiSwitch,
+ EuiForm,
+ EuiFormRow,
+ EuiButtonGroup,
+} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
+export interface State {
+ searchable: string;
+ aggregatable: string;
+ type: string;
+ missing: boolean;
+ [index: string]: string | boolean;
+}
+
export interface Props {
/**
* triggered on input of user into search field
*/
- onChange: (field: string, value: string) => void;
- /**
- * triggered when the "additional filter btn" is clicked
- */
- onShowFilter: () => void;
- /**
- * determines whether additional filter fields are displayed
- */
- showFilter: boolean;
+ onChange: (field: string, value: string | boolean | undefined) => void;
+
/**
* the input value of the user
*/
value?: string;
+
/**
- * the number of selected filters
+ * types for the type filter
*/
- filtersActive: number;
+ types: string[];
}
/**
* Component is Discover's side bar to search of available fields
* Additionally there's a button displayed that allows the user to show/hide more filter fields
*/
-export function DiscoverFieldSearch({
- showFilter,
- onChange,
- onShowFilter,
- value,
- filtersActive,
-}: Props) {
+export function DiscoverFieldSearch({ onChange, value, types }: Props) {
if (typeof value !== 'string') {
// at initial rendering value is undefined (angular related), this catches the warning
// should be removed once all is react
return null;
}
- const filterBtnAriaLabel = showFilter
+ const searchPlaceholder = i18n.translate('kbn.discover.fieldChooser.searchPlaceHolder', {
+ defaultMessage: 'Search field names',
+ });
+ const aggregatableLabel = i18n.translate('kbn.discover.fieldChooser.filter.aggregatableLabel', {
+ defaultMessage: 'Aggregatable',
+ });
+ const searchableLabel = i18n.translate('kbn.discover.fieldChooser.filter.searchableLabel', {
+ defaultMessage: 'Searchable',
+ });
+ const typeLabel = i18n.translate('kbn.discover.fieldChooser.filter.typeLabel', {
+ defaultMessage: 'Type',
+ });
+ const typeOptions = types
+ ? types.map(type => {
+ return { value: type, text: type };
+ })
+ : [{ value: 'any', text: 'any' }];
+
+ const [activeFiltersCount, setActiveFiltersCount] = useState(0);
+ const [isPopoverOpen, setPopoverOpen] = useState(false);
+ const [values, setValues] = useState({
+ searchable: 'any',
+ aggregatable: 'any',
+ type: 'any',
+ missing: true,
+ });
+
+ const filterBtnAriaLabel = isPopoverOpen
? i18n.translate('kbn.discover.fieldChooser.toggleFieldFilterButtonHideAriaLabel', {
defaultMessage: 'Hide field filter settings',
})
: i18n.translate('kbn.discover.fieldChooser.toggleFieldFilterButtonShowAriaLabel', {
defaultMessage: 'Show field filter settings',
});
- const searchPlaceholder = i18n.translate('kbn.discover.fieldChooser.searchPlaceHolder', {
- defaultMessage: 'Search fields',
- });
+ const handleFacetButtonClicked = () => {
+ setPopoverOpen(!isPopoverOpen);
+ };
+
+ const applyFilterValue = (id: string, filterValue: string | boolean) => {
+ switch (filterValue) {
+ case 'any':
+ if (id !== 'type') {
+ onChange(id, undefined);
+ } else {
+ onChange(id, filterValue);
+ }
+ break;
+ case 'true':
+ onChange(id, true);
+ break;
+ case 'false':
+ onChange(id, false);
+ break;
+ default:
+ onChange(id, filterValue);
+ }
+ };
+
+ const isFilterActive = (name: string, filterValue: string | boolean) => {
+ return name !== 'missing' && filterValue !== 'any';
+ };
+
+ const handleValueChange = (name: string, filterValue: string | boolean) => {
+ const previousValue = values[name];
+ updateFilterCount(name, previousValue, filterValue);
+ const updatedValues = { ...values };
+ updatedValues[name] = filterValue;
+ setValues(updatedValues);
+ applyFilterValue(name, filterValue);
+ };
+
+ const updateFilterCount = (
+ name: string,
+ previousValue: string | boolean,
+ currentValue: string | boolean
+ ) => {
+ const previouslyFilterActive = isFilterActive(name, previousValue);
+ const filterActive = isFilterActive(name, currentValue);
+ const diff = Number(filterActive) - Number(previouslyFilterActive);
+ setActiveFiltersCount(activeFiltersCount + diff);
+ };
+
+ const handleMissingChange = (e: React.ChangeEvent) => {
+ const missingValue = e.target.checked;
+ handleValueChange('missing', missingValue);
+ };
+
+ const buttonContent = (
+ }
+ isSelected={activeFiltersCount > 0}
+ quantity={activeFiltersCount}
+ onClick={handleFacetButtonClicked}
+ >
+
+
+ );
+
+ const select = (
+ id: string,
+ selectOptions: Array<{ text: ReactNode } & OptionHTMLAttributes>,
+ selectValue: string
+ ) => {
+ return (
+ ) =>
+ handleValueChange(id, e.target.value)
+ }
+ aria-label={i18n.translate('kbn.discover.fieldChooser.filter.fieldSelectorLabel', {
+ defaultMessage: 'Selection of {id} filter options',
+ values: { id },
+ })}
+ data-test-subj={`${id}Select`}
+ compressed
+ />
+ );
+ };
+
+ const toggleButtons = (id: string) => {
+ return [
+ {
+ id: `${id}-any`,
+ label: 'any',
+ },
+ {
+ id: `${id}-true`,
+ label: 'yes',
+ },
+ {
+ id: `${id}-false`,
+ label: 'no',
+ },
+ ];
+ };
+
+ const buttonGroup = (id: string, legend: string) => {
+ return (
+ handleValueChange(id, optionId.replace(`${id}-`, ''))}
+ buttonSize="compressed"
+ isFullWidth
+ data-test-subj={`${id}ButtonGroup`}
+ />
+ );
+ };
+
+ const selectionPanel = (
+
+
+
+ {buttonGroup('aggregatable', aggregatableLabel)}
+
+
+ {buttonGroup('searchable', searchableLabel)}
+
+
+ {select('type', typeOptions, values.type)}
+
+
+
+ );
return (
@@ -86,20 +259,35 @@ export function DiscoverFieldSearch({
/>
- }
- isSelected={filtersActive > 0}
- quantity={filtersActive}
- onClick={() => onShowFilter()}
- >
-
-
+
+ {}}
+ button={buttonContent}
+ >
+
+ {i18n.translate('kbn.discover.fieldChooser.filter.filterByTypeLabel', {
+ defaultMessage: 'Filter by type',
+ })}
+
+ {selectionPanel}
+
+
+
+
+
);
}
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search_directive.ts b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search_directive.ts
index 2e7dd3e210ef8..b78f993e18772 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search_directive.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search_directive.ts
@@ -27,9 +27,7 @@ const app = uiModules.get('apps/discover');
app.directive('discoverFieldSearch', function(reactDirective: any) {
return reactDirective(wrapInI18nContext(DiscoverFieldSearch), [
['onChange', { watchDepth: 'reference' }],
- ['onShowFilter', { watchDepth: 'reference' }],
- ['showFilter', { watchDepth: 'value' }],
['value', { watchDepth: 'value' }],
- ['filtersActive', { watchDepth: 'value' }],
+ ['types', { watchDepth: 'value' }],
]);
});
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.html b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.html
index 3d8b38c278f31..adf4b1b4326e8 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.html
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.html
@@ -9,10 +9,8 @@
0 ? savedObjectsResponse.saved_objects[0] : null;
+ const fields = indexPattern ? JSON.parse(indexPattern.attributes.fields) : null;
+ const field = fields ? fields.find((field) => field.name === fieldName) : fieldName;
+
const body = getBody(
{ field, query, boolFilter },
autocompleteTerminateAfter,
autocompleteTimeout
);
+
try {
const response = await callWithRequest(req, 'search', { index, body });
- const buckets = get(response, 'aggregations.suggestions.buckets') || [];
+ const buckets = get(response, 'aggregations.suggestions.buckets')
+ || get(response, 'aggregations.nestedSuggestions.suggestions.buckets')
+ || [];
const suggestions = map(buckets, 'key');
return suggestions;
} catch (error) {
@@ -55,7 +67,7 @@ function getBody({ field, query, boolFilter = [] }, terminateAfter, timeout) {
// the amount of information that needs to be transmitted to the coordinating node
const shardSize = 10;
- return {
+ const body = {
size: 0,
timeout: `${timeout}ms`,
terminate_after: terminateAfter,
@@ -67,7 +79,7 @@ function getBody({ field, query, boolFilter = [] }, terminateAfter, timeout) {
aggs: {
suggestions: {
terms: {
- field,
+ field: field.name || field,
include: `${getEscapedQuery(query)}.*`,
execution_hint: executionHint,
shard_size: shardSize,
@@ -75,6 +87,22 @@ function getBody({ field, query, boolFilter = [] }, terminateAfter, timeout) {
},
},
};
+
+ if (field.subType && field.subType.nested) {
+ return {
+ ...body,
+ aggs: {
+ nestedSuggestions: {
+ nested: {
+ path: field.subType.nested.path,
+ },
+ aggs: body.aggs,
+ },
+ }
+ };
+ }
+
+ return body;
}
function getEscapedQuery(query = '') {
diff --git a/src/legacy/core_plugins/kibana/server/tutorials/cockroachdb_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/cockroachdb_metrics/index.js
new file mode 100644
index 0000000000000..e05be3bda145f
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/server/tutorials/cockroachdb_metrics/index.js
@@ -0,0 +1,63 @@
+/*
+ * 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 { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
+import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
+
+export function cockroachdbMetricsSpecProvider(server, context) {
+ const moduleName = 'cockroachdb';
+ return {
+ id: 'cockroachdbMetrics',
+ name: i18n.translate('kbn.server.tutorials.cockroachdbMetrics.nameTitle', {
+ defaultMessage: 'CockroachDB metrics',
+ }),
+ category: TUTORIAL_CATEGORY.METRICS,
+ shortDescription: i18n.translate('kbn.server.tutorials.cockroachdbMetrics.shortDescription', {
+ defaultMessage: 'Fetch monitoring metrics from the CockroachDB server.',
+ }),
+ longDescription: i18n.translate('kbn.server.tutorials.cockroachdbMetrics.longDescription', {
+ defaultMessage: 'The `cockroachdb` Metricbeat module fetches monitoring metrics from CockroachDB. \
+[Learn more]({learnMoreLink}).',
+ values: {
+ learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-cockroachdb.html',
+ },
+ }),
+ euiIconType: '/plugins/kibana/home/tutorial_resources/logos/cockroachdb.svg',
+ artifacts: {
+ dashboards: [
+ {
+ id: 'e3ba0c30-9766-11e9-9eea-6f554992ec1f',
+ linkLabel: i18n.translate('kbn.server.tutorials.cockroachdbMetrics.artifacts.dashboards.linkLabel', {
+ defaultMessage: 'CockroachDB metrics dashboard',
+ }),
+ isOverview: true
+ }
+ ],
+ exportedFields: {
+ documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-cockroachdb.html'
+ }
+ },
+ completionTimeMinutes: 10,
+ previewImagePath: '/plugins/kibana/home/tutorial_resources/cockroachdb_metrics/screenshot.png',
+ onPrem: onPremInstructions(moduleName, null, null, null, context),
+ elasticCloud: cloudInstructions(moduleName),
+ onPremElasticCloud: onPremCloudInstructions(moduleName)
+ };
+}
diff --git a/src/legacy/core_plugins/kibana/server/tutorials/coredns_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/coredns_logs/index.js
index 69f31c623e5ef..ca308ac969e49 100644
--- a/src/legacy/core_plugins/kibana/server/tutorials/coredns_logs/index.js
+++ b/src/legacy/core_plugins/kibana/server/tutorials/coredns_logs/index.js
@@ -46,7 +46,7 @@ export function corednsLogsSpecProvider(server, context) {
learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-coredns.html',
},
}),
- //TODO: euiIconType: 'logoCoredns',
+ euiIconType: '/plugins/kibana/home/tutorial_resources/logos/coredns.svg',
artifacts: {
dashboards: [
{
diff --git a/src/legacy/core_plugins/kibana/server/tutorials/register.js b/src/legacy/core_plugins/kibana/server/tutorials/register.js
index 70bc0f4d3c9eb..a95baad4ccb65 100644
--- a/src/legacy/core_plugins/kibana/server/tutorials/register.js
+++ b/src/legacy/core_plugins/kibana/server/tutorials/register.js
@@ -78,6 +78,7 @@ import { envoyproxyLogsSpecProvider } from './envoyproxy_logs';
import { couchdbMetricsSpecProvider } from './couchdb_metrics';
import { emsBoundariesSpecProvider } from './ems';
import { consulMetricsSpecProvider } from './consul_metrics';
+import { cockroachdbMetricsSpecProvider } from './cockroachdb_metrics';
export function registerTutorials(server) {
server.registerTutorial(systemLogsSpecProvider);
@@ -141,4 +142,5 @@ export function registerTutorials(server) {
server.registerTutorial(couchdbMetricsSpecProvider);
server.registerTutorial(emsBoundariesSpecProvider);
server.registerTutorial(consulMetricsSpecProvider);
+ server.registerTutorial(cockroachdbMetricsSpecProvider);
}
diff --git a/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx
index 803119bdac119..4f8c5d11f1916 100644
--- a/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx
+++ b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx
@@ -29,7 +29,7 @@ jest.mock('ui/new_platform');
const dataShim = {
ui: {
- SearchBar: () =>
,
+ SearchBar: () =>
,
},
};
diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts
index 3271373449eb3..4b6566415f3e1 100644
--- a/src/legacy/core_plugins/telemetry/index.ts
+++ b/src/legacy/core_plugins/telemetry/index.ts
@@ -48,6 +48,9 @@ const telemetry = (kibana: any) => {
// `config` is used internally and not intended to be set
config: Joi.string().default(Joi.ref('$defaultConfigPath')),
banner: Joi.boolean().default(true),
+ lastVersionChecked: Joi.string()
+ .allow('')
+ .default(''),
url: Joi.when('$dev', {
is: true,
then: Joi.string().default(
@@ -77,7 +80,8 @@ const telemetry = (kibana: any) => {
},
},
async replaceInjectedVars(originalInjectedVars: any, request: any) {
- const telemetryOptedIn = await getTelemetryOptIn(request);
+ const currentKibanaVersion = getCurrentKibanaVersion(request.server);
+ const telemetryOptedIn = await getTelemetryOptIn({ request, currentKibanaVersion });
return {
...originalInjectedVars,
@@ -97,7 +101,13 @@ const telemetry = (kibana: any) => {
mappings,
},
init(server: Server) {
- const initializerContext = {} as PluginInitializerContext;
+ const initializerContext = {
+ env: {
+ packageInfo: {
+ version: getCurrentKibanaVersion(server),
+ },
+ },
+ } as PluginInitializerContext;
const coreSetup = ({
http: { server },
@@ -116,3 +126,7 @@ const telemetry = (kibana: any) => {
// eslint-disable-next-line import/no-default-export
export default telemetry;
+
+function getCurrentKibanaVersion(server: Server): string {
+ return server.config().get('pkg.version');
+}
diff --git a/src/legacy/core_plugins/telemetry/mappings.json b/src/legacy/core_plugins/telemetry/mappings.json
index d83f7f5967630..1245ef88f5892 100644
--- a/src/legacy/core_plugins/telemetry/mappings.json
+++ b/src/legacy/core_plugins/telemetry/mappings.json
@@ -3,6 +3,9 @@
"properties": {
"enabled": {
"type": "boolean"
+ },
+ "lastVersionChecked": {
+ "type": "keyword"
}
}
}
diff --git a/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.test.ts b/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.test.ts
new file mode 100644
index 0000000000000..67ad3aaae427d
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.test.ts
@@ -0,0 +1,214 @@
+/*
+ * 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 { getTelemetryOptIn } from './get_telemetry_opt_in';
+
+describe('get_telemetry_opt_in', () => {
+ it('returns false when request path is not /app*', async () => {
+ const params = getCallGetTelemetryOptInParams({
+ requestPath: '/foo/bar',
+ });
+
+ const result = await callGetTelemetryOptIn(params);
+
+ expect(result).toBe(false);
+ });
+
+ it('returns null when saved object not found', async () => {
+ const params = getCallGetTelemetryOptInParams({
+ savedObjectNotFound: true,
+ });
+
+ const result = await callGetTelemetryOptIn(params);
+
+ expect(result).toBe(null);
+ });
+
+ it('returns false when saved object forbidden', async () => {
+ const params = getCallGetTelemetryOptInParams({
+ savedObjectForbidden: true,
+ });
+
+ const result = await callGetTelemetryOptIn(params);
+
+ expect(result).toBe(false);
+ });
+
+ it('throws an error on unexpected saved object error', async () => {
+ const params = getCallGetTelemetryOptInParams({
+ savedObjectOtherError: true,
+ });
+
+ let threw = false;
+ try {
+ await callGetTelemetryOptIn(params);
+ } catch (err) {
+ threw = true;
+ expect(err.message).toBe(SavedObjectOtherErrorMessage);
+ }
+
+ expect(threw).toBe(true);
+ });
+
+ it('returns null if enabled is null or undefined', async () => {
+ for (const enabled of [null, undefined]) {
+ const params = getCallGetTelemetryOptInParams({
+ enabled,
+ });
+
+ const result = await callGetTelemetryOptIn(params);
+
+ expect(result).toBe(null);
+ }
+ });
+
+ it('returns true when enabled is true', async () => {
+ const params = getCallGetTelemetryOptInParams({
+ enabled: true,
+ });
+
+ const result = await callGetTelemetryOptIn(params);
+
+ expect(result).toBe(true);
+ });
+
+ // build a table of tests with version checks, with results for enabled false
+ type VersionCheckTable = Array>;
+
+ const EnabledFalseVersionChecks: VersionCheckTable = [
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '8.0.0', result: false },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '8.0.1', result: false },
+ { lastVersionChecked: '8.0.1', currentKibanaVersion: '8.0.0', result: false },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '8.1.0', result: null },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '9.0.0', result: null },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '7.0.0', result: false },
+ { lastVersionChecked: '8.1.0', currentKibanaVersion: '8.0.0', result: false },
+ { lastVersionChecked: '8.0.0-X', currentKibanaVersion: '8.0.0', result: false },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '8.0.0-X', result: false },
+ { lastVersionChecked: null, currentKibanaVersion: '8.0.0', result: null },
+ { lastVersionChecked: undefined, currentKibanaVersion: '8.0.0', result: null },
+ { lastVersionChecked: 5, currentKibanaVersion: '8.0.0', result: null },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: 'beta', result: null },
+ { lastVersionChecked: 'beta', currentKibanaVersion: '8.0.0', result: null },
+ { lastVersionChecked: 'beta', currentKibanaVersion: 'beta', result: false },
+ { lastVersionChecked: 'BETA', currentKibanaVersion: 'beta', result: null },
+ ].map(el => ({ ...el, enabled: false }));
+
+ // build a table of tests with version checks, with results for enabled true/null/undefined
+ const EnabledTrueVersionChecks: VersionCheckTable = EnabledFalseVersionChecks.map(el => ({
+ ...el,
+ enabled: true,
+ result: true,
+ }));
+
+ const EnabledNullVersionChecks: VersionCheckTable = EnabledFalseVersionChecks.map(el => ({
+ ...el,
+ enabled: null,
+ result: null,
+ }));
+
+ const EnabledUndefinedVersionChecks: VersionCheckTable = EnabledFalseVersionChecks.map(el => ({
+ ...el,
+ enabled: undefined,
+ result: null,
+ }));
+
+ const AllVersionChecks = [
+ ...EnabledFalseVersionChecks,
+ ...EnabledTrueVersionChecks,
+ ...EnabledNullVersionChecks,
+ ...EnabledUndefinedVersionChecks,
+ ];
+
+ test.each(AllVersionChecks)(
+ 'returns expected result for version check with %j',
+ async (params: Partial) => {
+ const result = await callGetTelemetryOptIn({ ...DefaultParams, ...params });
+ expect(result).toBe(params.result);
+ }
+ );
+});
+
+interface CallGetTelemetryOptInParams {
+ requestPath: string;
+ savedObjectNotFound: boolean;
+ savedObjectForbidden: boolean;
+ savedObjectOtherError: boolean;
+ enabled: boolean | null | undefined;
+ lastVersionChecked?: any; // should be a string, but test with non-strings
+ currentKibanaVersion: string;
+ result?: boolean | null;
+}
+
+const DefaultParams = {
+ requestPath: '/app/something',
+ savedObjectNotFound: false,
+ savedObjectForbidden: false,
+ savedObjectOtherError: false,
+ enabled: true,
+ lastVersionChecked: '8.0.0',
+ currentKibanaVersion: '8.0.0',
+};
+
+function getCallGetTelemetryOptInParams(
+ overrides: Partial
+): CallGetTelemetryOptInParams {
+ return { ...DefaultParams, ...overrides };
+}
+
+async function callGetTelemetryOptIn(params: CallGetTelemetryOptInParams): Promise {
+ const { currentKibanaVersion } = params;
+ const request = getMockRequest(params);
+ return await getTelemetryOptIn({ request, currentKibanaVersion });
+}
+
+function getMockRequest(params: CallGetTelemetryOptInParams): any {
+ return {
+ path: params.requestPath,
+ getSavedObjectsClient() {
+ return getMockSavedObjectsClient(params);
+ },
+ };
+}
+
+const SavedObjectNotFoundMessage = 'savedObjectNotFound';
+const SavedObjectForbiddenMessage = 'savedObjectForbidden';
+const SavedObjectOtherErrorMessage = 'savedObjectOtherError';
+
+function getMockSavedObjectsClient(params: CallGetTelemetryOptInParams) {
+ return {
+ async get(type: string, id: string) {
+ if (params.savedObjectNotFound) throw new Error(SavedObjectNotFoundMessage);
+ if (params.savedObjectForbidden) throw new Error(SavedObjectForbiddenMessage);
+ if (params.savedObjectOtherError) throw new Error(SavedObjectOtherErrorMessage);
+
+ const enabled = params.enabled;
+ const lastVersionChecked = params.lastVersionChecked;
+ return { attributes: { enabled, lastVersionChecked } };
+ },
+ errors: {
+ isNotFoundError(error: any) {
+ return error.message === SavedObjectNotFoundMessage;
+ },
+ isForbiddenError(error: any) {
+ return error.message === SavedObjectForbiddenMessage;
+ },
+ },
+ };
+}
diff --git a/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts
index 9b365d6dd7ae5..c8bd4a4b6dfbd 100644
--- a/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts
+++ b/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts
@@ -17,7 +17,21 @@
* under the License.
*/
-export async function getTelemetryOptIn(request: any) {
+import semver from 'semver';
+
+import { SavedObjectAttributes } from './routes/opt_in';
+
+interface GetTelemetryOptIn {
+ request: any;
+ currentKibanaVersion: string;
+}
+
+// Returns whether telemetry has been opt'ed into or not.
+// Returns null not set, meaning Kibana should prompt in the UI.
+export async function getTelemetryOptIn({
+ request,
+ currentKibanaVersion,
+}: GetTelemetryOptIn): Promise {
const isRequestingApplication = request.path.startsWith('/app');
// Prevent interstitial screens (such as the space selector) from prompting for telemetry
@@ -27,9 +41,9 @@ export async function getTelemetryOptIn(request: any) {
const savedObjectsClient = request.getSavedObjectsClient();
+ let savedObject;
try {
- const { attributes } = await savedObjectsClient.get('telemetry', 'telemetry');
- return attributes.enabled;
+ savedObject = await savedObjectsClient.get('telemetry', 'telemetry');
} catch (error) {
if (savedObjectsClient.errors.isNotFoundError(error)) {
return null;
@@ -43,4 +57,50 @@ export async function getTelemetryOptIn(request: any) {
throw error;
}
+
+ const { attributes }: { attributes: SavedObjectAttributes } = savedObject;
+
+ // if enabled is already null, return null
+ if (attributes.enabled == null) return null;
+
+ const enabled = !!attributes.enabled;
+
+ // if enabled is true, return it
+ if (enabled === true) return enabled;
+
+ // Additional check if they've already opted out (enabled: false):
+ // - if the Kibana version has changed by at least a minor version,
+ // return null to re-prompt.
+
+ const lastKibanaVersion = attributes.lastVersionChecked;
+
+ // if the last kibana version isn't set, or is somehow not a string, return null
+ if (typeof lastKibanaVersion !== 'string') return null;
+
+ // if version hasn't changed, just return enabled value
+ if (lastKibanaVersion === currentKibanaVersion) return enabled;
+
+ const lastSemver = parseSemver(lastKibanaVersion);
+ const currentSemver = parseSemver(currentKibanaVersion);
+
+ // if either version is invalid, return null
+ if (lastSemver == null || currentSemver == null) return null;
+
+ // actual major/minor version comparison, for cases when to return null
+ if (currentSemver.major > lastSemver.major) return null;
+ if (currentSemver.major === lastSemver.major) {
+ if (currentSemver.minor > lastSemver.minor) return null;
+ }
+
+ // current version X.Y is not greater than last version X.Y, return enabled
+ return enabled;
+}
+
+function parseSemver(version: string): semver.SemVer | null {
+ // semver functions both return nulls AND throw exceptions: "it depends!"
+ try {
+ return semver.parse(version);
+ } catch (err) {
+ return null;
+ }
}
diff --git a/src/legacy/core_plugins/telemetry/server/index.ts b/src/legacy/core_plugins/telemetry/server/index.ts
index b8ae5fc231fba..aa13fab9a5f81 100644
--- a/src/legacy/core_plugins/telemetry/server/index.ts
+++ b/src/legacy/core_plugins/telemetry/server/index.ts
@@ -25,5 +25,5 @@ export { getTelemetryOptIn } from './get_telemetry_opt_in';
export { telemetryCollectionManager } from './collection_manager';
export const telemetryPlugin = (initializerContext: PluginInitializerContext) =>
- new TelemetryPlugin();
+ new TelemetryPlugin(initializerContext);
export { constants };
diff --git a/src/legacy/core_plugins/telemetry/server/plugin.ts b/src/legacy/core_plugins/telemetry/server/plugin.ts
index 70de51b2abe99..a5f0f1234799a 100644
--- a/src/legacy/core_plugins/telemetry/server/plugin.ts
+++ b/src/legacy/core_plugins/telemetry/server/plugin.ts
@@ -17,14 +17,21 @@
* under the License.
*/
-import { CoreSetup } from 'src/core/server';
+import { CoreSetup, PluginInitializerContext } from 'src/core/server';
import { registerRoutes } from './routes';
import { telemetryCollectionManager } from './collection_manager';
import { getStats } from './telemetry_collection';
export class TelemetryPlugin {
+ private readonly currentKibanaVersion: string;
+
+ constructor(initializerContext: PluginInitializerContext) {
+ this.currentKibanaVersion = initializerContext.env.packageInfo.version;
+ }
+
public setup(core: CoreSetup) {
+ const currentKibanaVersion = this.currentKibanaVersion;
telemetryCollectionManager.setStatsGetter(getStats, 'local');
- registerRoutes(core);
+ registerRoutes({ core, currentKibanaVersion });
}
}
diff --git a/src/legacy/core_plugins/telemetry/server/routes/index.ts b/src/legacy/core_plugins/telemetry/server/routes/index.ts
index 12ba541d699f9..2eb6bf95b4f45 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/index.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/index.ts
@@ -21,7 +21,12 @@ import { CoreSetup } from 'src/core/server';
import { registerOptInRoutes } from './opt_in';
import { registerTelemetryDataRoutes } from './telemetry_stats';
-export function registerRoutes(core: CoreSetup) {
- registerOptInRoutes(core);
+interface RegisterRoutesParams {
+ core: CoreSetup;
+ currentKibanaVersion: string;
+}
+
+export function registerRoutes({ core, currentKibanaVersion }: RegisterRoutesParams) {
+ registerOptInRoutes({ core, currentKibanaVersion });
registerTelemetryDataRoutes(core);
}
diff --git a/src/legacy/core_plugins/telemetry/server/routes/opt_in.ts b/src/legacy/core_plugins/telemetry/server/routes/opt_in.ts
index aabc0259f08fc..3a7194890b570 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/opt_in.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/opt_in.ts
@@ -21,7 +21,17 @@ import Joi from 'joi';
import { boomify } from 'boom';
import { CoreSetup } from 'src/core/server';
-export function registerOptInRoutes(core: CoreSetup) {
+interface RegisterOptInRoutesParams {
+ core: CoreSetup;
+ currentKibanaVersion: string;
+}
+
+export interface SavedObjectAttributes {
+ enabled?: boolean;
+ lastVersionChecked: string;
+}
+
+export function registerOptInRoutes({ core, currentKibanaVersion }: RegisterOptInRoutesParams) {
const { server } = core.http as any;
server.route({
@@ -36,17 +46,16 @@ export function registerOptInRoutes(core: CoreSetup) {
},
handler: async (req: any, h: any) => {
const savedObjectsClient = req.getSavedObjectsClient();
+ const savedObject: SavedObjectAttributes = {
+ enabled: req.payload.enabled,
+ lastVersionChecked: currentKibanaVersion,
+ };
+ const options = {
+ id: 'telemetry',
+ overwrite: true,
+ };
try {
- await savedObjectsClient.create(
- 'telemetry',
- {
- enabled: req.payload.enabled,
- },
- {
- id: 'telemetry',
- overwrite: true,
- }
- );
+ await savedObjectsClient.create('telemetry', savedObject, options);
} catch (err) {
return boomify(err);
}
diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js
index 5b8bb07577510..ca798b6bf2470 100644
--- a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js
+++ b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js
@@ -21,9 +21,8 @@ import { get } from 'lodash';
import { GeohashLayer } from './geohash_layer';
import { BaseMapsVisualizationProvider } from './base_maps_visualization';
import { TileMapTooltipFormatterProvider } from './editors/_tooltip_formatter';
+import { npStart } from 'ui/new_platform';
import { getFormat } from '../../../ui/public/visualize/loader/pipeline_helpers/utilities';
-import { start as data } from '../../../core_plugins/data/public/legacy';
-const filterManager = data.filter.filterManager;
export const createTileMapVisualization = ({ serviceSettings, $injector }) => {
const BaseMapsVisualization = new BaseMapsVisualizationProvider(serviceSettings);
@@ -189,6 +188,7 @@ export const createTileMapVisualization = ({ serviceSettings, $injector }) => {
filter[filterName] = { ignore_unmapped: true };
filter[filterName][field] = filterData;
+ const { filterManager } = npStart.plugins.data.query;
filterManager.addFilters([filter]);
this.vis.updateState();
diff --git a/src/legacy/core_plugins/timelion/public/vis/timelion_request_handler.ts b/src/legacy/core_plugins/timelion/public/vis/timelion_request_handler.ts
index eb4fb3f397149..156c06a605528 100644
--- a/src/legacy/core_plugins/timelion/public/vis/timelion_request_handler.ts
+++ b/src/legacy/core_plugins/timelion/public/vis/timelion_request_handler.ts
@@ -18,12 +18,12 @@
*/
// @ts-ignore
-import { buildEsQuery, getEsQueryConfig, Filter } from '@kbn/es-query';
+import { buildEsQuery, getEsQueryConfig } from '@kbn/es-query';
// @ts-ignore
import { timezoneProvider } from 'ui/vis/lib/timezone';
import { KIBANA_CONTEXT_NAME } from 'src/plugins/expressions/public';
import { Query } from 'src/legacy/core_plugins/data/public';
-import { TimeRange } from 'src/plugins/data/public';
+import { TimeRange, esFilters } from 'src/plugins/data/public';
import { VisParams } from 'ui/vis';
import { i18n } from '@kbn/i18n';
import { TimelionVisualizationDependencies } from '../plugin';
@@ -60,7 +60,7 @@ export function getTimelionRequestHandler(dependencies: TimelionVisualizationDep
visParams,
}: {
timeRange: TimeRange;
- filters: Filter[];
+ filters: esFilters.Filter[];
query: Query;
visParams: VisParams;
forceFetch?: boolean;
diff --git a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts
index 63adccb3e02b0..7310ee5b5f172 100644
--- a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts
+++ b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts
@@ -47,14 +47,20 @@ interface AnalyicsReporterConfig {
}
export function createAnalyticsReporter(config: AnalyicsReporterConfig) {
- const { localStorage, basePath, $http, debug } = config;
+ const { localStorage, basePath, debug } = config;
return createReporter({
debug,
storage: localStorage,
async http(report) {
const url = `${basePath}/api/telemetry/report`;
- await $http.post(url, { report });
+ await fetch(url, {
+ method: 'POST',
+ headers: {
+ 'kbn-xsrf': 'true',
+ },
+ body: JSON.stringify({ report }),
+ });
},
});
}
diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts
index 89f74ef4b53e9..3b2e503a01e38 100644
--- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts
+++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts
@@ -171,7 +171,7 @@ export const createMetricVisFn = (): ExpressionFunction<
throw new Error('colorRange must be provided when using percentage');
}
- const fontSize = Number.parseInt(args.font.spec.fontSize, 10);
+ const fontSize = Number.parseInt(args.font.spec.fontSize || '', 10);
return {
type: 'render',
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js
index 3497a35f5c99d..842d3aa6c4ad7 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js
@@ -32,10 +32,10 @@ import { fetchFields } from '../lib/fetch_fields';
import { extractIndexPatterns } from '../../common/extract_index_patterns';
import { npStart } from 'ui/new_platform';
-import { Storage } from 'ui/storage';
+
import { CoreStartContextProvider } from '../contexts/query_input_bar_context';
import { KibanaContextProvider } from '../../../../../plugins/kibana_react/public';
-const localStorage = new Storage(window.localStorage);
+import { Storage } from '../../../../../plugins/kibana_utils/public';
import { timefilter } from 'ui/timefilter';
const VIS_STATE_DEBOUNCE_DELAY = 200;
@@ -46,6 +46,7 @@ export class VisEditor extends Component {
super(props);
const { vis } = props;
this.appState = vis.API.getAppState();
+ this.localStorage = new Storage(window.localStorage);
this.state = {
model: props.visParams,
dirty: false,
@@ -63,7 +64,7 @@ export class VisEditor extends Component {
appName: APP_NAME,
uiSettings: npStart.core.uiSettings,
savedObjectsClient: npStart.core.savedObjects.client,
- store: localStorage,
+ store: this.localStorage,
};
}
@@ -169,7 +170,7 @@ export class VisEditor extends Component {
{
+ this._subscription = this._handler.handler.data$.subscribe(data => {
this.setPanelInterval(data.visData);
onDataChange(data);
});
@@ -152,10 +150,12 @@ class VisEditorVisualizationUI extends Component {
this._loadVisualization();
}
- componentDidUpdate(prevProps) {
- if (this._handler && !isEqual(this.props.timeRange, prevProps.timeRange)) {
- this._handler.update({
+ componentDidUpdate() {
+ if (this._handler) {
+ this._handler.updateInput({
timeRange: this.props.timeRange,
+ filters: this.props.filters || [],
+ query: this.props.query,
});
}
}
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor_visualization.test.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor_visualization.test.js
deleted file mode 100644
index e60626f8fbf0a..0000000000000
--- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor_visualization.test.js
+++ /dev/null
@@ -1,71 +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.
- */
-
-jest.mock('ui/visualize/loader/visualize_loader', () => ({}));
-
-jest.mock('ui/new_platform');
-
-import React from 'react';
-import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { VisEditorVisualization } from './vis_editor_visualization';
-
-describe('getVisualizeLoader', () => {
- let updateStub;
-
- beforeEach(() => {
- updateStub = jest.fn();
- const handlerMock = {
- update: updateStub,
- data$: {
- subscribe: () => {},
- },
- };
- const loaderMock = {
- embedVisualizationWithSavedObject: () => handlerMock,
- };
- require('ui/visualize/loader/visualize_loader').getVisualizeLoader = async () => loaderMock;
- });
-
- it('should not call _handler.update until getVisualizeLoader returns _handler', async () => {
- const wrapper = mountWithIntl( );
-
- // Set prop to force DOM change and componentDidUpdate to be triggered
- wrapper.setProps({
- timeRange: {
- from: '2019-03-20T20:35:37.637Z',
- to: '2019-03-23T18:40:16.486Z',
- },
- });
-
- expect(updateStub).not.toHaveBeenCalled();
-
- // Ensure all promises resolve
- await new Promise(resolve => process.nextTick(resolve));
-
- // Set prop to force DOM change and componentDidUpdate to be triggered
- wrapper.setProps({
- timeRange: {
- from: 'now/d',
- to: 'now/d',
- },
- });
-
- expect(updateStub).toHaveBeenCalled();
- });
-});
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/contexts/query_input_bar_context.ts b/src/legacy/core_plugins/vis_type_timeseries/public/contexts/query_input_bar_context.ts
index 19519571f1ab0..925b483905d01 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/contexts/query_input_bar_context.ts
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/contexts/query_input_bar_context.ts
@@ -18,14 +18,14 @@
*/
import React from 'react';
-import { Storage } from 'ui/storage';
import { UiSettingsClientContract, SavedObjectsClientContract } from 'src/core/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
export interface ICoreStartContext {
appName: string;
uiSettings: UiSettingsClientContract;
savedObjectsClient: SavedObjectsClientContract;
- store: Storage;
+ storage: IStorageWrapper;
}
export const CoreStartContext = React.createContext(null);
diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_index_pattern_service.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_index_pattern_service.js
index 0766e6a48765f..54e90ab7dd9b7 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_index_pattern_service.js
+++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_index_pattern_service.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import { IndexPatternsService } from '../../../../server/index_patterns/service';
+import { IndexPatternsFetcher } from '../../../../../plugins/data/server/';
export const getIndexPatternService = {
assign: 'indexPatternsService',
method(req) {
@@ -25,6 +25,6 @@ export const getIndexPatternService = {
const callDataCluster = (...args) => {
return dataCluster.callWithRequest(req, ...args);
};
- return new IndexPatternsService(callDataCluster);
+ return new IndexPatternsFetcher(callDataCluster);
},
};
diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts b/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts
index 22a71bd999d54..b4c32f37eb90c 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts
+++ b/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+
import { timefilter } from 'ui/timefilter';
import { TimeRange } from 'src/plugins/data/public';
import { Query } from 'src/legacy/core_plugins/data/public';
-
-// @ts-ignore
import { buildEsQuery, getEsQueryConfig } from '@kbn/es-query';
+
+import { esFilters } from '../../../../plugins/data/public';
+
// @ts-ignore
import { VegaParser } from './data_model/vega_parser';
// @ts-ignore
@@ -35,7 +36,7 @@ import { VisParams } from './vega_fn';
interface VegaRequestHandlerParams {
query: Query;
- filters: Filter;
+ filters: esFilters.Filter;
timeRange: TimeRange;
visParams: VisParams;
}
diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js
index ec898080c581e..5abb99e9bf716 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js
+++ b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js
@@ -27,7 +27,7 @@ import { Utils } from '../data_model/utils';
import { VISUALIZATION_COLORS } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { TooltipHandler } from './vega_tooltip';
-import { buildQueryFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../plugins/data/public';
import { getEnableExternalUrls } from '../helpers/vega_config_provider';
@@ -263,7 +263,7 @@ export class VegaBaseView {
*/
async addFilterHandler(query, index) {
const indexId = await this._findIndex(index);
- const filter = buildQueryFilter(query, indexId);
+ const filter = esFilters.buildQueryFilter(query, indexId);
this._queryfilter.addFilters(filter);
}
@@ -274,7 +274,7 @@ export class VegaBaseView {
async removeFilterHandler(query, index) {
const $injector = await chrome.dangerouslyGetActiveInjector();
const indexId = await this._findIndex(index);
- const filter = buildQueryFilter(query, indexId);
+ const filter = esFilters.buildQueryFilter(query, indexId);
// This is a workaround for the https://github.com/elastic/kibana/issues/18863
// Once fixed, replace with a direct call (no await is needed because its not async)
diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js
index 1dc73d6f9ff20..7aa60bb0cc469 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js
+++ b/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js
@@ -23,6 +23,7 @@ import { VegaView } from './vega_view/vega_view';
import { VegaMapView } from './vega_view/vega_map_view';
import { timefilter } from 'ui/timefilter';
import { start as data } from '../../../core_plugins/data/public/legacy';
+import { npStart } from 'ui/new_platform';
import { findIndexPatternByTitle } from '../../data/public/index_patterns';
@@ -99,11 +100,12 @@ export const createVegaVisualization = ({ serviceSettings }) => class VegaVisual
this._vegaView = null;
}
+ const { filterManager } = npStart.plugins.data.query;
const vegaViewParams = {
parentEl: this._el,
vegaParser,
serviceSettings,
- queryfilter: data.filter.filterManager,
+ queryfilter: filterManager,
timefilter: timefilter,
findIndex: this.findIndex.bind(this),
};
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts
index 5dc0e452eea56..5d7ab12a677cf 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts
@@ -42,6 +42,7 @@ const createSetupContract = (): VisualizationsSetup => ({
types: {
registerVisualization: jest.fn(),
registerAlias: jest.fn(),
+ hideTypes: jest.fn(),
},
});
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/types/types_service.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/types/types_service.ts
index 1556c3716de1a..e0d26e3405048 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/types/types_service.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/types/types_service.ts
@@ -48,16 +48,30 @@ export interface VisType {
*/
export class TypesService {
private types: Record = {};
+ private unregisteredHiddenTypes: string[] = [];
public setup() {
return {
registerVisualization: (registerFn: () => VisType) => {
const visDefinition = registerFn();
+ if (this.unregisteredHiddenTypes.includes(visDefinition.name)) {
+ visDefinition.hidden = true;
+ }
+
if (this.types[visDefinition.name]) {
throw new Error('type already exists!');
}
this.types[visDefinition.name] = visDefinition;
},
registerAlias: visTypeAliasRegistry.add,
+ hideTypes: (typeNames: string[]) => {
+ typeNames.forEach((name: string) => {
+ if (this.types[name]) {
+ this.types[name].hidden = true;
+ } else {
+ this.unregisteredHiddenTypes.push(name);
+ }
+ });
+ },
};
}
diff --git a/src/legacy/server/index_patterns/index.ts b/src/legacy/server/index_patterns/index.ts
index eea8a4a998e2d..75d0038cf9023 100644
--- a/src/legacy/server/index_patterns/index.ts
+++ b/src/legacy/server/index_patterns/index.ts
@@ -17,7 +17,9 @@
* under the License.
*/
-// @ts-ignore no types
export { indexPatternsMixin } from './mixin';
-export { IndexPatternsService, FieldDescriptor } from './service';
+export {
+ IndexPatternsFetcher,
+ FieldDescriptor,
+} from '../../../plugins/data/server/index_patterns/fetcher';
export { IndexPatternsServiceFactory } from './mixin';
diff --git a/src/legacy/server/index_patterns/mixin.ts b/src/legacy/server/index_patterns/mixin.ts
index a7180d6a2d70e..6b04c3842007b 100644
--- a/src/legacy/server/index_patterns/mixin.ts
+++ b/src/legacy/server/index_patterns/mixin.ts
@@ -17,11 +17,10 @@
* under the License.
*/
-import { IndexPatternsService } from './service';
+import { IndexPatternsFetcher } from '../../../plugins/data/server';
import KbnServer from '../kbn_server';
import { APICaller, CallAPIOptions } from '../../../core/server';
import { Legacy } from '../../../../kibana';
-import { registerRoutes } from './routes';
export function indexPatternsMixin(kbnServer: KbnServer, server: Legacy.Server) {
/**
@@ -31,7 +30,7 @@ export function indexPatternsMixin(kbnServer: KbnServer, server: Legacy.Server)
* @type {IndexPatternsService}
*/
server.decorate('server', 'indexPatternsServiceFactory', ({ callCluster }) => {
- return new IndexPatternsService(callCluster);
+ return new IndexPatternsFetcher(callCluster);
});
/**
@@ -50,10 +49,8 @@ export function indexPatternsMixin(kbnServer: KbnServer, server: Legacy.Server)
) => callWithRequest(request, endpoint, params, options);
return server.indexPatternsServiceFactory({ callCluster });
});
-
- registerRoutes(kbnServer.newPlatform.setup.core);
}
export type IndexPatternsServiceFactory = (args: {
callCluster: (endpoint: string, clientParams: any, options: any) => Promise;
-}) => IndexPatternsService;
+}) => IndexPatternsFetcher;
diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts
index e7f2f4c85435f..9cc4e30d4252d 100644
--- a/src/legacy/server/kbn_server.d.ts
+++ b/src/legacy/server/kbn_server.d.ts
@@ -150,5 +150,5 @@ export default class KbnServer {
export { Server, Request, ResponseToolkit } from 'hapi';
// Re-export commonly accessed api types.
-export { IndexPatternsService } from './index_patterns';
+export { IndexPatternsFetcher as IndexPatternsService } from './index_patterns';
export { SavedObjectsLegacyService, SavedObjectsClient } from 'src/core/server';
diff --git a/src/legacy/server/sample_data/data_sets/ecommerce/saved_objects.js b/src/legacy/server/sample_data/data_sets/ecommerce/saved_objects.js
index 87a1f1c9ece47..da44cc618eedd 100644
--- a/src/legacy/server/sample_data/data_sets/ecommerce/saved_objects.js
+++ b/src/legacy/server/sample_data/data_sets/ecommerce/saved_objects.js
@@ -269,7 +269,7 @@ export const getSavedObjects = () => [
"attributes": {
"title": "kibana_sample_data_ecommerce",
"timeFieldName": "order_date",
- "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"category\",\"subType\":\"multi\"},{\"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},{\"name\":\"customer_first_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"customer_first_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"customer_first_name\",\"subType\":\"multi\"},{\"name\":\"customer_full_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"customer_full_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"customer_full_name\",\"subType\":\"multi\"},{\"name\":\"customer_gender\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"customer_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"customer_last_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"customer_last_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"customer_last_name\",\"subType\":\"multi\"},{\"name\":\"customer_phone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"day_of_week\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"day_of_week_i\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"manufacturer\",\"subType\":\"multi\"},{\"name\":\"order_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"order_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products._id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products._id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"products._id\",\"subType\":\"multi\"},{\"name\":\"products.base_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.base_unit_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"products.category\",\"subType\":\"multi\"},{\"name\":\"products.created_on\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.discount_percentage\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products.manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"products.manufacturer\",\"subType\":\"multi\"},{\"name\":\"products.min_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.product_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.product_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products.product_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"products.product_name\",\"subType\":\"multi\"},{\"name\":\"products.quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.tax_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.taxful_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.taxless_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.unit_discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"taxful_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"taxless_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"total_quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"total_unique_products\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]",
+ "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"category\"}}},{\"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},{\"name\":\"customer_first_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"customer_first_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"customer_first_name\"}}},{\"name\":\"customer_full_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"customer_full_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"customer_full_name\"}}},{\"name\":\"customer_gender\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"customer_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"customer_last_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"customer_last_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"customer_last_name\"}}},{\"name\":\"customer_phone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"day_of_week\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"day_of_week_i\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"manufacturer\"}}},{\"name\":\"order_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"order_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products._id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products._id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"products._id\"}}},{\"name\":\"products.base_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.base_unit_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"products.category\"}}},{\"name\":\"products.created_on\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.discount_percentage\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products.manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"products.manufacturer\"}}},{\"name\":\"products.min_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.product_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.product_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products.product_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"products.product_name\"}}},{\"name\":\"products.quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.tax_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.taxful_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.taxless_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.unit_discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"taxful_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"taxless_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"total_quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"total_unique_products\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]",
"fieldFormatMap": "{\"taxful_total_price\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.[00]\"}}}"
}
},
diff --git a/src/legacy/server/sample_data/data_sets/logs/saved_objects.js b/src/legacy/server/sample_data/data_sets/logs/saved_objects.js
index 234436349b02f..522f43d107b24 100644
--- a/src/legacy/server/sample_data/data_sets/logs/saved_objects.js
+++ b/src/legacy/server/sample_data/data_sets/logs/saved_objects.js
@@ -241,7 +241,7 @@ export const getSavedObjects = () => [
"attributes": {
"title": "kibana_sample_data_logs",
"timeFieldName": "timestamp",
- "fields": "[{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"agent\",\"subType\":\"multi\"},{\"name\":\"bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.dataset\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"extension\",\"subType\":\"multi\"},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"host\",\"subType\":\"multi\"},{\"name\":\"index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"index\",\"subType\":\"multi\"},{\"name\":\"ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"machine.os\",\"subType\":\"multi\"},{\"name\":\"machine.ram\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"message.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"message\",\"subType\":\"multi\"},{\"name\":\"phpmemory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"request\",\"subType\":\"multi\"},{\"name\":\"response\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"response\",\"subType\":\"multi\"},{\"name\":\"tags\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"tags.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"tags\",\"subType\":\"multi\"},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"parent\":\"url\",\"subType\":\"multi\"},{\"name\":\"utc_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hour_of_day\",\"type\":\"number\",\"count\":0,\"scripted\":true,\"script\":\"doc['timestamp'].value.getHour()\",\"lang\":\"painless\",\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false}]",
+ "fields": "[{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"agent\"}}},{\"name\":\"bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.dataset\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"extension\"}}},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"host\"}}},{\"name\":\"index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"index\"}}},{\"name\":\"ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"machine.os\"}}},{\"name\":\"machine.ram\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"message.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"message\"}}},{\"name\":\"phpmemory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"request\"}}},{\"name\":\"response\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"response\"}}},{\"name\":\"tags\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"tags.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"tags\"}}},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\": \"url\"}}},{\"name\":\"utc_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hour_of_day\",\"type\":\"number\",\"count\":0,\"scripted\":true,\"script\":\"doc['timestamp'].value.getHour()\",\"lang\":\"painless\",\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false}]",
"fieldFormatMap": "{\"hour_of_day\":{}}"
}
},
diff --git a/src/legacy/server/usage/README.md b/src/legacy/server/usage/README.md
index ad1bb822b70cd..5c4bcc05bbc38 100644
--- a/src/legacy/server/usage/README.md
+++ b/src/legacy/server/usage/README.md
@@ -90,5 +90,3 @@ There are a few ways you can test that your usage collector is working properly.
Yes. When you talk to the Platform team about new fields being added, point out specifically which properties will have dynamic inner fields.
5. **If I accumulate an event counter in server memory, which my fetch method returns, won't it reset when the Kibana server restarts?**
Yes, but that is not a major concern. A visualization on such info might be a date histogram that gets events-per-second or something, which would be impacted by server restarts, so we'll have to offset the beginning of the time range when we detect that the latest metric is smaller than the earliest metric. That would be a pretty custom visualization, but perhaps future Kibana enhancements will be able to support that.
-6. **Who can I talk to with more questions?**
- The Kibana Platform team is the owner of the telemetry service. You can bring questions to them. You can also talk to Tim Sullivan, who created the Kibana telemetry service, or Chris Earle, who set up the telemetry cluster and AWS Lambas for the upstream prod and staging endpoints that recieve the data sent from end-user browsers.
diff --git a/src/legacy/ui/public/agg_types/__tests__/agg_param_writer.js b/src/legacy/ui/public/agg_types/__tests__/agg_param_writer.js
deleted file mode 100644
index c85899ca5704e..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/agg_param_writer.js
+++ /dev/null
@@ -1,103 +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 _ from 'lodash';
-import { VisProvider } from '../../vis';
-import { aggTypes } from '..';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import { AggGroupNames } from '../../vis/editors/default/agg_groups';
-
-// eslint-disable-next-line import/no-default-export
-export default function AggParamWriterHelper(Private) {
- const Vis = Private(VisProvider);
- const stubbedLogstashIndexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
-
- /**
- * Helper object for writing aggParams. Specify an aggType and it will find a vis & schema, and
- * wire up the supporting objects required to feed in parameters, and get #write() output.
- *
- * Use cases:
- * - Verify that the interval parameter of the histogram visualization casts its input to a number
- * ```js
- * it('casts to a number', function () {
- * let writer = new AggParamWriter({ aggType: 'histogram' });
- * let output = writer.write({ interval : '100/10' });
- * expect(output.params.interval).to.be.a('number');
- * expect(output.params.interval).to.be(100);
- * });
- * ```
- *
- * @class AggParamWriter
- * @param {object} opts - describe the properties of this paramWriter
- * @param {string} opts.aggType - the name of the aggType we want to test. ('histogram', 'filter', etc.)
- */
- class AggParamWriter {
-
- constructor(opts) {
- this.aggType = opts.aggType;
- if (_.isString(this.aggType)) {
- this.aggType = aggTypes.buckets.find(agg => agg.name === this.aggType) || aggTypes.metrics.find(agg => agg.name === this.aggType);
- }
-
- // not configurable right now, but totally required
- this.indexPattern = stubbedLogstashIndexPattern;
-
- // the schema that the aggType satisfies
- this.visAggSchema = null;
-
- this.vis = new Vis(this.indexPattern, {
- type: 'histogram',
- aggs: [{
- id: 1,
- type: this.aggType.name,
- params: {}
- }]
- });
- }
-
- write(paramValues, modifyAggConfig = null) {
- paramValues = _.clone(paramValues);
-
- if (this.aggType.paramByName('field') && !paramValues.field) {
- // pick a field rather than force a field to be specified everywhere
- if (this.aggType.type === AggGroupNames.Metrics) {
- paramValues.field = _.sample(this.indexPattern.fields.getByType('number'));
- } else {
- const type = this.aggType.paramByName('field').filterFieldTypes || 'string';
- let field;
- do {
- field = _.sample(this.indexPattern.fields.getByType(type));
- } while (!field.aggregatable);
- paramValues.field = field.name;
- }
- }
-
- const aggConfig = this.vis.aggs.aggs[0];
- aggConfig.setParams(paramValues);
-
- if (modifyAggConfig) {
- modifyAggConfig(aggConfig);
- }
-
- return aggConfig.write(this.vis.aggs);
- }
- }
-
- return AggParamWriter;
-}
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/_date_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/_date_range.js
deleted file mode 100644
index 94603dfa69a66..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/_date_range.js
+++ /dev/null
@@ -1,80 +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 { set } from 'lodash';
-import expect from '@kbn/expect';
-import sinon from 'sinon';
-import ngMock from 'ng_mock';
-import { aggTypes } from '../..';
-import AggParamWriterProvider from '../agg_param_writer';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import chrome from '../../../chrome';
-
-const config = chrome.getUiSettingsClient();
-
-describe('date_range params', function () {
- let paramWriter;
- let timeField;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- const AggParamWriter = Private(AggParamWriterProvider);
- const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
-
- timeField = indexPattern.timeFieldName;
- paramWriter = new AggParamWriter({ aggType: 'date_range' });
- }));
-
- describe('getKey', () => {
- const dateRange = aggTypes.buckets.find(agg => agg.name === 'date_range');
- it('should return object', () => {
- const bucket = { from: 'from-date', to: 'to-date', key: 'from-dateto-date' };
- expect(dateRange.getKey(bucket)).to.equal({ from: 'from-date', to: 'to-date' });
- });
- });
-
- describe('time_zone', () => {
- beforeEach(() => {
- sinon.stub(config, 'get');
- sinon.stub(config, 'isDefault');
- });
-
- it('should use the specified time_zone', () => {
- const output = paramWriter.write({ time_zone: 'Europe/Kiev' });
- expect(output.params).to.have.property('time_zone', 'Europe/Kiev');
- });
-
- it('should use the Kibana time_zone if no parameter specified', () => {
- config.isDefault.withArgs('dateFormat:tz').returns(false);
- config.get.withArgs('dateFormat:tz').returns('Europe/Riga');
- const output = paramWriter.write({});
- expect(output.params).to.have.property('time_zone', 'Europe/Riga');
- });
-
- it('should use the fixed time_zone from the index pattern typeMeta', () => {
- set(paramWriter.indexPattern, ['typeMeta', 'aggs', 'date_range', timeField, 'time_zone'], 'Europe/Rome');
- const output = paramWriter.write({ field: timeField });
- expect(output.params).to.have.property('time_zone', 'Europe/Rome');
- });
-
- afterEach(() => {
- config.get.restore();
- config.isDefault.restore();
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/_geo_hash.js b/src/legacy/ui/public/agg_types/__tests__/buckets/_geo_hash.js
deleted file mode 100644
index 7172d1f40936e..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/_geo_hash.js
+++ /dev/null
@@ -1,257 +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 expect from '@kbn/expect';
-import sinon from 'sinon';
-import { geoHashBucketAgg } from '../../buckets/geo_hash';
-import * as AggConfigModule from '../../agg_config';
-import * as BucketAggTypeModule from '../../buckets/_bucket_agg_type';
-
-describe('Geohash Agg', () => {
-
- const initialZoom = 10;
- const initialMapBounds = {
- top_left: { lat: 1.0, lon: -1.0 },
- bottom_right: { lat: -1.0, lon: 1.0 }
- };
-
- const BucketAggTypeMock = (aggOptions) => {
- return aggOptions;
- };
- const AggConfigMock = (parent, aggOptions) => {
- return aggOptions;
- };
- const createAggregationMock = (aggOptions) => {
- return new AggConfigMock(null, aggOptions);
- };
-
- const aggMock = {
- getField: () => {
- return {
- name: 'location'
- };
- },
- params: {
- isFilteredByCollar: true,
- useGeocentroid: true,
- mapZoom: initialZoom
- },
- aggConfigs: {},
- type: 'geohash_grid',
- };
- aggMock.aggConfigs.createAggConfig = createAggregationMock;
-
-
- before(function () {
- sinon.stub(AggConfigModule, 'AggConfig').callsFake(AggConfigMock);
- sinon.stub(BucketAggTypeModule, 'BucketAggType').callsFake(BucketAggTypeMock);
- });
-
- after(function () {
- AggConfigModule.AggConfig.restore();
- BucketAggTypeModule.BucketAggType.restore();
- });
-
- function initAggParams() {
- aggMock.params.isFilteredByCollar = true;
- aggMock.params.useGeocentroid = true;
- aggMock.params.mapBounds = initialMapBounds;
- }
-
- function zoomMap(zoomChange) {
- aggMock.params.mapZoom += zoomChange;
- }
-
- function moveMap(newBounds) {
- aggMock.params.mapBounds = newBounds;
- }
-
- function resetMap() {
- aggMock.params.mapZoom = initialZoom;
- aggMock.params.mapBounds = initialMapBounds;
- aggMock.params.mapCollar = {
- top_left: { lat: 1.5, lon: -1.5 },
- bottom_right: { lat: -1.5, lon: 1.5 },
- zoom: initialZoom
- };
- }
-
- describe('precision parameter', () => {
-
- const PRECISION_PARAM_INDEX = 2;
- let precisionParam;
- beforeEach(() => {
- precisionParam = geoHashBucketAgg.params[PRECISION_PARAM_INDEX];
- });
-
- it('should select precision parameter', () => {
- expect(precisionParam.name).to.equal('precision');
- });
-
- describe('precision parameter write', () => {
-
- const zoomToGeoHashPrecision = {
- 0: 1,
- 1: 2,
- 2: 2,
- 3: 2,
- 4: 3,
- 5: 3,
- 6: 4,
- 7: 4,
- 8: 4,
- 9: 5,
- 10: 5,
- 11: 6,
- 12: 6,
- 13: 6,
- 14: 7,
- 15: 7,
- 16: 7,
- 17: 7,
- 18: 7,
- 19: 7,
- 20: 7,
- 21: 7
- };
-
- Object.keys(zoomToGeoHashPrecision).forEach((zoomLevel) => {
- it(`zoom level ${zoomLevel} should correspond to correct geohash-precision`, () => {
- const output = { params: {} };
- precisionParam.write({
- params: {
- autoPrecision: true,
- mapZoom: zoomLevel
- }
- }, output);
- expect(output.params.precision).to.equal(zoomToGeoHashPrecision[zoomLevel]);
- });
- });
- });
-
- });
-
- describe('getRequestAggs', () => {
-
- describe('initial aggregation creation', () => {
- let requestAggs;
- beforeEach(() => {
- initAggParams();
- requestAggs = geoHashBucketAgg.getRequestAggs(aggMock);
- });
-
- it('should create filter, geohash_grid, and geo_centroid aggregations', () => {
- expect(requestAggs.length).to.equal(3);
- expect(requestAggs[0].type).to.equal('filter');
- expect(requestAggs[1].type).to.equal('geohash_grid');
- expect(requestAggs[2].type).to.equal('geo_centroid');
- });
-
- it('should set mapCollar in vis session state', () => {
- expect(aggMock).to.have.property('lastMapCollar');
- expect(aggMock.lastMapCollar).to.have.property('top_left');
- expect(aggMock.lastMapCollar).to.have.property('bottom_right');
- expect(aggMock.lastMapCollar).to.have.property('zoom');
- });
-
- // there was a bug because of an "&& mapZoom" check which excluded 0 as a valid mapZoom, but it is.
- it('should create filter, geohash_grid, and geo_centroid aggregations when zoom level 0', () => {
- aggMock.params.mapZoom = 0;
- requestAggs = geoHashBucketAgg.getRequestAggs(aggMock);
- expect(requestAggs.length).to.equal(3);
- expect(requestAggs[0].type).to.equal('filter');
- expect(requestAggs[1].type).to.equal('geohash_grid');
- expect(requestAggs[2].type).to.equal('geo_centroid');
- });
- });
-
- describe('aggregation options', () => {
-
- beforeEach(() => {
- initAggParams();
- });
-
- it('should only create geohash_grid and geo_centroid aggregations when isFilteredByCollar is false', () => {
- aggMock.params.isFilteredByCollar = false;
- const requestAggs = geoHashBucketAgg.getRequestAggs(aggMock);
- expect(requestAggs.length).to.equal(2);
- expect(requestAggs[0].type).to.equal('geohash_grid');
- expect(requestAggs[1].type).to.equal('geo_centroid');
- });
-
- it('should only create filter and geohash_grid aggregations when useGeocentroid is false', () => {
- aggMock.params.useGeocentroid = false;
- const requestAggs = geoHashBucketAgg.getRequestAggs(aggMock);
- expect(requestAggs.length).to.equal(2);
- expect(requestAggs[0].type).to.equal('filter');
- expect(requestAggs[1].type).to.equal('geohash_grid');
-
- });
- });
-
- describe('aggregation creation after map interaction', () => {
-
- let origRequestAggs;
- let origMapCollar;
- beforeEach(() => {
- resetMap();
- initAggParams();
- origRequestAggs = geoHashBucketAgg.getRequestAggs(aggMock);
- origMapCollar = JSON.stringify(aggMock.lastMapCollar, null, '');
- });
-
- it('should not change geo_bounding_box filter aggregation and vis session state when map movement is within map collar', () => {
- moveMap({
- top_left: { lat: 1.1, lon: -1.1 },
- bottom_right: { lat: -0.9, lon: 0.9 }
- });
-
- const newRequestAggs = geoHashBucketAgg.getRequestAggs(aggMock);
- expect(JSON.stringify(origRequestAggs[0].params, null, '')).to.equal(JSON.stringify(newRequestAggs[0].params, null, ''));
-
- const newMapCollar = JSON.stringify(aggMock.lastMapCollar, null, '');
- expect(origMapCollar).to.equal(newMapCollar);
- });
-
- it('should change geo_bounding_box filter aggregation and vis session state when map movement is outside map collar', () => {
- moveMap({
- top_left: { lat: 10.0, lon: -10.0 },
- bottom_right: { lat: 9.0, lon: -9.0 }
- });
-
- const newRequestAggs = geoHashBucketAgg.getRequestAggs(aggMock);
- expect(JSON.stringify(origRequestAggs[0].params, null, '')).not.to.equal(JSON.stringify(newRequestAggs[0].params, null, ''));
-
- const newMapCollar = JSON.stringify(aggMock.lastMapCollar, null, '');
- expect(origMapCollar).not.to.equal(newMapCollar);
- });
-
- it('should change geo_bounding_box filter aggregation and vis session state when map zoom level changes', () => {
- zoomMap(-1);
-
- geoHashBucketAgg.getRequestAggs(aggMock);
-
- const newMapCollar = JSON.stringify(aggMock.lastMapCollar, null, '');
- expect(origMapCollar).not.to.equal(newMapCollar);
- });
-
- });
-
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/_histogram.js b/src/legacy/ui/public/agg_types/__tests__/buckets/_histogram.js
deleted file mode 100644
index 26ad80e28ae9b..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/_histogram.js
+++ /dev/null
@@ -1,210 +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 expect from '@kbn/expect';
-import sinon from 'sinon';
-import ngMock from 'ng_mock';
-import { aggTypes } from '../..';
-import chrome from '../../../chrome';
-import AggParamWriterProvider from '../agg_param_writer';
-
-const config = chrome.getUiSettingsClient();
-const histogram = aggTypes.buckets.find(agg => agg.name === 'histogram');
-describe('Histogram Agg', function () {
-
- describe('ordered', function () {
-
- it('is ordered', function () {
- expect(histogram.ordered).to.be.ok();
- });
-
- it('is not ordered by date', function () {
- expect(histogram.ordered).to.not.have.property('date');
- });
- });
-
-
- describe('params', function () {
- let paramWriter;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- const AggParamWriter = Private(AggParamWriterProvider);
- paramWriter = new AggParamWriter({ aggType: 'histogram' });
- }));
-
- describe('intervalBase', () => {
- it('should not be written to the DSL', () => {
- const output = paramWriter.write({ intervalBase: 100 });
- expect(output.params).not.to.have.property('intervalBase');
- });
- });
-
- describe('interval', function () {
- // reads aggConfig.params.interval, writes to dsl.interval
-
- it('accepts a whole number', function () {
- const output = paramWriter.write({ interval: 100 });
- expect(output.params).to.have.property('interval', 100);
- });
-
- it('accepts a decimal number', function () {
- const output = paramWriter.write({ interval: 0.1 });
- expect(output.params).to.have.property('interval', 0.1);
- });
-
- it('accepts a decimal number string', function () {
- const output = paramWriter.write({ interval: '0.1' });
- expect(output.params).to.have.property('interval', 0.1);
- });
-
- it('accepts a whole number string', function () {
- const output = paramWriter.write({ interval: '10' });
- expect(output.params).to.have.property('interval', 10);
- });
-
- it('fails on non-numeric values', function () {
- // template validation prevents this from users, not devs
- const output = paramWriter.write({ interval: [] });
- expect(isNaN(output.params.interval)).to.be.ok();
- });
-
- describe('interval scaling', () => {
-
- beforeEach(() => {
- sinon.stub(config, 'get');
- });
-
- it('will respect the histogram:maxBars setting', () => {
- config.get.withArgs('histogram:maxBars').returns(5);
- const output = paramWriter.write({ interval: 5 },
- aggConfig => aggConfig.setAutoBounds({ min: 0, max: 10000 }));
- expect(output.params).to.have.property('interval', 2000);
- });
-
- it('will return specified interval, if bars are below histogram:maxBars config', () => {
- config.get.withArgs('histogram:maxBars').returns(10000);
- const output = paramWriter.write({ interval: 5 },
- aggConfig => aggConfig.setAutoBounds({ min: 0, max: 10000 }));
- expect(output.params).to.have.property('interval', 5);
- });
-
- it('will set to intervalBase if interval is below base', () => {
- const output = paramWriter.write({ interval: 3, intervalBase: 8 });
- expect(output.params).to.have.property('interval', 8);
- });
-
- it('will round to nearest intervalBase multiple if interval is above base', () => {
- const roundUp = paramWriter.write({ interval: 46, intervalBase: 10 });
- expect(roundUp.params).to.have.property('interval', 50);
- const roundDown = paramWriter.write({ interval: 43, intervalBase: 10 });
- expect(roundDown.params).to.have.property('interval', 40);
- });
-
- it('will not change interval if it is a multiple of base', () => {
- const output = paramWriter.write({ interval: 35, intervalBase: 5 });
- expect(output.params).to.have.property('interval', 35);
- });
-
- it('will round to intervalBase after scaling histogram:maxBars', () => {
- config.get.withArgs('histogram:maxBars').returns(100);
- const output = paramWriter.write({ interval: 5, intervalBase: 6 },
- aggConfig => aggConfig.setAutoBounds({ min: 0, max: 1000 }));
- // 100 buckets in 0 to 1000 would result in an interval of 10, so we should
- // round to the next multiple of 6 -> 12
- expect(output.params).to.have.property('interval', 12);
- });
-
- afterEach(() => {
- config.get.restore();
- });
- });
- });
-
- describe('min_doc_count', function () {
- it('casts true values to 0', function () {
- let output = paramWriter.write({ min_doc_count: true });
- expect(output.params).to.have.property('min_doc_count', 0);
-
- output = paramWriter.write({ min_doc_count: 'yes' });
- expect(output.params).to.have.property('min_doc_count', 0);
-
- output = paramWriter.write({ min_doc_count: 1 });
- expect(output.params).to.have.property('min_doc_count', 0);
-
- output = paramWriter.write({ min_doc_count: {} });
- expect(output.params).to.have.property('min_doc_count', 0);
- });
-
- it('writes 1 for falsy values', function () {
- let output = paramWriter.write({ min_doc_count: '' });
- expect(output.params).to.have.property('min_doc_count', 1);
-
- output = paramWriter.write({ min_doc_count: null });
- expect(output.params).to.have.property('min_doc_count', 1);
-
- output = paramWriter.write({ min_doc_count: undefined });
- expect(output.params).to.have.property('min_doc_count', 1);
- });
- });
-
- describe('extended_bounds', function () {
- it('does not write when only eb.min is set', function () {
- const output = paramWriter.write({
- has_extended_bounds: true,
- extended_bounds: { min: 0 }
- });
- expect(output.params).not.to.have.property('extended_bounds');
- });
-
- it('does not write when only eb.max is set', function () {
- const output = paramWriter.write({
- has_extended_bounds: true,
- extended_bounds: { max: 0 }
- });
- expect(output.params).not.to.have.property('extended_bounds');
- });
-
- it('writes when both eb.min and eb.max are set', function () {
- const output = paramWriter.write({
- has_extended_bounds: true,
- extended_bounds: { min: 99, max: 100 }
- });
- expect(output.params.extended_bounds).to.have.property('min', 99);
- expect(output.params.extended_bounds).to.have.property('max', 100);
- });
-
- it('does not write when nothing is set', function () {
- const output = paramWriter.write({
- has_extended_bounds: true,
- extended_bounds: {}
- });
- expect(output.params).to.not.have.property('extended_bounds');
- });
-
- it('does not write when has_extended_bounds is false', function () {
- const output = paramWriter.write({
- has_extended_bounds: false,
- extended_bounds: { min: 99, max: 100 }
- });
- expect(output.params).to.not.have.property('extended_bounds');
- });
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/_range.js
deleted file mode 100644
index e47802aa6f4bf..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/_range.js
+++ /dev/null
@@ -1,71 +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 { values } from 'lodash';
-import ngMock from 'ng_mock';
-import expect from '@kbn/expect';
-import resp from 'fixtures/agg_resp/range';
-import { VisProvider } from '../../../vis';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-
-describe('Range Agg', function () {
- const buckets = values(resp.aggregations[1].buckets);
-
- let Vis;
- let indexPattern;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- Vis = Private(VisProvider);
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- indexPattern.stubSetFieldFormat('bytes', 'bytes', {
- pattern: '0,0.[000] b'
- });
- }));
-
- describe('formating', function () {
- it('formats bucket keys properly', function () {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'range',
- schema: 'segment',
- params: {
- field: 'bytes',
- ranges: [
- { from: 0, to: 1000 },
- { from: 1000, to: 2000 }
- ]
- }
- }
- ]
- });
-
- const agg = vis.aggs.byName('range')[0];
- const format = function (val) {
- return agg.fieldFormatter()(agg.getKey(val));
- };
- expect(format(buckets[0])).to.be('≥ -∞ and < 1 KB');
- expect(format(buckets[1])).to.be('≥ 1 KB and < 2.5 KB');
- expect(format(buckets[2])).to.be('≥ 2.5 KB and < +∞');
-
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js
deleted file mode 100644
index 11e410c43b592..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js
+++ /dev/null
@@ -1,121 +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 _ from 'lodash';
-import moment from 'moment';
-import aggResp from 'fixtures/agg_resp/date_histogram';
-import ngMock from 'ng_mock';
-import expect from '@kbn/expect';
-import { VisProvider } from '../../../../vis';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import { createFilterDateHistogram } from '../../../buckets/create_filter/date_histogram';
-import { intervalOptions } from '../../../buckets/_interval_options';
-
-describe('AggConfig Filters', function () {
- describe('date_histogram', function () {
- let vis;
- let agg;
- let field;
- let filter;
- let bucketKey;
- let bucketStart;
-
- let init;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- const Vis = Private(VisProvider);
- const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
-
- init = function (interval, duration) {
- interval = interval || 'auto';
- if (interval === 'custom') interval = agg.params.customInterval;
- duration = duration || moment.duration(15, 'minutes');
- field = _.sample(_.reject(indexPattern.fields.getByType('date'), 'scripted'));
- vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'date_histogram',
- schema: 'segment',
- params: { field: field.name, interval: interval, customInterval: '5d' }
- }
- ]
- });
-
- agg = vis.aggs.aggs[0];
- bucketKey = _.sample(aggResp.aggregations['1'].buckets).key;
- bucketStart = moment(bucketKey);
-
- const timePad = moment.duration(duration / 2);
- agg.buckets.setBounds({
- min: bucketStart.clone().subtract(timePad),
- max: bucketStart.clone().add(timePad),
- });
- agg.buckets.setInterval(interval);
-
- filter = createFilterDateHistogram(agg, bucketKey);
- };
- }));
-
- it('creates a valid range filter', function () {
- init();
-
- expect(filter).to.have.property('range');
- expect(filter.range).to.have.property(field.name);
-
- const fieldParams = filter.range[field.name];
- expect(fieldParams).to.have.property('gte');
- expect(fieldParams.gte).to.be.a('string');
-
- expect(fieldParams).to.have.property('lt');
- expect(fieldParams.lt).to.be.a('string');
-
- expect(fieldParams).to.have.property('format');
- expect(fieldParams.format).to.be('strict_date_optional_time');
-
- expect(fieldParams.gte).to.be.lessThan(fieldParams.lt);
-
- expect(filter).to.have.property('meta');
- expect(filter.meta).to.have.property('index', vis.indexPattern.id);
- });
-
-
- it('extends the filter edge to 1ms before the next bucket for all interval options', function () {
- intervalOptions.forEach(function (option) {
- let duration;
- if (option.val !== 'custom' && moment(1, option.val).isValid()) {
- duration = moment.duration(10, option.val);
-
- if (+duration < 10) {
- throw new Error('unable to create interval for ' + option.val);
- }
- }
-
- init(option.val, duration);
-
- const interval = agg.buckets.getInterval();
- const params = filter.range[field.name];
-
- expect(params.gte).to.be(bucketStart.toISOString());
- expect(params.lt).to.be(bucketStart.clone().add(interval).toISOString());
- });
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js
deleted file mode 100644
index 3ba03f232428f..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js
+++ /dev/null
@@ -1,67 +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 expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import moment from 'moment';
-import { VisProvider } from '../../../../vis';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import { createFilterDateRange } from '../../../buckets/create_filter/date_range';
-
-describe('AggConfig Filters', function () {
- describe('Date range', function () {
- let indexPattern;
- let Vis;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- Vis = Private(VisProvider);
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- }));
-
- it('should return a range filter for date_range agg', function () {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'date_range',
- params: {
- field: '@timestamp',
- ranges: [
- { from: '2014-01-01', to: '2014-12-31' }
- ]
- }
- }
- ]
- });
-
- const aggConfig = vis.aggs.byName('date_range')[0];
- const from = new Date('1 Feb 2015');
- const to = new Date('7 Feb 2015');
- const filter = createFilterDateRange(aggConfig, { from: from.valueOf(), to: to.valueOf() });
- expect(filter).to.have.property('range');
- expect(filter).to.have.property('meta');
- expect(filter.meta).to.have.property('index', indexPattern.id);
- expect(filter.range).to.have.property('@timestamp');
- expect(filter.range['@timestamp']).to.have.property('gte', moment(from).toISOString());
- expect(filter.range['@timestamp']).to.have.property('lt', moment(to).toISOString());
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/filters.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/filters.js
deleted file mode 100644
index 409c9a40b19c4..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/filters.js
+++ /dev/null
@@ -1,61 +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 expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import { VisProvider } from '../../../../vis';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import { createFilterFilters } from '../../../buckets/create_filter/filters';
-
-describe('AggConfig Filters', function () {
- describe('filters', function () {
- let indexPattern;
- let Vis;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- Vis = Private(VisProvider);
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- }));
-
- it('should return a filters filter', function () {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'filters',
- schema: 'segment',
- params: {
- filters: [
- { input: { query: 'type:apache', language: 'lucene' } },
- { input: { query: 'type:nginx', language: 'lucene' } }
- ]
- }
- }
- ]
- });
-
- const aggConfig = vis.aggs.byName('filters')[0];
- const filter = createFilterFilters(aggConfig, 'type:nginx');
- expect(filter.query.bool.must[0].query_string.query).to.be('type:nginx');
- expect(filter.meta).to.have.property('index', indexPattern.id);
- expect(filter.meta).to.have.property('alias', 'type:nginx');
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js
deleted file mode 100644
index 6d4534bba4dd1..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js
+++ /dev/null
@@ -1,61 +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 expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import { VisProvider } from '../../../../vis';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import { createFilterHistogram } from '../../../buckets/create_filter/histogram';
-
-describe('AggConfig Filters', function () {
- describe('histogram', function () {
- let indexPattern;
- let Vis;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- Vis = Private(VisProvider);
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- }));
-
- it('should return an range filter for histogram', function () {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'histogram',
- schema: 'segment',
- params: { field: 'bytes', interval: 1024 }
- }
- ]
- });
-
- const aggConfig = vis.aggs.byName('histogram')[0];
- const filter = createFilterHistogram(aggConfig, 2048);
- expect(filter).to.have.property('meta');
- expect(filter.meta).to.have.property('index', indexPattern.id);
- expect(filter).to.have.property('range');
- expect(filter.range).to.have.property('bytes');
- expect(filter.range.bytes).to.have.property('gte', 2048);
- expect(filter.range.bytes).to.have.property('lt', 3072);
- expect(filter.meta).to.have.property('formattedValue', '2,048');
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js
deleted file mode 100644
index e29ebd689db20..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js
+++ /dev/null
@@ -1,97 +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 expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import { VisProvider } from '../../../../vis';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import { createFilterIpRange } from '../../../buckets/create_filter/ip_range';
-describe('AggConfig Filters', function () {
-
- describe('IP range', function () {
- let indexPattern;
- let Vis;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- Vis = Private(VisProvider);
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- }));
-
- it('should return a range filter for ip_range agg', function () {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'ip_range',
- schema: 'segment',
- params: {
- field: 'ip',
- ipRangeType: 'fromTo',
- ranges: {
- fromTo: [
- { from: '0.0.0.0', to: '1.1.1.1' }
- ]
- }
- }
- }
- ]
- });
-
- const aggConfig = vis.aggs.byName('ip_range')[0];
- const filter = createFilterIpRange(aggConfig, { type: 'fromTo', from: '0.0.0.0', to: '1.1.1.1' });
- expect(filter).to.have.property('range');
- expect(filter).to.have.property('meta');
- expect(filter.meta).to.have.property('index', indexPattern.id);
- expect(filter.range).to.have.property('ip');
- expect(filter.range.ip).to.have.property('gte', '0.0.0.0');
- expect(filter.range.ip).to.have.property('lte', '1.1.1.1');
- });
-
- it('should return a range filter for ip_range agg using a CIDR mask', function () {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'ip_range',
- schema: 'segment',
- params: {
- field: 'ip',
- ipRangeType: 'mask',
- ranges: {
- mask: [
- { mask: '67.129.65.201/27' }
- ]
- }
- }
- }
- ]
- });
-
- const aggConfig = vis.aggs.byName('ip_range')[0];
- const filter = createFilterIpRange(aggConfig, { type: 'mask', mask: '67.129.65.201/27' });
- expect(filter).to.have.property('range');
- expect(filter).to.have.property('meta');
- expect(filter.meta).to.have.property('index', indexPattern.id);
- expect(filter.range).to.have.property('ip');
- expect(filter.range.ip).to.have.property('gte', '67.129.65.192');
- expect(filter.range.ip).to.have.property('lte', '67.129.65.223');
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/range.js
deleted file mode 100644
index 228fd6bce5cfb..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/range.js
+++ /dev/null
@@ -1,66 +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 expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import { VisProvider } from '../../../../vis';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import { createFilterRange } from '../../../buckets/create_filter/range';
-
-describe('AggConfig Filters', function () {
-
- describe('range', function () {
- let indexPattern;
- let Vis;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- Vis = Private(VisProvider);
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- }));
-
- it('should return a range filter for range agg', function () {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'range',
- schema: 'segment',
- params: {
- field: 'bytes',
- ranges: [
- { from: 1024, to: 2048 }
- ]
- }
- }
- ]
- });
-
- const aggConfig = vis.aggs.byName('range')[0];
- const filter = createFilterRange(aggConfig, { gte: 1024, lt: 2048.0 });
- expect(filter).to.have.property('range');
- expect(filter).to.have.property('meta');
- expect(filter.meta).to.have.property('index', indexPattern.id);
- expect(filter.range).to.have.property('bytes');
- expect(filter.range.bytes).to.have.property('gte', 1024.0);
- expect(filter.range.bytes).to.have.property('lt', 2048.0);
- expect(filter.meta).to.have.property('formattedValue', '≥ 1,024 and < 2,048');
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/terms.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/terms.js
deleted file mode 100644
index a2812ffb97965..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/terms.js
+++ /dev/null
@@ -1,104 +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 expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import { VisProvider } from '../../../../vis';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import { createFilterTerms } from '../../../buckets/create_filter/terms';
-
-describe('AggConfig Filters', function () {
-
- describe('terms', function () {
- let indexPattern;
- let Vis;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- Vis = Private(VisProvider);
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- }));
-
- it('should return a match_phrase filter for terms', function () {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [ { type: 'terms', schema: 'segment', params: { field: '_type' } } ]
- });
- const aggConfig = vis.aggs.byName('terms')[0];
- const filter = createFilterTerms(aggConfig, 'apache');
- expect(filter).to.have.property('query');
- expect(filter.query).to.have.property('match_phrase');
- expect(filter.query.match_phrase).to.have.property('_type');
- expect(filter.query.match_phrase._type).to.be('apache');
- expect(filter).to.have.property('meta');
- expect(filter.meta).to.have.property('index', indexPattern.id);
-
- });
-
- it('should set query to true or false for boolean filter', () => {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [ { type: 'terms', schema: 'segment', params: { field: 'ssl' } } ]
- });
- const aggConfig = vis.aggs.byName('terms')[0];
- const filterFalse = createFilterTerms(aggConfig, 0);
- expect(filterFalse).to.have.property('query');
- expect(filterFalse.query).to.have.property('match_phrase');
- expect(filterFalse.query.match_phrase).to.have.property('ssl');
- expect(filterFalse.query.match_phrase.ssl).to.be(false);
-
- const filterTrue = createFilterTerms(aggConfig, 1);
- expect(filterTrue).to.have.property('query');
- expect(filterTrue.query).to.have.property('match_phrase');
- expect(filterTrue.query.match_phrase).to.have.property('ssl');
- expect(filterTrue.query.match_phrase.ssl).to.be(true);
- });
-
- it('should generate correct __missing__ filter', () => {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [ { type: 'terms', schema: 'segment', params: { field: '_type' } } ]
- });
- const aggConfig = vis.aggs.byName('terms')[0];
- const filter = createFilterTerms(aggConfig, '__missing__');
- expect(filter).to.have.property('exists');
- expect(filter.exists).to.have.property('field', '_type');
- expect(filter).to.have.property('meta');
- expect(filter.meta).to.have.property('index', indexPattern.id);
- expect(filter.meta).to.have.property('negate', true);
- });
-
- it('should generate correct __other__ filter', () => {
- const vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [ { type: 'terms', schema: 'segment', params: { field: '_type' } } ]
- });
- const aggConfig = vis.aggs.byName('terms')[0];
- const filter = createFilterTerms(aggConfig, '__other__', { terms: ['apache'] })[0];
- expect(filter).to.have.property('query');
- expect(filter.query).to.have.property('bool');
- expect(filter.query.bool).to.have.property('should');
- expect(filter.query.bool.should[0]).to.have.property('match_phrase');
- expect(filter.query.bool.should[0].match_phrase).to.have.property('_type', 'apache');
- expect(filter).to.have.property('meta');
- expect(filter.meta).to.have.property('index', indexPattern.id);
- expect(filter.meta).to.have.property('negate', true);
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js b/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js
deleted file mode 100644
index 7b8f099a1f9b4..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js
+++ /dev/null
@@ -1,124 +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 _ from 'lodash';
-import $ from 'jquery';
-import ngMock from 'ng_mock';
-import expect from '@kbn/expect';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import { VisProvider } from '../../../../vis';
-import { intervalOptions } from '../../../buckets/_interval_options';
-
-describe.skip('editor', function () {
-
- let indexPattern;
- let vis;
- let agg;
- let render;
- let $scope;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private, $injector, $compile) {
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
-
- const Vis = Private(VisProvider);
-
- /**
- * Render the AggParams editor for the date histogram aggregation
- *
- * @param {object} params - the agg params to give to the date_histogram
- * by default
- * @return {object} - object pointing to the different inputs, keys
- * are the aggParam name and the value is an object
- * with $el, $scope, and a few helpers for getting
- * data from them.
- */
- render = function (params) {
- vis = new Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- { schema: 'metric', type: 'avg', params: { field: 'bytes' } },
- { schema: 'segment', type: 'date_histogram', params: params || {} }
- ]
- });
-
- const $el = $('' +
- ' ');
- const $parentScope = $injector.get('$rootScope').$new();
-
- agg = $parentScope.agg = vis.aggs.bySchemaName('segment')[0];
- $parentScope.groupName = 'buckets';
- $parentScope.vis = vis;
-
- $compile($el)($parentScope);
- $scope = $el.scope();
- $scope.$digest();
-
- const $inputs = $('vis-agg-param-editor', $el);
- return _.transform($inputs.toArray(), function (inputs, e) {
- const $el = $(e);
- const $scope = $el.scope();
-
- inputs[$scope.aggParam.name] = {
- $el: $el,
- $scope: $scope,
- $input: function () {
- return $el.find('[ng-model]').first();
- },
- modelValue: function () {
- return this.$input().controller('ngModel').$modelValue;
- }
- };
- }, {});
- };
-
- }));
-
- describe('random field/interval', function () {
- let params;
- let field;
- let interval;
-
- beforeEach(ngMock.inject(function () {
- field = _.sample(indexPattern.fields);
- interval = _.sample(intervalOptions);
- params = render({ field: field, interval: interval.val });
- }));
-
- it('renders the field editor', function () {
- expect(agg.params.field).to.be(field);
-
- expect(params).to.have.property('field');
- expect(params.field).to.have.property('$el');
- expect($scope.agg.params.field).to.be(field);
- });
-
- it('renders the interval editor', function () {
- expect(agg.params.interval).to.be(interval.val);
-
- expect(params).to.have.property('interval');
- expect(params.interval).to.have.property('$el');
- expect($scope.agg.params.interval).to.be(interval.val);
- });
- });
-
-
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js b/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js
deleted file mode 100644
index 88646bd36ee80..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js
+++ /dev/null
@@ -1,215 +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 _ from 'lodash';
-import moment from 'moment';
-import expect from '@kbn/expect';
-import sinon from 'sinon';
-import ngMock from 'ng_mock';
-import AggParamWriterProvider from '../../agg_param_writer';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import chrome from '../../../../chrome';
-import { aggTypes } from '../../..';
-import { AggConfig } from '../../../agg_config';
-import { timefilter } from 'ui/timefilter';
-
-const config = chrome.getUiSettingsClient();
-
-describe('date_histogram params', function () {
-
- let paramWriter;
- let writeInterval;
- let write;
-
- let getTimeBounds;
- let timeField;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- const AggParamWriter = Private(AggParamWriterProvider);
- const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
-
- timeField = indexPattern.timeFieldName;
-
- paramWriter = new AggParamWriter({ aggType: 'date_histogram' });
- writeInterval = function (interval, timeRange, params = {}) {
- return paramWriter.write({ ...params, interval: interval, field: timeField, timeRange: timeRange });
- };
- write = (params) => {
- return paramWriter.write({ interval: '10s', ...params });
- };
-
- const now = moment();
- getTimeBounds = function (n, units) {
- timefilter.enableAutoRefreshSelector();
- timefilter.enableTimeRangeSelector();
- return {
- from: now.clone().subtract(n, units),
- to: now.clone()
- };
- };
- }));
-
- describe('interval', function () {
- it('accepts a valid calendar interval', function () {
- const output = writeInterval('d');
- expect(output.params).to.have.property('calendar_interval', '1d');
- });
-
- it('accepts a valid fixed interval', () => {
- const output = writeInterval('100s');
- expect(output.params).to.have.property('fixed_interval', '100s');
- });
-
- it('throws error when interval is invalid', function () {
- expect(() => writeInterval('foo')).to.throw('TypeError: "foo" is not a valid interval.');
- });
-
- it('automatically picks an interval', function () {
- const timeBounds = getTimeBounds(15, 'm');
- const output = writeInterval('auto', timeBounds);
- expect(output.params).to.have.property('fixed_interval', '30s');
- });
-
- it('does not scale down the interval', () => {
- const timeBounds = getTimeBounds(1, 'm');
- const output = writeInterval('h', timeBounds);
- expect(output.params).to.have.property('calendar_interval', '1h');
- expect(output).not.to.have.property('metricScaleText');
- expect(output).not.to.have.property('metricScale');
- });
-
- describe('scaling behavior', () => {
-
- it('should not scale without scaleMetricValues: true', function () {
- const timeBounds = getTimeBounds(30, 'm');
- const output = writeInterval('s', timeBounds);
- expect(output.params).to.have.property('fixed_interval', '10s');
- expect(output).not.to.have.property('metricScaleText');
- expect(output).not.to.property('metricScale');
- });
-
- describe('only scales when all metrics are sum or count', function () {
- const tests = [
- [ false, 'avg', 'count', 'sum' ],
- [ true, 'count', 'sum' ],
- [ false, 'count', 'cardinality' ]
- ];
-
- tests.forEach(function (test) {
- const should = test.shift();
- const typeNames = test.slice();
-
- it(typeNames.join(', ') + ' should ' + (should ? '' : 'not') + ' scale', function () {
- const timeBounds = getTimeBounds(1, 'y');
-
- const vis = paramWriter.vis;
- vis.aggs.aggs.splice(0);
-
- const histoConfig = new AggConfig(vis.aggs, {
- type: aggTypes.buckets.find(agg => agg.name === 'date_histogram'),
- schema: 'segment',
- params: { interval: 's', field: timeField, timeRange: timeBounds, scaleMetricValues: true }
- });
-
- vis.aggs.aggs.push(histoConfig);
-
- typeNames.forEach(function (type) {
- vis.aggs.aggs.push(new AggConfig(vis.aggs, {
- type: aggTypes.metrics.find(agg => agg.name === type),
- schema: 'metric'
- }));
- });
-
- const output = histoConfig.write(vis.aggs);
- expect(_.has(output, 'metricScale')).to.be(should);
- });
- });
- });
- });
- });
-
- describe('time_zone', () => {
- beforeEach(() => {
- sinon.stub(config, 'get');
- sinon.stub(config, 'isDefault');
- });
-
- it('should use the specified time_zone', () => {
- const output = write({ time_zone: 'Europe/Kiev' });
- expect(output.params).to.have.property('time_zone', 'Europe/Kiev');
- });
-
- it('should use the Kibana time_zone if no parameter specified', () => {
- config.isDefault.withArgs('dateFormat:tz').returns(false);
- config.get.withArgs('dateFormat:tz').returns('Europe/Riga');
- const output = write({});
- expect(output.params).to.have.property('time_zone', 'Europe/Riga');
- });
-
- it('should use the fixed time_zone from the index pattern typeMeta', () => {
- _.set(paramWriter.indexPattern, ['typeMeta', 'aggs', 'date_histogram', timeField, 'time_zone'], 'Europe/Rome');
- const output = write({ field: timeField });
- expect(output.params).to.have.property('time_zone', 'Europe/Rome');
- });
-
- afterEach(() => {
- config.get.restore();
- config.isDefault.restore();
- });
- });
-
- describe('extended_bounds', function () {
- it('should write a long value if a moment passed in', function () {
- const then = moment(0);
- const now = moment(500);
- const output = write({
- extended_bounds: {
- min: then,
- max: now
- }
- });
-
- expect(typeof output.params.extended_bounds.min).to.be('number');
- expect(typeof output.params.extended_bounds.max).to.be('number');
- expect(output.params.extended_bounds.min).to.be(then.valueOf());
- expect(output.params.extended_bounds.max).to.be(now.valueOf());
-
-
- });
-
- it('should write a long if a long is passed', function () {
- const then = 0;
- const now = 500;
- const output = write({
- extended_bounds: {
- min: then,
- max: now
- }
- });
-
- expect(typeof output.params.extended_bounds.min).to.be('number');
- expect(typeof output.params.extended_bounds.max).to.be('number');
- expect(output.params.extended_bounds.min).to.be(then.valueOf());
- expect(output.params.extended_bounds.max).to.be(now.valueOf());
-
-
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/significant_terms.js b/src/legacy/ui/public/agg_types/__tests__/buckets/significant_terms.js
deleted file mode 100644
index ae52fb476c120..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/significant_terms.js
+++ /dev/null
@@ -1,95 +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 expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import { aggTypes } from '../..';
-
-describe('Significant Terms Agg', function () {
-
- describe('order agg editor UI', function () {
-
- describe('convert include/exclude from old format', function () {
-
- let $rootScope;
-
- function init({ aggParams = {} }) {
- ngMock.module('kibana');
- ngMock.inject(function (_$rootScope_) {
- const significantTerms = aggTypes.buckets.find(agg => agg.name === 'significant_terms');
-
- $rootScope = _$rootScope_;
- $rootScope.agg = {
- id: 'test',
- params: aggParams,
- type: significantTerms,
- getParam: key => aggParams[key],
- };
- });
- }
-
- function testSerializeAndWrite(aggConfig) {
- const includeArg = $rootScope.agg.type.paramByName('include');
- const excludeArg = $rootScope.agg.type.paramByName('exclude');
-
- expect(includeArg.serialize(aggConfig.params.include, aggConfig)).to.equal('404');
- expect(excludeArg.serialize(aggConfig.params.exclude, aggConfig)).to.equal('400');
-
- const output = { params: {} };
-
- includeArg.write(aggConfig, output);
- excludeArg.write(aggConfig, output);
-
- expect(output.params.include).to.equal('404');
- expect(output.params.exclude).to.equal('400');
- }
-
- it('it doesnt do anything with string type', function () {
- init({
- aggParams: {
- include: '404',
- exclude: '400',
- field: {
- type: 'string'
- },
- }
- });
-
- testSerializeAndWrite($rootScope.agg);
- });
-
- it('converts object to string type', function () {
- init({
- aggParams: {
- include: {
- pattern: '404'
- }, exclude: {
- pattern: '400'
- },
- field: {
- type: 'string'
- },
- }
- });
-
- testSerializeAndWrite($rootScope.agg);
- });
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/terms.js b/src/legacy/ui/public/agg_types/__tests__/buckets/terms.js
deleted file mode 100644
index 600323d32d38c..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/buckets/terms.js
+++ /dev/null
@@ -1,193 +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 expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import { aggTypes } from '../..';
-
-describe('Terms Agg', function () {
- describe('order agg editor UI', function () {
-
- let $rootScope;
-
- function init({ metricAggs = [], aggParams = {} }) {
- ngMock.module('kibana');
- ngMock.inject(function ($controller, _$rootScope_) {
- const terms = aggTypes.buckets.find(agg => agg.name === 'terms');
- const orderAggController = terms.paramByName('orderAgg').controller;
-
- $rootScope = _$rootScope_;
- $rootScope.agg = {
- id: 'test',
- params: aggParams,
- type: terms,
- vis: {
- aggs: []
- },
- getParam: key => aggParams[key],
- };
- $rootScope.metricAggs = metricAggs;
- $controller(orderAggController, { $scope: $rootScope });
- $rootScope.$digest();
- });
- }
-
- // should be rewritten after EUIficate order_agg.html
- it.skip('selects _key if the selected metric becomes incompatible', function () {
- init({
- metricAggs: [
- {
- id: 'agg1',
- type: {
- name: 'count'
- }
- }
- ]
- });
-
- expect($rootScope.agg.params.orderBy).to.be('agg1');
- $rootScope.metricAggs = [
- {
- id: 'agg1',
- type: {
- name: 'top_hits'
- }
- }
- ];
- $rootScope.$digest();
- expect($rootScope.agg.params.orderBy).to.be('_key');
- });
-
- // should be rewritten after EUIficate order_agg.html
- it.skip('selects _key if the selected metric is removed', function () {
- init({
- metricAggs: [
- {
- id: 'agg1',
- type: {
- name: 'count'
- }
- }
- ]
- });
- expect($rootScope.agg.params.orderBy).to.be('agg1');
- $rootScope.metricAggs = [];
- $rootScope.$digest();
- expect($rootScope.agg.params.orderBy).to.be('_key');
- });
-
- describe.skip('custom field formatter', () => {
- beforeEach(() => {
- init({
- metricAggs: [
- {
- id: 'agg1',
- type: {
- name: 'count'
- }
- }
- ],
- aggParams: {
- otherBucketLabel: 'Other',
- missingBucketLabel: 'Missing'
- }
- });
- $rootScope.$digest();
- });
-
- it ('converts __other__ key', () => {
- const formatter = $rootScope.agg.type.getFormat($rootScope.agg).getConverterFor('text');
- expect(formatter('__other__')).to.be('Other');
- });
-
- it ('converts __missing__ key', () => {
- const formatter = $rootScope.agg.type.getFormat($rootScope.agg).getConverterFor('text');
- expect(formatter('__missing__')).to.be('Missing');
- });
- });
-
- it('adds "custom metric" option');
- it('lists all metric agg responses');
- it('lists individual values of a multi-value metric');
- it('displays a metric editor if "custom metric" is selected');
- it('saves the "custom metric" to state and refreshes from it');
- it('invalidates the form if the metric agg form is not complete');
-
- describe.skip('convert include/exclude from old format', function () {
-
- it('it doesnt do anything with string type', function () {
- init({
- aggParams: {
- include: '404',
- exclude: '400',
- field: {
- type: 'string'
- },
- }
- });
-
- const aggConfig = $rootScope.agg;
- const includeArg = $rootScope.agg.type.params.byName.include;
- const excludeArg = $rootScope.agg.type.params.byName.exclude;
-
- expect(includeArg.serialize(aggConfig.params.include, aggConfig)).to.equal('404');
- expect(excludeArg.serialize(aggConfig.params.exclude, aggConfig)).to.equal('400');
-
- const output = { params: {} };
-
- includeArg.write(aggConfig, output);
- excludeArg.write(aggConfig, output);
-
- expect(output.params.include).to.equal('404');
- expect(output.params.exclude).to.equal('400');
- });
-
- it('converts object to string type', function () {
- init({
- aggParams: {
- include: {
- pattern: '404'
- }, exclude: {
- pattern: '400'
- },
- field: {
- type: 'string'
- },
- }
- });
-
- const aggConfig = $rootScope.agg;
- const includeArg = $rootScope.agg.type.params.byName.include;
- const excludeArg = $rootScope.agg.type.params.byName.exclude;
-
- expect(includeArg.serialize(aggConfig.params.include, aggConfig)).to.equal('404');
- expect(excludeArg.serialize(aggConfig.params.exclude, aggConfig)).to.equal('400');
-
- const output = { params: {} };
-
- includeArg.write(aggConfig, output);
- excludeArg.write(aggConfig, output);
-
- expect(output.params.include).to.equal('404');
- expect(output.params.exclude).to.equal('400');
- });
-
- });
- });
-});
diff --git a/src/legacy/ui/public/agg_types/__tests__/utils/_stub_agg_params.js b/src/legacy/ui/public/agg_types/__tests__/utils/_stub_agg_params.js
deleted file mode 100644
index f30572bcc0ed5..0000000000000
--- a/src/legacy/ui/public/agg_types/__tests__/utils/_stub_agg_params.js
+++ /dev/null
@@ -1,67 +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 _ from 'lodash';
-import sinon from 'sinon';
-import { BaseParamType } from '../../param_types/base';
-import { FieldParamType } from '../../param_types/field';
-import { OptionedParamType } from '../../param_types/optioned';
-import { createLegacyClass } from '../../../utils/legacy_class';
-
-function ParamClassStub(parent, body) {
- const stub = sinon.spy(body || function () {
- stub.Super && stub.Super.call(this);
- });
- if (parent) createLegacyClass(stub).inherits(parent);
- return stub;
-}
-
-/**
- * stub all of the param classes, but ensure that they still inherit properly.
- * This method should be passed directly to ngMock.inject();
- *
- * ```js
- * let stubParamClasses = require('./utils/_stub_agg_params');
- * describe('something', function () {
- * beforeEach(ngMock.inject(stubParamClasses));
- * })
- * ```
- *
- * @param {PrivateLoader} Private - The private module loader, inject by passing this function to ngMock.inject()
- * @return {undefined}
- */
-// eslint-disable-next-line import/no-default-export
-export default function stubParamClasses(Private) {
- const BaseAggParam = Private.stub(
- BaseParamType,
- new ParamClassStub(null, function (config) {
- _.assign(this, config);
- })
- );
-
- Private.stub(
- FieldParamType,
- new ParamClassStub(BaseAggParam)
- );
-
- Private.stub(
- OptionedParamType,
- new ParamClassStub(BaseAggParam)
- );
-}
diff --git a/src/legacy/ui/public/agg_types/agg_config.ts b/src/legacy/ui/public/agg_types/agg_config.ts
index a5b1aa7cf9c0b..eedfc1cc05a84 100644
--- a/src/legacy/ui/public/agg_types/agg_config.ts
+++ b/src/legacy/ui/public/agg_types/agg_config.ts
@@ -332,7 +332,7 @@ export class AggConfig {
return this.type.getValue(this, bucket);
}
- getKey(bucket: any, key: string) {
+ getKey(bucket: any, key?: string) {
if (this.type.getKey) {
return this.type.getKey(bucket, key, this);
} else {
diff --git a/src/legacy/ui/public/agg_types/buckets/_terms_other_bucket_helper.js b/src/legacy/ui/public/agg_types/buckets/_terms_other_bucket_helper.js
index 5dfa2e3d6ae3f..70bca2e40ae3f 100644
--- a/src/legacy/ui/public/agg_types/buckets/_terms_other_bucket_helper.js
+++ b/src/legacy/ui/public/agg_types/buckets/_terms_other_bucket_helper.js
@@ -18,8 +18,9 @@
*/
import _ from 'lodash';
-import { buildExistsFilter, buildPhrasesFilter, buildQueryFromFilters } from '@kbn/es-query';
+import { buildQueryFromFilters } from '@kbn/es-query';
import { AggGroupNames } from '../../vis/editors/default/agg_groups';
+import { esFilters } from '../../../../../plugins/data/public';
/**
* walks the aggregation DSL and returns DSL starting at aggregation with id of startFromAggId
@@ -180,7 +181,7 @@ export const buildOtherBucketAgg = (aggConfigs, aggWithOtherBucket, response) =>
agg.buckets.some(bucket => bucket.key === '__missing__')
) {
filters.push(
- buildExistsFilter(
+ esFilters.buildExistsFilter(
aggWithOtherBucket.params.field,
aggWithOtherBucket.params.field.indexPattern
)
@@ -232,7 +233,7 @@ export const mergeOtherBucketAggResponse = (
);
const requestFilterTerms = getOtherAggTerms(requestAgg, key, otherAgg);
- const phraseFilter = buildPhrasesFilter(
+ const phraseFilter = esFilters.buildPhrasesFilter(
otherAgg.params.field,
requestFilterTerms,
otherAgg.params.field.indexPattern
@@ -243,7 +244,7 @@ export const mergeOtherBucketAggResponse = (
if (aggResultBuckets.some(bucket => bucket.key === '__missing__')) {
bucket.filters.push(
- buildExistsFilter(otherAgg.params.field, otherAgg.params.field.indexPattern)
+ esFilters.buildExistsFilter(otherAgg.params.field, otherAgg.params.field.indexPattern)
);
}
aggResultBuckets.push(bucket);
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.test.ts
new file mode 100644
index 0000000000000..9426df7d34c29
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.test.ts
@@ -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 moment from 'moment';
+import { createFilterDateHistogram } from './date_histogram';
+import { intervalOptions } from '../_interval_options';
+import { AggConfigs } from '../../agg_configs';
+import { IBucketDateHistogramAggConfig } from '../date_histogram';
+import { BUCKET_TYPES } from '../bucket_agg_types';
+import { esFilters } from '../../../../../../plugins/data/public';
+
+jest.mock('ui/new_platform');
+
+describe('AggConfig Filters', () => {
+ describe('date_histogram', () => {
+ let agg: IBucketDateHistogramAggConfig;
+ let filter: esFilters.RangeFilter;
+ let bucketStart: any;
+ let field: any;
+
+ const init = (interval: string = 'auto', duration: any = moment.duration(15, 'minutes')) => {
+ field = {
+ name: 'date',
+ };
+
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+ const aggConfigs = new AggConfigs(
+ indexPattern,
+ [
+ {
+ type: BUCKET_TYPES.DATE_HISTOGRAM,
+ schema: 'segment',
+ params: { field: field.name, interval, customInterval: '5d' },
+ },
+ ],
+ null
+ );
+ const bucketKey = 1422579600000;
+
+ agg = aggConfigs.aggs[0] as IBucketDateHistogramAggConfig;
+ bucketStart = moment(bucketKey);
+
+ const timePad = moment.duration(duration / 2);
+
+ agg.buckets.setBounds({
+ min: bucketStart.clone().subtract(timePad),
+ max: bucketStart.clone().add(timePad),
+ });
+ agg.buckets.setInterval(interval);
+ filter = createFilterDateHistogram(agg, bucketKey);
+ };
+
+ it('creates a valid range filter', () => {
+ init();
+
+ expect(filter).toHaveProperty('range');
+ expect(filter.range).toHaveProperty(field.name);
+
+ const fieldParams = filter.range[field.name];
+ expect(fieldParams).toHaveProperty('gte');
+ expect(typeof fieldParams.gte).toBe('string');
+
+ expect(fieldParams).toHaveProperty('lt');
+ expect(typeof fieldParams.lt).toBe('string');
+
+ expect(fieldParams).toHaveProperty('format');
+ expect(fieldParams.format).toBe('strict_date_optional_time');
+
+ expect(filter).toHaveProperty('meta');
+ expect(filter.meta).toHaveProperty('index', '1234');
+ });
+
+ it('extends the filter edge to 1ms before the next bucket for all interval options', () => {
+ intervalOptions.forEach(option => {
+ let duration;
+ if (option.val !== 'custom' && moment(1, option.val).isValid()) {
+ // @ts-ignore
+ duration = moment.duration(10, option.val);
+
+ if (+duration < 10) {
+ throw new Error('unable to create interval for ' + option.val);
+ }
+ }
+ init(option.val, duration);
+
+ const interval = agg.buckets.getInterval();
+ const params = filter.range[field.name];
+
+ expect(params.gte).toBe(bucketStart.toISOString());
+ expect(params.lt).toBe(
+ bucketStart
+ .clone()
+ .add(interval)
+ .toISOString()
+ );
+ });
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.ts
index 6bda085335309..f91a92eab1c33 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.ts
@@ -18,14 +18,17 @@
*/
import moment from 'moment';
-import { buildRangeFilter } from '@kbn/es-query';
import { IBucketDateHistogramAggConfig } from '../date_histogram';
+import { esFilters } from '../../../../../../plugins/data/public';
-export const createFilterDateHistogram = (agg: IBucketDateHistogramAggConfig, key: string) => {
+export const createFilterDateHistogram = (
+ agg: IBucketDateHistogramAggConfig,
+ key: string | number
+) => {
const start = moment(key);
const interval = agg.buckets.getInterval();
- return buildRangeFilter(
+ return esFilters.buildRangeFilter(
agg.params.field,
{
gte: start.toISOString(),
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.test.ts
new file mode 100644
index 0000000000000..35b6c38bad799
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.test.ts
@@ -0,0 +1,77 @@
+/*
+ * 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 { createFilterDateRange } from './date_range';
+import { DateFormat } from '../../../../../../plugins/data/common';
+import { AggConfigs } from '../../agg_configs';
+import { BUCKET_TYPES } from '../bucket_agg_types';
+
+jest.mock('ui/new_platform');
+
+describe('AggConfig Filters', () => {
+ describe('Date range', () => {
+ const getAggConfigs = () => {
+ const field = {
+ name: '@timestamp',
+ format: new DateFormat({}, () => {}),
+ };
+
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ type: BUCKET_TYPES.DATE_RANGE,
+ params: {
+ field: '@timestamp',
+ ranges: [{ from: '2014-01-01', to: '2014-12-31' }],
+ },
+ },
+ ],
+ null
+ );
+ };
+
+ it('should return a range filter for date_range agg', () => {
+ const aggConfigs = getAggConfigs();
+ const from = new Date('1 Feb 2015');
+ const to = new Date('7 Feb 2015');
+ const filter = createFilterDateRange(aggConfigs.aggs[0], {
+ from: from.valueOf(),
+ to: to.valueOf(),
+ });
+
+ expect(filter).toHaveProperty('range');
+ expect(filter).toHaveProperty('meta');
+ expect(filter.meta).toHaveProperty('index', '1234');
+ expect(filter.range).toHaveProperty('@timestamp');
+ expect(filter.range['@timestamp']).toHaveProperty('gte', moment(from).toISOString());
+ expect(filter.range['@timestamp']).toHaveProperty('lt', moment(to).toISOString());
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.ts
index cd4b0ffc215b0..01689d954a072 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.ts
@@ -17,16 +17,16 @@
* under the License.
*/
-import { buildRangeFilter, RangeFilterParams } from '@kbn/es-query';
import moment from 'moment';
import { IBucketAggConfig } from '../_bucket_agg_type';
import { DateRangeKey } from '../date_range';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterDateRange = (agg: IBucketAggConfig, { from, to }: DateRangeKey) => {
- const filter: RangeFilterParams = {};
+ const filter: esFilters.RangeFilterParams = {};
if (from) filter.gte = moment(from).toISOString();
if (to) filter.lt = moment(to).toISOString();
if (to && from) filter.format = 'strict_date_optional_time';
- return buildRangeFilter(agg.params.field, filter, agg.getIndexPattern());
+ return esFilters.buildRangeFilter(agg.params.field, filter, agg.getIndexPattern());
};
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/filters.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/filters.test.ts
new file mode 100644
index 0000000000000..125532fe070ba
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/filters.test.ts
@@ -0,0 +1,66 @@
+/*
+ * 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 { createFilterFilters } from './filters';
+import { AggConfigs } from '../../agg_configs';
+
+jest.mock('ui/new_platform');
+
+describe('AggConfig Filters', () => {
+ describe('filters', () => {
+ const getAggConfigs = () => {
+ const field = {
+ name: 'bytes',
+ };
+
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ type: 'filters',
+ schema: 'segment',
+ params: {
+ filters: [
+ { input: { query: 'type:apache', language: 'lucene' } },
+ { input: { query: 'type:nginx', language: 'lucene' } },
+ ],
+ },
+ },
+ ],
+ null
+ );
+ };
+ it('should return a filters filter', () => {
+ const aggConfigs = getAggConfigs();
+ const filter = createFilterFilters(aggConfigs.aggs[0], 'type:nginx');
+
+ expect(filter!.query.bool.must[0].query_string.query).toBe('type:nginx');
+ expect(filter!.meta).toHaveProperty('index', '1234');
+ expect(filter!.meta).toHaveProperty('alias', 'type:nginx');
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/filters.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/filters.ts
index bf30b333056bc..6b614514580b6 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/filters.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/filters.ts
@@ -18,8 +18,8 @@
*/
import { get } from 'lodash';
-import { buildQueryFilter } from '@kbn/es-query';
import { IBucketAggConfig } from '../_bucket_agg_type';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterFilters = (aggConfig: IBucketAggConfig, key: string) => {
// have the aggConfig write agg dsl params
@@ -28,6 +28,6 @@ export const createFilterFilters = (aggConfig: IBucketAggConfig, key: string) =>
const indexPattern = aggConfig.getIndexPattern();
if (filter && indexPattern && indexPattern.id) {
- return buildQueryFilter(filter.query, indexPattern.id, key);
+ return esFilters.buildQueryFilter(filter.query, indexPattern.id, key);
}
};
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.test.ts
new file mode 100644
index 0000000000000..0095df75b8914
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.test.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 { createFilterHistogram } from './histogram';
+import { AggConfigs } from '../../agg_configs';
+import { BUCKET_TYPES } from '../bucket_agg_types';
+import { BytesFormat } from '../../../../../../plugins/data/common';
+
+jest.mock('ui/new_platform');
+
+describe('AggConfig Filters', () => {
+ describe('histogram', () => {
+ const getAggConfigs = () => {
+ const field = {
+ name: 'bytes',
+ format: new BytesFormat({}, () => {}),
+ };
+
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ id: BUCKET_TYPES.HISTOGRAM,
+ type: BUCKET_TYPES.HISTOGRAM,
+ schema: 'buckets',
+ params: {
+ field: 'bytes',
+ interval: 1024,
+ },
+ },
+ ],
+ null
+ );
+ };
+
+ it('should return an range filter for histogram', () => {
+ const aggConfigs = getAggConfigs();
+ const filter = createFilterHistogram(aggConfigs.aggs[0], '2048');
+
+ expect(filter).toHaveProperty('meta');
+ expect(filter.meta).toHaveProperty('index', '1234');
+ expect(filter).toHaveProperty('range');
+ expect(filter.range).toHaveProperty('bytes');
+ expect(filter.range.bytes).toHaveProperty('gte', 2048);
+ expect(filter.range.bytes).toHaveProperty('lt', 3072);
+ expect(filter.meta).toHaveProperty('formattedValue', '2,048');
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.ts
index 37d5c6bc8adc1..fc587fa9ecdb6 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-import { buildRangeFilter, RangeFilterParams } from '@kbn/es-query';
import { IBucketAggConfig } from '../_bucket_agg_type';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterHistogram = (aggConfig: IBucketAggConfig, key: string) => {
const value = parseInt(key, 10);
- const params: RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval };
+ const params: esFilters.RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval };
- return buildRangeFilter(
+ return esFilters.buildRangeFilter(
aggConfig.params.field,
params,
aggConfig.getIndexPattern(),
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.test.ts
new file mode 100644
index 0000000000000..2e030d820b396
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.test.ts
@@ -0,0 +1,104 @@
+/*
+ * 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 { createFilterIpRange } from './ip_range';
+import { AggConfigs } from '../../agg_configs';
+import { IpFormat } from '../../../../../../plugins/data/common';
+import { BUCKET_TYPES } from '../bucket_agg_types';
+
+jest.mock('ui/new_platform');
+
+describe('AggConfig Filters', () => {
+ describe('IP range', () => {
+ const getAggConfigs = (aggs: Array>) => {
+ const field = {
+ name: 'ip',
+ format: IpFormat,
+ };
+
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ return new AggConfigs(indexPattern, aggs, null);
+ };
+
+ it('should return a range filter for ip_range agg', () => {
+ const aggConfigs = getAggConfigs([
+ {
+ type: BUCKET_TYPES.IP_RANGE,
+ schema: 'segment',
+ params: {
+ field: 'ip',
+ ipRangeType: 'range',
+ ranges: {
+ fromTo: [{ from: '0.0.0.0', to: '1.1.1.1' }],
+ },
+ },
+ },
+ ]);
+
+ const filter = createFilterIpRange(aggConfigs.aggs[0], {
+ type: 'range',
+ from: '0.0.0.0',
+ to: '1.1.1.1',
+ });
+
+ expect(filter).toHaveProperty('range');
+ expect(filter).toHaveProperty('meta');
+ expect(filter.meta).toHaveProperty('index', '1234');
+ expect(filter.range).toHaveProperty('ip');
+ expect(filter.range.ip).toHaveProperty('gte', '0.0.0.0');
+ expect(filter.range.ip).toHaveProperty('lte', '1.1.1.1');
+ });
+
+ it('should return a range filter for ip_range agg using a CIDR mask', () => {
+ const aggConfigs = getAggConfigs([
+ {
+ type: BUCKET_TYPES.IP_RANGE,
+ schema: 'segment',
+ params: {
+ field: 'ip',
+ ipRangeType: 'mask',
+ ranges: {
+ mask: [{ mask: '67.129.65.201/27' }],
+ },
+ },
+ },
+ ]);
+
+ const filter = createFilterIpRange(aggConfigs.aggs[0], {
+ type: 'mask',
+ mask: '67.129.65.201/27',
+ });
+
+ expect(filter).toHaveProperty('range');
+ expect(filter).toHaveProperty('meta');
+ expect(filter.meta).toHaveProperty('index', '1234');
+ expect(filter.range).toHaveProperty('ip');
+ expect(filter.range.ip).toHaveProperty('gte', '67.129.65.192');
+ expect(filter.range.ip).toHaveProperty('lte', '67.129.65.223');
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.ts
index 83769578725f2..803f6d97ae42d 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.ts
@@ -17,13 +17,13 @@
* under the License.
*/
-import { buildRangeFilter, RangeFilterParams } from '@kbn/es-query';
import { CidrMask } from '../../../utils/cidr_mask';
import { IBucketAggConfig } from '../_bucket_agg_type';
import { IpRangeKey } from '../ip_range';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterIpRange = (aggConfig: IBucketAggConfig, key: IpRangeKey) => {
- let range: RangeFilterParams;
+ let range: esFilters.RangeFilterParams;
if (key.type === 'mask') {
range = new CidrMask(key.mask).getRange();
@@ -34,7 +34,7 @@ export const createFilterIpRange = (aggConfig: IBucketAggConfig, key: IpRangeKey
};
}
- return buildRangeFilter(
+ return esFilters.buildRangeFilter(
aggConfig.params.field,
{ gte: range.from, lte: range.to },
aggConfig.getIndexPattern()
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/range.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/range.test.ts
new file mode 100644
index 0000000000000..04476ba62ccd5
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/range.test.ts
@@ -0,0 +1,74 @@
+/*
+ * 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 { createFilterRange } from './range';
+import { BytesFormat } from '../../../../../../plugins/data/common';
+import { AggConfigs } from '../../agg_configs';
+import { BUCKET_TYPES } from '../bucket_agg_types';
+
+jest.mock('ui/new_platform');
+
+describe('AggConfig Filters', () => {
+ describe('range', () => {
+ const getAggConfigs = () => {
+ const field = {
+ name: 'bytes',
+ format: new BytesFormat({}, () => {}),
+ };
+
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ id: BUCKET_TYPES.RANGE,
+ type: BUCKET_TYPES.RANGE,
+ schema: 'buckets',
+ params: {
+ field: 'bytes',
+ ranges: [{ from: 1024, to: 2048 }],
+ },
+ },
+ ],
+ null
+ );
+ };
+
+ it('should return a range filter for range agg', () => {
+ const aggConfigs = getAggConfigs();
+ const filter = createFilterRange(aggConfigs.aggs[0], { gte: 1024, lt: 2048.0 });
+
+ expect(filter).toHaveProperty('range');
+ expect(filter).toHaveProperty('meta');
+ expect(filter.meta).toHaveProperty('index', '1234');
+ expect(filter.range).toHaveProperty('bytes');
+ expect(filter.range.bytes).toHaveProperty('gte', 1024.0);
+ expect(filter.range.bytes).toHaveProperty('lt', 2048.0);
+ expect(filter.meta).toHaveProperty('formattedValue', '≥ 1,024 and < 2,048');
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/range.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/range.ts
index cf2c83884651a..929827c6e3fec 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/range.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/range.ts
@@ -17,11 +17,11 @@
* under the License.
*/
-import { buildRangeFilter } from '@kbn/es-query';
import { IBucketAggConfig } from '../_bucket_agg_type';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterRange = (aggConfig: IBucketAggConfig, params: any) => {
- return buildRangeFilter(
+ return esFilters.buildRangeFilter(
aggConfig.params.field,
params,
aggConfig.getIndexPattern(),
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/terms.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/terms.test.ts
new file mode 100644
index 0000000000000..42f8349d5a2a3
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/terms.test.ts
@@ -0,0 +1,118 @@
+/*
+ * 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 { createFilterTerms } from './terms';
+import { AggConfigs } from '../../agg_configs';
+import { BUCKET_TYPES } from '../bucket_agg_types';
+import { esFilters } from '../../../../../../plugins/data/public';
+
+jest.mock('ui/new_platform');
+
+describe('AggConfig Filters', () => {
+ describe('terms', () => {
+ const getAggConfigs = (aggs: Array>) => {
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ const field = {
+ name: 'field',
+ indexPattern,
+ };
+
+ return new AggConfigs(indexPattern, aggs, null);
+ };
+
+ it('should return a match_phrase filter for terms', () => {
+ const aggConfigs = getAggConfigs([
+ { type: BUCKET_TYPES.TERMS, schema: 'segment', params: { field: 'field' } },
+ ]);
+
+ const filter = createFilterTerms(aggConfigs.aggs[0], 'apache', {}) as esFilters.Filter;
+
+ expect(filter).toHaveProperty('query');
+ expect(filter.query).toHaveProperty('match_phrase');
+ expect(filter.query.match_phrase).toHaveProperty('field');
+ expect(filter.query.match_phrase.field).toBe('apache');
+ expect(filter).toHaveProperty('meta');
+ expect(filter.meta).toHaveProperty('index', '1234');
+ });
+
+ it('should set query to true or false for boolean filter', () => {
+ const aggConfigs = getAggConfigs([
+ { type: BUCKET_TYPES.TERMS, schema: 'segment', params: { field: 'field' } },
+ ]);
+
+ const filterFalse = createFilterTerms(aggConfigs.aggs[0], '', {}) as esFilters.Filter;
+
+ expect(filterFalse).toHaveProperty('query');
+ expect(filterFalse.query).toHaveProperty('match_phrase');
+ expect(filterFalse.query.match_phrase).toHaveProperty('field');
+ expect(filterFalse.query.match_phrase.field).toBeFalsy();
+
+ const filterTrue = createFilterTerms(aggConfigs.aggs[0], '1', {}) as esFilters.Filter;
+
+ expect(filterTrue).toHaveProperty('query');
+ expect(filterTrue.query).toHaveProperty('match_phrase');
+ expect(filterTrue.query.match_phrase).toHaveProperty('field');
+ expect(filterTrue.query.match_phrase.field).toBeTruthy();
+ });
+ //
+ it('should generate correct __missing__ filter', () => {
+ const aggConfigs = getAggConfigs([
+ { type: BUCKET_TYPES.TERMS, schema: 'segment', params: { field: 'field' } },
+ ]);
+ const filter = createFilterTerms(
+ aggConfigs.aggs[0],
+ '__missing__',
+ {}
+ ) as esFilters.ExistsFilter;
+
+ expect(filter).toHaveProperty('exists');
+ expect(filter.exists).toHaveProperty('field', 'field');
+ expect(filter).toHaveProperty('meta');
+ expect(filter.meta).toHaveProperty('index', '1234');
+ expect(filter.meta).toHaveProperty('negate', true);
+ });
+ //
+ it('should generate correct __other__ filter', () => {
+ const aggConfigs = getAggConfigs([
+ { type: BUCKET_TYPES.TERMS, schema: 'segment', params: { field: 'field' } },
+ ]);
+
+ const [filter] = createFilterTerms(aggConfigs.aggs[0], '__other__', {
+ terms: ['apache'],
+ }) as esFilters.Filter[];
+
+ expect(filter).toHaveProperty('query');
+ expect(filter.query).toHaveProperty('bool');
+ expect(filter.query.bool).toHaveProperty('should');
+ expect(filter.query.bool.should[0]).toHaveProperty('match_phrase');
+ expect(filter.query.bool.should[0].match_phrase).toHaveProperty('field', 'apache');
+ expect(filter).toHaveProperty('meta');
+ expect(filter.meta).toHaveProperty('index', '1234');
+ expect(filter.meta).toHaveProperty('negate', true);
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/terms.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/terms.ts
index e5d4406c752c7..5bd770e672786 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/terms.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/terms.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { Filter, buildPhraseFilter, buildPhrasesFilter, buildExistsFilter } from '@kbn/es-query';
import { IBucketAggConfig } from '../_bucket_agg_type';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterTerms = (aggConfig: IBucketAggConfig, key: string, params: any) => {
const field = aggConfig.params.field;
@@ -27,20 +27,20 @@ export const createFilterTerms = (aggConfig: IBucketAggConfig, key: string, para
if (key === '__other__') {
const terms = params.terms;
- const phraseFilter = buildPhrasesFilter(field, terms, indexPattern);
+ const phraseFilter = esFilters.buildPhrasesFilter(field, terms, indexPattern);
phraseFilter.meta.negate = true;
- const filters: Filter[] = [phraseFilter];
+ const filters: esFilters.Filter[] = [phraseFilter];
if (terms.some((term: string) => term === '__missing__')) {
- filters.push(buildExistsFilter(field, indexPattern));
+ filters.push(esFilters.buildExistsFilter(field, indexPattern));
}
return filters;
} else if (key === '__missing__') {
- const existsFilter = buildExistsFilter(field, indexPattern);
+ const existsFilter = esFilters.buildExistsFilter(field, indexPattern);
existsFilter.meta.negate = true;
return existsFilter;
}
- return buildPhraseFilter(field, key, indexPattern);
+ return esFilters.buildPhraseFilter(field, key, indexPattern);
};
diff --git a/src/legacy/ui/public/agg_types/buckets/date_histogram.ts b/src/legacy/ui/public/agg_types/buckets/date_histogram.ts
index 4c2e67f758a7e..e86d561a1c79b 100644
--- a/src/legacy/ui/public/agg_types/buckets/date_histogram.ts
+++ b/src/legacy/ui/public/agg_types/buckets/date_histogram.ts
@@ -32,7 +32,6 @@ import { ScaleMetricsParamEditor } from '../../vis/editors/default/controls/scal
import { dateHistogramInterval } from '../../../../core_plugins/data/public';
import { writeParams } from '../agg_params';
import { AggConfigs } from '../agg_configs';
-import { AggConfig } from '../agg_config';
import { isMetricAggType } from '../metrics/metric_agg_type';
import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common';
@@ -189,7 +188,7 @@ export const dateHistogramBucketAgg = new BucketAggType isMetricAggType(a.type));
- const all = _.every(metrics, (a: AggConfig) => {
+ const all = _.every(metrics, (a: IBucketAggConfig) => {
const { type } = a;
if (isMetricAggType(type)) {
diff --git a/src/legacy/ui/public/agg_types/buckets/date_range.test.ts b/src/legacy/ui/public/agg_types/buckets/date_range.test.ts
new file mode 100644
index 0000000000000..7d9fe002636a2
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/date_range.test.ts
@@ -0,0 +1,112 @@
+/*
+ * 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 { AggConfigs } from '../agg_configs';
+import { BUCKET_TYPES } from './bucket_agg_types';
+import { npStart } from 'ui/new_platform';
+
+jest.mock('ui/new_platform');
+
+describe('date_range params', () => {
+ const getAggConfigs = (params: Record = {}, hasIncludeTypeMeta: boolean = true) => {
+ const field = {
+ name: 'bytes',
+ };
+
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ typeMeta: hasIncludeTypeMeta
+ ? {
+ aggs: {
+ date_range: {
+ bytes: {
+ time_zone: 'defaultTimeZone',
+ },
+ },
+ },
+ }
+ : undefined,
+ } as any;
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ id: BUCKET_TYPES.DATE_RANGE,
+ type: BUCKET_TYPES.DATE_RANGE,
+ schema: 'buckets',
+ params,
+ },
+ ],
+ null
+ );
+ };
+
+ describe('getKey', () => {
+ it('should return object', () => {
+ const aggConfigs = getAggConfigs();
+ const dateRange = aggConfigs.aggs[0];
+ const bucket = { from: 'from-date', to: 'to-date', key: 'from-dateto-date' };
+
+ expect(dateRange.getKey(bucket)).toEqual({ from: 'from-date', to: 'to-date' });
+ });
+ });
+
+ describe('time_zone', () => {
+ it('should use the specified time_zone', () => {
+ const aggConfigs = getAggConfigs({
+ time_zone: 'Europe/Minsk',
+ field: 'bytes',
+ });
+ const dateRange = aggConfigs.aggs[0];
+ const params = dateRange.toDsl()[BUCKET_TYPES.DATE_RANGE];
+
+ expect(params.time_zone).toBe('Europe/Minsk');
+ });
+
+ it('should use the fixed time_zone from the index pattern typeMeta', () => {
+ const aggConfigs = getAggConfigs({
+ field: 'bytes',
+ });
+ const dateRange = aggConfigs.aggs[0];
+ const params = dateRange.toDsl()[BUCKET_TYPES.DATE_RANGE];
+
+ expect(params.time_zone).toBe('defaultTimeZone');
+ });
+
+ it('should use the Kibana time_zone if no parameter specified', () => {
+ npStart.core.uiSettings.get = jest.fn(() => 'kibanaTimeZone');
+
+ const aggConfigs = getAggConfigs(
+ {
+ field: 'bytes',
+ },
+ false
+ );
+ const dateRange = aggConfigs.aggs[0];
+ const params = dateRange.toDsl()[BUCKET_TYPES.DATE_RANGE];
+
+ expect(params.time_zone).toBe('kibanaTimeZone');
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/date_range.ts b/src/legacy/ui/public/agg_types/buckets/date_range.ts
index dd7f0cb972ae2..4de6002e2e374 100644
--- a/src/legacy/ui/public/agg_types/buckets/date_range.ts
+++ b/src/legacy/ui/public/agg_types/buckets/date_range.ts
@@ -21,9 +21,8 @@ import moment from 'moment-timezone';
import { i18n } from '@kbn/i18n';
import { npStart } from 'ui/new_platform';
import { BUCKET_TYPES } from './bucket_agg_types';
-import { BucketAggType } from './_bucket_agg_type';
+import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
import { createFilterDateRange } from './create_filter/date_range';
-import { AggConfig } from '../agg_config';
import { FieldFormat } from '../../../../../plugins/data/common/field_formats';
import { DateRangesParamEditor } from '../../vis/editors/default/controls/date_ranges';
@@ -64,7 +63,7 @@ export const dateRangeBucketAgg = new BucketAggType({
name: 'field',
type: 'field',
filterFieldTypes: KBN_FIELD_TYPES.DATE,
- default(agg: AggConfig) {
+ default(agg: IBucketAggConfig) {
return agg.getIndexPattern().timeFieldName;
},
},
@@ -83,7 +82,7 @@ export const dateRangeBucketAgg = new BucketAggType({
default: undefined,
// Implimentation method is the same as that of date_histogram
serialize: () => undefined,
- write: (agg: AggConfig, output: Record) => {
+ write: (agg: IBucketAggConfig, output: Record) => {
const field = agg.getParam('field');
let tz = agg.getParam('time_zone');
diff --git a/src/legacy/ui/public/agg_types/buckets/filters.ts b/src/legacy/ui/public/agg_types/buckets/filters.ts
index f0450f220f610..44a97abb7a1d7 100644
--- a/src/legacy/ui/public/agg_types/buckets/filters.ts
+++ b/src/legacy/ui/public/agg_types/buckets/filters.ts
@@ -21,7 +21,6 @@ import _ from 'lodash';
import angular from 'angular';
import { i18n } from '@kbn/i18n';
-import { Storage } from 'ui/storage';
import chrome from 'ui/chrome';
import { buildEsQuery } from '@kbn/es-query';
@@ -29,6 +28,7 @@ import { FiltersParamEditor, FilterValue } from '../../vis/editors/default/contr
import { createFilterFilters } from './create_filter/filters';
import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
import { setup as data } from '../../../../core_plugins/data/public/legacy';
+import { Storage } from '../../../../../plugins/kibana_utils/public';
const { getQueryLog } = data.query.helpers;
const config = chrome.getUiSettingsClient();
diff --git a/src/legacy/ui/public/agg_types/buckets/geo_hash.test.ts b/src/legacy/ui/public/agg_types/buckets/geo_hash.test.ts
new file mode 100644
index 0000000000000..5c599f16e09c2
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/geo_hash.test.ts
@@ -0,0 +1,216 @@
+/*
+ * 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 { geoHashBucketAgg, IBucketGeoHashGridAggConfig } from './geo_hash';
+import { AggConfigs } from '../agg_configs';
+import { BUCKET_TYPES } from './bucket_agg_types';
+
+jest.mock('ui/new_platform');
+
+describe('Geohash Agg', () => {
+ const getAggConfigs = (params?: Record) => {
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ const field = {
+ name: 'location',
+ indexPattern,
+ };
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ id: BUCKET_TYPES.GEOHASH_GRID,
+ type: BUCKET_TYPES.GEOHASH_GRID,
+ schema: 'segment',
+ params: {
+ field: {
+ name: 'location',
+ },
+ isFilteredByCollar: true,
+ useGeocentroid: true,
+ mapZoom: 10,
+ mapBounds: {
+ top_left: { lat: 1.0, lon: -1.0 },
+ bottom_right: { lat: -1.0, lon: 1.0 },
+ },
+ ...params,
+ },
+ },
+ ],
+ null
+ );
+ };
+
+ describe('precision parameter', () => {
+ const PRECISION_PARAM_INDEX = 2;
+
+ let precisionParam: any;
+
+ beforeEach(() => {
+ precisionParam = geoHashBucketAgg.params[PRECISION_PARAM_INDEX];
+ });
+
+ it('should select precision parameter', () => {
+ expect(precisionParam.name).toEqual('precision');
+ });
+
+ describe('precision parameter write', () => {
+ const zoomToGeoHashPrecision: Record = {
+ 0: 1,
+ 1: 2,
+ 2: 2,
+ 3: 2,
+ 4: 3,
+ 5: 3,
+ 6: 4,
+ 7: 4,
+ 8: 4,
+ 9: 5,
+ 10: 5,
+ 11: 6,
+ 12: 6,
+ 13: 6,
+ 14: 7,
+ 15: 7,
+ 16: 8,
+ 17: 8,
+ 18: 8,
+ 19: 9,
+ 20: 9,
+ 21: 10,
+ };
+
+ Object.keys(zoomToGeoHashPrecision).forEach((zoomLevel: string) => {
+ it(`zoom level ${zoomLevel} should correspond to correct geohash-precision`, () => {
+ const aggConfigs = getAggConfigs({
+ autoPrecision: true,
+ mapZoom: zoomLevel,
+ });
+
+ const { [BUCKET_TYPES.GEOHASH_GRID]: params } = aggConfigs.aggs[0].toDsl();
+
+ expect(params.precision).toEqual(zoomToGeoHashPrecision[zoomLevel]);
+ });
+ });
+ });
+ });
+
+ describe('getRequestAggs', () => {
+ describe('initial aggregation creation', () => {
+ let aggConfigs: AggConfigs;
+ let geoHashGridAgg: IBucketGeoHashGridAggConfig;
+
+ beforeEach(() => {
+ aggConfigs = getAggConfigs();
+ geoHashGridAgg = aggConfigs.aggs[0] as IBucketGeoHashGridAggConfig;
+ });
+
+ it('should create filter, geohash_grid, and geo_centroid aggregations', () => {
+ const requestAggs = geoHashBucketAgg.getRequestAggs(
+ geoHashGridAgg
+ ) as IBucketGeoHashGridAggConfig[];
+
+ expect(requestAggs.length).toEqual(3);
+ expect(requestAggs[0].type.name).toEqual('filter');
+ expect(requestAggs[1].type.name).toEqual('geohash_grid');
+ expect(requestAggs[2].type.name).toEqual('geo_centroid');
+ });
+
+ it('should set mapCollar in vis session state', () => {
+ const [, geoHashAgg] = geoHashBucketAgg.getRequestAggs(
+ geoHashGridAgg
+ ) as IBucketGeoHashGridAggConfig[];
+
+ expect(geoHashAgg).toHaveProperty('lastMapCollar');
+ expect(geoHashAgg.lastMapCollar).toHaveProperty('top_left');
+ expect(geoHashAgg.lastMapCollar).toHaveProperty('bottom_right');
+ expect(geoHashAgg.lastMapCollar).toHaveProperty('zoom');
+ });
+ });
+ });
+
+ describe('aggregation options', () => {
+ it('should only create geohash_grid and geo_centroid aggregations when isFilteredByCollar is false', () => {
+ const aggConfigs = getAggConfigs({ isFilteredByCollar: false });
+ const requestAggs = geoHashBucketAgg.getRequestAggs(aggConfigs
+ .aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+
+ expect(requestAggs.length).toEqual(2);
+ expect(requestAggs[0].type.name).toEqual('geohash_grid');
+ expect(requestAggs[1].type.name).toEqual('geo_centroid');
+ });
+
+ it('should only create filter and geohash_grid aggregations when useGeocentroid is false', () => {
+ const aggConfigs = getAggConfigs({ useGeocentroid: false });
+ const requestAggs = geoHashBucketAgg.getRequestAggs(aggConfigs
+ .aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+
+ expect(requestAggs.length).toEqual(2);
+ expect(requestAggs[0].type.name).toEqual('filter');
+ expect(requestAggs[1].type.name).toEqual('geohash_grid');
+ });
+ });
+
+ describe('aggregation creation after map interaction', () => {
+ let originalRequestAggs: IBucketGeoHashGridAggConfig[];
+
+ beforeEach(() => {
+ originalRequestAggs = geoHashBucketAgg.getRequestAggs(getAggConfigs()
+ .aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+ });
+
+ it('should change geo_bounding_box filter aggregation and vis session state when map movement is outside map collar', () => {
+ const [, geoBoxingBox] = geoHashBucketAgg.getRequestAggs(getAggConfigs({
+ mapBounds: {
+ top_left: { lat: 10.0, lon: -10.0 },
+ bottom_right: { lat: 9.0, lon: -9.0 },
+ },
+ }).aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+
+ expect(originalRequestAggs[1].params).not.toEqual(geoBoxingBox.params);
+ });
+
+ it('should not change geo_bounding_box filter aggregation and vis session state when map movement is within map collar', () => {
+ const [, geoBoxingBox] = geoHashBucketAgg.getRequestAggs(getAggConfigs({
+ mapBounds: {
+ top_left: { lat: 1, lon: -1 },
+ bottom_right: { lat: -1, lon: 1 },
+ },
+ }).aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+
+ expect(originalRequestAggs[1].params).toEqual(geoBoxingBox.params);
+ });
+
+ it('should change geo_bounding_box filter aggregation and vis session state when map zoom level changes', () => {
+ const [, geoBoxingBox] = geoHashBucketAgg.getRequestAggs(getAggConfigs({
+ mapZoom: -1,
+ }).aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+
+ expect(originalRequestAggs[1].lastMapCollar).not.toEqual(geoBoxingBox.lastMapCollar);
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/geo_hash.ts b/src/legacy/ui/public/agg_types/buckets/geo_hash.ts
index 555aa94b636b8..1716891231b83 100644
--- a/src/legacy/ui/public/agg_types/buckets/geo_hash.ts
+++ b/src/legacy/ui/public/agg_types/buckets/geo_hash.ts
@@ -26,7 +26,6 @@ import { IsFilteredByCollarParamEditor } from '../../vis/editors/default/control
import { PrecisionParamEditor } from '../../vis/editors/default/controls/precision';
import { geohashColumns } from '../../utils/decode_geo_hash';
import { AggGroupNames } from '../../vis/editors/default/agg_groups';
-import { AggConfig } from '../agg_config';
import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common';
// @ts-ignore
@@ -143,7 +142,7 @@ export const geoHashBucketAgg = new BucketAggType({
},
],
getRequestAggs(agg) {
- const aggs: AggConfig[] = [];
+ const aggs: IBucketAggConfig[] = [];
const params = agg.params;
if (params.isFilteredByCollar && agg.getField()) {
diff --git a/src/legacy/ui/public/agg_types/buckets/histogram.test.ts b/src/legacy/ui/public/agg_types/buckets/histogram.test.ts
new file mode 100644
index 0000000000000..338af2e41cb88
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/histogram.test.ts
@@ -0,0 +1,292 @@
+/*
+ * 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 { npStart } from 'ui/new_platform';
+import { AggConfigs } from '../index';
+import { BUCKET_TYPES } from './bucket_agg_types';
+import { IBucketHistogramAggConfig, histogramBucketAgg, AutoBounds } from './histogram';
+import { BucketAggType } from './_bucket_agg_type';
+
+jest.mock('ui/new_platform');
+
+describe('Histogram Agg', () => {
+ const getAggConfigs = (params: Record = {}) => {
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ const field = {
+ name: 'field',
+ indexPattern,
+ };
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ field: {
+ name: 'field',
+ },
+ id: 'test',
+ type: BUCKET_TYPES.HISTOGRAM,
+ schema: 'segment',
+ params,
+ },
+ ],
+ null
+ );
+ };
+
+ const getParams = (options: Record) => {
+ const aggConfigs = getAggConfigs({
+ ...options,
+ field: {
+ name: 'field',
+ },
+ });
+ return aggConfigs.aggs[0].toDsl()[BUCKET_TYPES.HISTOGRAM];
+ };
+
+ describe('ordered', () => {
+ let histogramType: BucketAggType;
+
+ beforeEach(() => {
+ histogramType = histogramBucketAgg;
+ });
+
+ it('is ordered', () => {
+ expect(histogramType.ordered).toBeDefined();
+ });
+
+ it('is not ordered by date', () => {
+ expect(histogramType.ordered).not.toHaveProperty('date');
+ });
+ });
+
+ describe('params', () => {
+ describe('intervalBase', () => {
+ it('should not be written to the DSL', () => {
+ const aggConfigs = getAggConfigs({
+ intervalBase: 100,
+ field: {
+ name: 'field',
+ },
+ });
+ const { [BUCKET_TYPES.HISTOGRAM]: params } = aggConfigs.aggs[0].toDsl();
+
+ expect(params).not.toHaveProperty('intervalBase');
+ });
+ });
+
+ describe('interval', () => {
+ it('accepts a whole number', () => {
+ const params = getParams({
+ interval: 100,
+ });
+
+ expect(params).toHaveProperty('interval', 100);
+ });
+
+ it('accepts a decimal number', function() {
+ const params = getParams({
+ interval: 0.1,
+ });
+
+ expect(params).toHaveProperty('interval', 0.1);
+ });
+
+ it('accepts a decimal number string', function() {
+ const params = getParams({
+ interval: '0.1',
+ });
+
+ expect(params).toHaveProperty('interval', 0.1);
+ });
+
+ it('accepts a whole number string', function() {
+ const params = getParams({
+ interval: '10',
+ });
+
+ expect(params).toHaveProperty('interval', 10);
+ });
+
+ it('fails on non-numeric values', function() {
+ const params = getParams({
+ interval: [],
+ });
+
+ expect(params.interval).toBeNaN();
+ });
+
+ describe('interval scaling', () => {
+ const getInterval = (
+ maxBars: number,
+ params?: Record,
+ autoBounds?: AutoBounds
+ ) => {
+ const aggConfigs = getAggConfigs({
+ ...params,
+ field: {
+ name: 'field',
+ },
+ });
+ const aggConfig = aggConfigs.aggs[0] as IBucketHistogramAggConfig;
+
+ if (autoBounds) {
+ aggConfig.setAutoBounds(autoBounds);
+ }
+
+ // mock histogram:maxBars value;
+ npStart.core.uiSettings.get = jest.fn(() => maxBars);
+
+ return aggConfig.write(aggConfigs).params;
+ };
+
+ it('will respect the histogram:maxBars setting', () => {
+ const params = getInterval(
+ 5,
+ { interval: 5 },
+ {
+ min: 0,
+ max: 10000,
+ }
+ );
+
+ expect(params).toHaveProperty('interval', 2000);
+ });
+
+ it('will return specified interval, if bars are below histogram:maxBars config', () => {
+ const params = getInterval(100, { interval: 5 });
+
+ expect(params).toHaveProperty('interval', 5);
+ });
+
+ it('will set to intervalBase if interval is below base', () => {
+ const params = getInterval(1000, { interval: 3, intervalBase: 8 });
+
+ expect(params).toHaveProperty('interval', 8);
+ });
+
+ it('will round to nearest intervalBase multiple if interval is above base', () => {
+ const roundUp = getInterval(1000, { interval: 46, intervalBase: 10 });
+ expect(roundUp).toHaveProperty('interval', 50);
+
+ const roundDown = getInterval(1000, { interval: 43, intervalBase: 10 });
+ expect(roundDown).toHaveProperty('interval', 40);
+ });
+
+ it('will not change interval if it is a multiple of base', () => {
+ const output = getInterval(1000, { interval: 35, intervalBase: 5 });
+
+ expect(output).toHaveProperty('interval', 35);
+ });
+
+ it('will round to intervalBase after scaling histogram:maxBars', () => {
+ const output = getInterval(100, { interval: 5, intervalBase: 6 }, { min: 0, max: 1000 });
+
+ // 100 buckets in 0 to 1000 would result in an interval of 10, so we should
+ // round to the next multiple of 6 -> 12
+ expect(output).toHaveProperty('interval', 12);
+ });
+ });
+
+ describe('min_doc_count', () => {
+ let output: Record;
+
+ it('casts true values to 0', () => {
+ output = getParams({ min_doc_count: true });
+ expect(output).toHaveProperty('min_doc_count', 0);
+
+ output = getParams({ min_doc_count: 'yes' });
+ expect(output).toHaveProperty('min_doc_count', 0);
+
+ output = getParams({ min_doc_count: 1 });
+ expect(output).toHaveProperty('min_doc_count', 0);
+
+ output = getParams({ min_doc_count: {} });
+ expect(output).toHaveProperty('min_doc_count', 0);
+ });
+
+ it('writes 1 for falsy values', () => {
+ output = getParams({ min_doc_count: '' });
+ expect(output).toHaveProperty('min_doc_count', 1);
+
+ output = getParams({ min_doc_count: null });
+ expect(output).toHaveProperty('min_doc_count', 1);
+
+ output = getParams({ min_doc_count: undefined });
+ expect(output).toHaveProperty('min_doc_count', 1);
+ });
+ });
+
+ describe('extended_bounds', function() {
+ it('does not write when only eb.min is set', function() {
+ const output = getParams({
+ has_extended_bounds: true,
+ extended_bounds: { min: 0 },
+ });
+ expect(output).not.toHaveProperty('extended_bounds');
+ });
+
+ it('does not write when only eb.max is set', function() {
+ const output = getParams({
+ has_extended_bounds: true,
+ extended_bounds: { max: 0 },
+ });
+
+ expect(output).not.toHaveProperty('extended_bounds');
+ });
+
+ it('writes when both eb.min and eb.max are set', function() {
+ const output = getParams({
+ has_extended_bounds: true,
+ extended_bounds: { min: 99, max: 100 },
+ });
+
+ expect(output.extended_bounds).toHaveProperty('min', 99);
+ expect(output.extended_bounds).toHaveProperty('max', 100);
+ });
+
+ it('does not write when nothing is set', function() {
+ const output = getParams({
+ has_extended_bounds: true,
+ extended_bounds: {},
+ });
+
+ expect(output).not.toHaveProperty('extended_bounds');
+ });
+
+ it('does not write when has_extended_bounds is false', function() {
+ const output = getParams({
+ has_extended_bounds: false,
+ extended_bounds: { min: 99, max: 100 },
+ });
+
+ expect(output).not.toHaveProperty('extended_bounds');
+ });
+ });
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/histogram.ts b/src/legacy/ui/public/agg_types/buckets/histogram.ts
index 23edefc67d506..fba2f47010c34 100644
--- a/src/legacy/ui/public/agg_types/buckets/histogram.ts
+++ b/src/legacy/ui/public/agg_types/buckets/histogram.ts
@@ -21,18 +21,17 @@ import _ from 'lodash';
import { i18n } from '@kbn/i18n';
import { toastNotifications } from 'ui/notify';
-import chrome from '../../chrome';
+import { npStart } from 'ui/new_platform';
import { BucketAggType, IBucketAggConfig, BucketAggParam } from './_bucket_agg_type';
import { createFilterHistogram } from './create_filter/histogram';
import { NumberIntervalParamEditor } from '../../vis/editors/default/controls/number_interval';
import { MinDocCountParamEditor } from '../../vis/editors/default/controls/min_doc_count';
import { HasExtendedBoundsParamEditor } from '../../vis/editors/default/controls/has_extended_bounds';
import { ExtendedBoundsParamEditor } from '../../vis/editors/default/controls/extended_bounds';
-import { AggConfig } from '../agg_config';
import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common';
import { BUCKET_TYPES } from './bucket_agg_types';
-interface AutoBounds {
+export interface AutoBounds {
min: number;
max: number;
}
@@ -42,7 +41,8 @@ export interface IBucketHistogramAggConfig extends IBucketAggConfig {
getAutoBounds: () => AutoBounds;
}
-const config = chrome.getUiSettingsClient();
+const getUIConfig = () => npStart.core.uiSettings;
+
export const histogramBucketAgg = new BucketAggType({
name: BUCKET_TYPES.HISTOGRAM,
title: i18n.translate('common.ui.aggTypes.buckets.histogramTitle', {
@@ -135,25 +135,30 @@ export const histogramBucketAgg = new BucketAggType({
if (interval <= 0) {
interval = 1;
}
+ const autoBounds = aggConfig.getAutoBounds();
// ensure interval does not create too many buckets and crash browser
- if (aggConfig.getAutoBounds()) {
- const range = aggConfig.getAutoBounds().max - aggConfig.getAutoBounds().min;
+ if (autoBounds) {
+ const range = autoBounds.max - autoBounds.min;
const bars = range / interval;
+
+ const config = getUIConfig();
if (bars > config.get('histogram:maxBars')) {
const minInterval = range / config.get('histogram:maxBars');
+
// Round interval by order of magnitude to provide clean intervals
// Always round interval up so there will always be less buckets than histogram:maxBars
const orderOfMagnitude = Math.pow(10, Math.floor(Math.log10(minInterval)));
let roundInterval = orderOfMagnitude;
+
while (roundInterval < minInterval) {
roundInterval += orderOfMagnitude;
}
interval = roundInterval;
}
}
-
const base = aggConfig.params.intervalBase;
+
if (base) {
if (interval < base) {
// In case the specified interval is below the base, just increase it to it's base
@@ -171,7 +176,7 @@ export const histogramBucketAgg = new BucketAggType({
name: 'min_doc_count',
default: false,
editorComponent: MinDocCountParamEditor,
- write(aggConfig: AggConfig, output: Record) {
+ write(aggConfig: IBucketAggConfig, output: Record) {
if (aggConfig.params.min_doc_count) {
output.params.min_doc_count = 0;
} else {
@@ -192,14 +197,14 @@ export const histogramBucketAgg = new BucketAggType({
max: '',
},
editorComponent: ExtendedBoundsParamEditor,
- write(aggConfig: AggConfig, output: Record) {
+ write(aggConfig: IBucketAggConfig, output: Record) {
const { min, max } = aggConfig.params.extended_bounds;
if (aggConfig.params.has_extended_bounds && (min || min === 0) && (max || max === 0)) {
output.params.extended_bounds = { min, max };
}
},
- shouldShow: (aggConfig: AggConfig) => aggConfig.params.has_extended_bounds,
+ shouldShow: (aggConfig: IBucketAggConfig) => aggConfig.params.has_extended_bounds,
},
],
});
diff --git a/src/legacy/ui/public/agg_types/buckets/migrate_include_exclude_format.ts b/src/legacy/ui/public/agg_types/buckets/migrate_include_exclude_format.ts
index 2bf0930d37684..e4527ff87f48c 100644
--- a/src/legacy/ui/public/agg_types/buckets/migrate_include_exclude_format.ts
+++ b/src/legacy/ui/public/agg_types/buckets/migrate_include_exclude_format.ts
@@ -18,7 +18,6 @@
*/
import { isString, isObject } from 'lodash';
-import { AggConfig } from 'ui/agg_types';
import { IBucketAggConfig, BucketAggType, BucketAggParam } from './_bucket_agg_type';
export const isType = (type: string) => {
@@ -32,12 +31,16 @@ export const isType = (type: string) => {
export const isStringType = isType('string');
export const migrateIncludeExcludeFormat = {
- serialize(this: BucketAggParam, value: any, agg: AggConfig) {
+ serialize(this: BucketAggParam, value: any, agg: IBucketAggConfig) {
if (this.shouldShow && !this.shouldShow(agg)) return;
if (!value || isString(value)) return value;
else return value.pattern;
},
- write(this: BucketAggType, aggConfig: AggConfig, output: Record) {
+ write(
+ this: BucketAggType,
+ aggConfig: IBucketAggConfig,
+ output: Record
+ ) {
const value = aggConfig.getParam(this.name);
if (isObject(value)) {
diff --git a/src/legacy/ui/public/agg_types/buckets/range.test.ts b/src/legacy/ui/public/agg_types/buckets/range.test.ts
new file mode 100644
index 0000000000000..f7cae60cce773
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/range.test.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 { AggConfigs } from '../agg_configs';
+import { BUCKET_TYPES } from './bucket_agg_types';
+import { NumberFormat } from '../../../../../plugins/data/common/';
+
+jest.mock('ui/new_platform');
+
+const buckets = [
+ {
+ to: 1024,
+ to_as_string: '1024.0',
+ doc_count: 20904,
+ },
+ {
+ from: 1024,
+ from_as_string: '1024.0',
+ to: 2560,
+ to_as_string: '2560.0',
+ doc_count: 23358,
+ },
+ {
+ from: 2560,
+ from_as_string: '2560.0',
+ doc_count: 174250,
+ },
+];
+
+describe('Range Agg', () => {
+ const getAggConfigs = () => {
+ const field = {
+ name: 'bytes',
+ format: new NumberFormat(
+ {
+ pattern: '0,0.[000] b',
+ },
+ () => {}
+ ),
+ };
+
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ type: BUCKET_TYPES.RANGE,
+ schema: 'segment',
+ params: {
+ field: 'bytes',
+ ranges: [{ from: 0, to: 1000 }, { from: 1000, to: 2000 }],
+ },
+ },
+ ],
+ null
+ );
+ };
+
+ describe('formating', () => {
+ it('formats bucket keys properly', () => {
+ const aggConfigs = getAggConfigs();
+ const agg = aggConfigs.aggs[0];
+
+ const format = (val: any) => agg.fieldFormatter()(agg.getKey(val));
+
+ expect(format(buckets[0])).toBe('≥ -∞ and < 1 KB');
+ expect(format(buckets[1])).toBe('≥ 1 KB and < 2.5 KB');
+ expect(format(buckets[2])).toBe('≥ 2.5 KB and < +∞');
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/significant_terms.test.ts b/src/legacy/ui/public/agg_types/buckets/significant_terms.test.ts
new file mode 100644
index 0000000000000..454f1bf70a790
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/significant_terms.test.ts
@@ -0,0 +1,110 @@
+/*
+ * 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 { AggConfigs } from '../index';
+import { BUCKET_TYPES } from './bucket_agg_types';
+import { significantTermsBucketAgg } from './significant_terms';
+
+jest.mock('ui/new_platform');
+
+describe('Significant Terms Agg', () => {
+ describe('order agg editor UI', () => {
+ describe('convert include/exclude from old format', () => {
+ const getAggConfigs = (params: Record = {}) => {
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ const field = {
+ name: 'field',
+ indexPattern,
+ };
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ id: 'test',
+ type: BUCKET_TYPES.SIGNIFICANT_TERMS,
+ schema: 'segment',
+ params,
+ },
+ ],
+ null
+ );
+ };
+
+ const testSerializeAndWrite = (aggs: AggConfigs) => {
+ const agg = aggs.aggs[0];
+ const { [BUCKET_TYPES.SIGNIFICANT_TERMS]: params } = agg.toDsl();
+
+ expect(params.field).toBe('field');
+ expect(params.include).toBe('404');
+ expect(params.exclude).toBe('400');
+ };
+
+ it('should generate correct label', () => {
+ const aggConfigs = getAggConfigs({
+ size: 'SIZE',
+ field: {
+ name: 'FIELD',
+ },
+ });
+ const label = significantTermsBucketAgg.makeLabel(aggConfigs.aggs[0]);
+
+ expect(label).toBe('Top SIZE unusual terms in FIELD');
+ });
+
+ it('should doesnt do anything with string type', () => {
+ const aggConfigs = getAggConfigs({
+ include: '404',
+ exclude: '400',
+ field: {
+ name: 'field',
+ type: 'string',
+ },
+ });
+
+ testSerializeAndWrite(aggConfigs);
+ });
+
+ it('should converts object to string type', () => {
+ const aggConfigs = getAggConfigs({
+ include: {
+ pattern: '404',
+ },
+ exclude: {
+ pattern: '400',
+ },
+ field: {
+ name: 'field',
+ type: 'string',
+ },
+ });
+
+ testSerializeAndWrite(aggConfigs);
+ });
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/buckets/terms.test.ts b/src/legacy/ui/public/agg_types/buckets/terms.test.ts
new file mode 100644
index 0000000000000..24ac332ae4d55
--- /dev/null
+++ b/src/legacy/ui/public/agg_types/buckets/terms.test.ts
@@ -0,0 +1,78 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { AggConfigs } from '../index';
+import { BUCKET_TYPES } from './bucket_agg_types';
+
+jest.mock('ui/new_platform');
+
+describe('Terms Agg', () => {
+ describe('order agg editor UI', () => {
+ const getAggConfigs = (params: Record = {}) => {
+ const indexPattern = {
+ id: '1234',
+ title: 'logstash-*',
+ fields: {
+ getByName: () => field,
+ filter: () => [field],
+ },
+ } as any;
+
+ const field = {
+ name: 'field',
+ indexPattern,
+ };
+
+ return new AggConfigs(
+ indexPattern,
+ [
+ {
+ id: 'test',
+ params,
+ type: BUCKET_TYPES.TERMS,
+ },
+ ],
+ null
+ );
+ };
+
+ it('converts object to string type', function() {
+ const aggConfigs = getAggConfigs({
+ include: {
+ pattern: '404',
+ },
+ exclude: {
+ pattern: '400',
+ },
+ field: {
+ name: 'field',
+ },
+ orderAgg: {
+ type: 'count',
+ },
+ });
+
+ const { [BUCKET_TYPES.TERMS]: params } = aggConfigs.aggs[0].toDsl();
+
+ expect(params.field).toBe('field');
+ expect(params.include).toBe('404');
+ expect(params.exclude).toBe('400');
+ });
+ });
+});
diff --git a/src/legacy/ui/public/agg_types/filter/prop_filter.test.ts b/src/legacy/ui/public/agg_types/filter/prop_filter.test.ts
index 0d32c9dc769da..431e1161e0dbd 100644
--- a/src/legacy/ui/public/agg_types/filter/prop_filter.test.ts
+++ b/src/legacy/ui/public/agg_types/filter/prop_filter.test.ts
@@ -27,7 +27,7 @@ describe('prop filter', () => {
nameFilter = propFilter('name');
});
- function getObjects(...names: string[]) {
+ const getObjects = (...names: string[]) => {
const count = new Map();
const objects = [];
@@ -41,8 +41,9 @@ describe('prop filter', () => {
});
count.set(name, count.get(name) + 1);
}
+
return objects;
- }
+ };
it('returns list when no filters are provided', () => {
const objects = getObjects('table', 'table', 'pie');
diff --git a/src/legacy/ui/public/agg_types/metrics/lib/make_nested_label.test.ts b/src/legacy/ui/public/agg_types/metrics/lib/make_nested_label.test.ts
index aed5bd630d3d2..479ff40b7c0ae 100644
--- a/src/legacy/ui/public/agg_types/metrics/lib/make_nested_label.test.ts
+++ b/src/legacy/ui/public/agg_types/metrics/lib/make_nested_label.test.ts
@@ -18,7 +18,7 @@
*/
import { makeNestedLabel } from './make_nested_label';
-import { IMetricAggConfig } from 'ui/agg_types/metrics/metric_agg_type';
+import { IMetricAggConfig } from '../metric_agg_type';
describe('metric agg make_nested_label', () => {
const generateAggConfig = (metricLabel: string): IMetricAggConfig => {
diff --git a/src/legacy/ui/public/agg_types/metrics/parent_pipeline.test.ts b/src/legacy/ui/public/agg_types/metrics/parent_pipeline.test.ts
index bf88adcee92b7..7c7a2a68cd7c5 100644
--- a/src/legacy/ui/public/agg_types/metrics/parent_pipeline.test.ts
+++ b/src/legacy/ui/public/agg_types/metrics/parent_pipeline.test.ts
@@ -22,8 +22,8 @@ import { derivativeMetricAgg } from './derivative';
import { cumulativeSumMetricAgg } from './cumulative_sum';
import { movingAvgMetricAgg } from './moving_avg';
import { serialDiffMetricAgg } from './serial_diff';
-import { AggConfigs } from 'ui/agg_types';
-import { IMetricAggConfig, MetricAggType } from 'ui/agg_types/metrics/metric_agg_type';
+import { AggConfigs } from '../agg_configs';
+import { IMetricAggConfig, MetricAggType } from './metric_agg_type';
jest.mock('../../vis/editors/default/schemas', () => {
class MockedSchemas {
diff --git a/src/legacy/ui/public/agg_types/metrics/sibling_pipeline.test.ts b/src/legacy/ui/public/agg_types/metrics/sibling_pipeline.test.ts
index a3381aca6f9e7..e038936de07d2 100644
--- a/src/legacy/ui/public/agg_types/metrics/sibling_pipeline.test.ts
+++ b/src/legacy/ui/public/agg_types/metrics/sibling_pipeline.test.ts
@@ -23,8 +23,8 @@ import { bucketAvgMetricAgg } from './bucket_avg';
import { bucketMinMetricAgg } from './bucket_min';
import { bucketMaxMetricAgg } from './bucket_max';
-import { AggConfigs } from 'ui/agg_types';
-import { IMetricAggConfig, MetricAggType } from 'ui/agg_types/metrics/metric_agg_type';
+import { AggConfigs } from '../agg_configs';
+import { IMetricAggConfig, MetricAggType } from './metric_agg_type';
jest.mock('../../vis/editors/default/schemas', () => {
class MockedSchemas {
diff --git a/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts b/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts
index ca81e8daee449..ae09b5cd78977 100644
--- a/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts
+++ b/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts
@@ -18,8 +18,8 @@
*/
import { IStdDevAggConfig, stdDeviationMetricAgg } from './std_deviation';
-import { AggConfigs } from 'ui/agg_types';
-import { METRIC_TYPES } from 'ui/agg_types/metrics/metric_agg_types';
+import { AggConfigs } from '../agg_configs';
+import { METRIC_TYPES } from './metric_agg_types';
jest.mock('ui/new_platform');
diff --git a/src/legacy/ui/public/agg_types/metrics/top_hit.test.ts b/src/legacy/ui/public/agg_types/metrics/top_hit.test.ts
index 4ed6fcdcf641b..e9d1ebb93d3ba 100644
--- a/src/legacy/ui/public/agg_types/metrics/top_hit.test.ts
+++ b/src/legacy/ui/public/agg_types/metrics/top_hit.test.ts
@@ -19,8 +19,8 @@
import { dropRight, last } from 'lodash';
import { topHitMetricAgg } from './top_hit';
-import { AggConfigs } from 'ui/agg_types';
-import { IMetricAggConfig } from 'ui/agg_types/metrics/metric_agg_type';
+import { AggConfigs } from '../agg_configs';
+import { IMetricAggConfig } from './metric_agg_type';
import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common';
jest.mock('ui/new_platform');
diff --git a/src/legacy/ui/public/agg_types/param_types/json.test.ts b/src/legacy/ui/public/agg_types/param_types/json.test.ts
index fb31385505a76..827299814c62a 100644
--- a/src/legacy/ui/public/agg_types/param_types/json.test.ts
+++ b/src/legacy/ui/public/agg_types/param_types/json.test.ts
@@ -19,7 +19,7 @@
import { BaseParamType } from './base';
import { JsonParamType } from './json';
-import { AggConfig } from 'ui/agg_types';
+import { AggConfig } from '../agg_config';
jest.mock('ui/new_platform');
@@ -28,13 +28,12 @@ describe('JSON', function() {
let aggConfig: AggConfig;
let output: Record;
- function initAggParam(config: Record = {}) {
- return new JsonParamType({
+ const initAggParam = (config: Record = {}) =>
+ new JsonParamType({
...config,
type: 'json',
name: paramName,
});
- }
beforeEach(function() {
aggConfig = { params: {} } as AggConfig;
diff --git a/src/legacy/ui/public/agg_types/param_types/string.test.ts b/src/legacy/ui/public/agg_types/param_types/string.test.ts
index 3d496ecf898e4..fd5ccebde993e 100644
--- a/src/legacy/ui/public/agg_types/param_types/string.test.ts
+++ b/src/legacy/ui/public/agg_types/param_types/string.test.ts
@@ -19,7 +19,7 @@
import { BaseParamType } from './base';
import { StringParamType } from './string';
-import { AggConfig } from 'ui/agg_types';
+import { AggConfig } from '../agg_config';
jest.mock('ui/new_platform');
@@ -28,13 +28,12 @@ describe('String', function() {
let aggConfig: AggConfig;
let output: Record;
- function initAggParam(config: Record = {}) {
- return new StringParamType({
+ const initAggParam = (config: Record = {}) =>
+ new StringParamType({
...config,
type: 'string',
name: paramName,
});
- }
beforeEach(() => {
aggConfig = { params: {} } as AggConfig;
diff --git a/src/legacy/ui/public/agg_types/utils.ts b/src/legacy/ui/public/agg_types/utils.ts
index c6452cf46e0c0..6721262d265f4 100644
--- a/src/legacy/ui/public/agg_types/utils.ts
+++ b/src/legacy/ui/public/agg_types/utils.ts
@@ -49,7 +49,7 @@ function isValidJson(value: string): boolean {
}
}
-function isValidInterval(value: string, baseInterval: string) {
+function isValidInterval(value: string, baseInterval?: string) {
if (baseInterval) {
return _parseWithBase(value, baseInterval);
} else {
diff --git a/src/legacy/ui/public/autoload/modules.js b/src/legacy/ui/public/autoload/modules.js
index d662d479fc86b..e1d897236297e 100644
--- a/src/legacy/ui/public/autoload/modules.js
+++ b/src/legacy/ui/public/autoload/modules.js
@@ -27,7 +27,6 @@ import '../promises';
import '../modals';
import '../state_management/app_state';
import '../state_management/global_state';
-import '../storage';
import '../style_compile';
import '../url';
import '../directives/watch_multi';
diff --git a/src/legacy/ui/public/capabilities/react/inject_ui_capabilities.test.tsx b/src/legacy/ui/public/capabilities/react/inject_ui_capabilities.test.tsx
index dccea2f61d567..ff46b6ec34a86 100644
--- a/src/legacy/ui/public/capabilities/react/inject_ui_capabilities.test.tsx
+++ b/src/legacy/ui/public/capabilities/react/inject_ui_capabilities.test.tsx
@@ -77,6 +77,7 @@ describe('injectUICapabilities', () => {
uiCapabilities: UICapabilities;
}
+ // eslint-disable-next-line react/prefer-stateless-function
class MyClassComponent extends React.Component {
public render() {
return {this.props.uiCapabilities.uiCapability2.nestedProp} ;
diff --git a/src/legacy/ui/public/capabilities/react/legacy/inject_ui_capabilities.test.tsx b/src/legacy/ui/public/capabilities/react/legacy/inject_ui_capabilities.test.tsx
index 21f96cf918afd..76f1dd8016313 100644
--- a/src/legacy/ui/public/capabilities/react/legacy/inject_ui_capabilities.test.tsx
+++ b/src/legacy/ui/public/capabilities/react/legacy/inject_ui_capabilities.test.tsx
@@ -77,6 +77,7 @@ describe('injectUICapabilities', () => {
uiCapabilities: UICapabilities;
}
+ // eslint-disable-next-line react/prefer-stateless-function
class MyClassComponent extends React.Component {
public render() {
return {this.props.uiCapabilities.uiCapability2.nestedProp} ;
diff --git a/src/legacy/ui/public/capabilities/react/ui_capabilities_provider.tsx b/src/legacy/ui/public/capabilities/react/ui_capabilities_provider.tsx
index fb6a1dc55c29f..3871147107439 100644
--- a/src/legacy/ui/public/capabilities/react/ui_capabilities_provider.tsx
+++ b/src/legacy/ui/public/capabilities/react/ui_capabilities_provider.tsx
@@ -17,22 +17,14 @@
* under the License.
*/
-import React, { ReactNode } from 'react';
+import React from 'react';
import { UICapabilitiesContext } from './ui_capabilities_context';
import { capabilities } from '..';
-interface Props {
- children: ReactNode;
-}
+export const UICapabilitiesProvider: React.SFC = props => (
+
+ {props.children}
+
+);
-export class UICapabilitiesProvider extends React.Component {
- public static displayName: string = 'UICapabilitiesProvider';
-
- public render() {
- return (
-
- {this.props.children}
-
- );
- }
-}
+UICapabilitiesProvider.displayName = 'UICapabilitiesProvider';
diff --git a/src/legacy/ui/public/chrome/chrome.js b/src/legacy/ui/public/chrome/chrome.js
index a5a0521013a6e..d644965e09225 100644
--- a/src/legacy/ui/public/chrome/chrome.js
+++ b/src/legacy/ui/public/chrome/chrome.js
@@ -26,7 +26,7 @@ import '../config';
import '../notify';
import '../private';
import '../promises';
-import '../storage';
+import '../directives/storage';
import '../directives/watch_multi';
import './services';
import '../react_components';
diff --git a/src/legacy/ui/public/chrome/directives/kbn_chrome.html b/src/legacy/ui/public/chrome/directives/kbn_chrome.html
index 541082e68de58..7738093fe9dea 100644
--- a/src/legacy/ui/public/chrome/directives/kbn_chrome.html
+++ b/src/legacy/ui/public/chrome/directives/kbn_chrome.html
@@ -1,4 +1,4 @@
-
+
{
const newPlatform = npStart.core;
const legacyMetadata = newPlatform.injectedMetadata.getLegacyMetadata();
@@ -187,6 +194,9 @@ const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart) => (
});
$rootScope.$on('$routeChangeSuccess', () => {
+ if (isDummyWrapperRoute($route)) {
+ return;
+ }
const current = $route.current || {};
if (breadcrumbSetSinceRouteChange || (current.$$route && current.$$route.redirectTo)) {
@@ -226,6 +236,9 @@ const $setupBadgeAutoClear = (newPlatform: CoreStart) => (
});
$rootScope.$on('$routeChangeSuccess', () => {
+ if (isDummyWrapperRoute($route)) {
+ return;
+ }
const current = $route.current || {};
if (badgeSetSinceRouteChange || (current.$$route && current.$$route.redirectTo)) {
@@ -270,10 +283,16 @@ const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => (
const $route = $injector.has('$route') ? $injector.get('$route') : {};
$rootScope.$on('$routeChangeStart', () => {
+ if (isDummyWrapperRoute($route)) {
+ return;
+ }
helpExtensionSetSinceRouteChange = false;
});
$rootScope.$on('$routeChangeSuccess', () => {
+ if (isDummyWrapperRoute($route)) {
+ return;
+ }
const current = $route.current || {};
if (helpExtensionSetSinceRouteChange || (current.$$route && current.$$route.redirectTo)) {
@@ -286,10 +305,15 @@ const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => (
const $setupUrlOverflowHandling = (newPlatform: CoreStart) => (
$location: ILocationService,
- $rootScope: IRootScopeService
+ $rootScope: IRootScopeService,
+ $injector: auto.IInjectorService
) => {
+ const $route = $injector.has('$route') ? $injector.get('$route') : {};
const urlOverflow = new UrlOverflowService();
const check = () => {
+ if (isDummyWrapperRoute($route)) {
+ return;
+ }
// disable long url checks when storing state in session storage
if (newPlatform.uiSettings.get('state:storeInSessionStorage')) {
return;
diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js
index 20ea9c9141aca..611a182cf5d7f 100644
--- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js
+++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js
@@ -36,9 +36,17 @@ export const npSetup = {
register: () => undefined,
get: () => null,
},
+ getExecutor: () => ({
+ interpreter: {
+ interpretAst: () => {},
+ },
+ }),
},
},
data: {
+ query: {
+ filterManager: sinon.fake(),
+ },
},
inspector: {
registerView: () => undefined,
@@ -73,6 +81,24 @@ export const npStart = {
},
data: {
getSuggestions: sinon.fake(),
+ query: {
+ filterManager: {
+ getFetches$: sinon.fake(),
+ getFilters: sinon.fake(),
+ getAppFilters: sinon.fake(),
+ getGlobalFilters: sinon.fake(),
+ removeFilter: sinon.fake(),
+ addFilters: sinon.fake(),
+ setFilters: sinon.fake(),
+ removeAll: sinon.fake(),
+ getUpdates$: () => {
+ return {
+ subscribe: () => {}
+ };
+ },
+
+ },
+ },
},
inspector: {
isAvailable: () => false,
diff --git a/src/legacy/ui/public/routes/route_manager.d.ts b/src/legacy/ui/public/routes/route_manager.d.ts
index 3471d7e954862..56203354f3c20 100644
--- a/src/legacy/ui/public/routes/route_manager.d.ts
+++ b/src/legacy/ui/public/routes/route_manager.d.ts
@@ -26,7 +26,10 @@ import { ChromeBreadcrumb } from '../../../../core/public';
interface RouteConfiguration {
controller?: string | ((...args: any[]) => void);
redirectTo?: string;
+ resolveRedirectTo?: (...args: any[]) => void;
reloadOnSearch?: boolean;
+ reloadOnUrl?: boolean;
+ outerAngularWrapperRoute?: boolean;
resolve?: object;
template?: string;
k7Breadcrumbs?: (...args: any[]) => ChromeBreadcrumb[];
diff --git a/src/legacy/ui/public/styles/_legacy/_base.scss b/src/legacy/ui/public/styles/_legacy/_base.scss
index aad90a99ac357..0fcfb515c7c90 100644
--- a/src/legacy/ui/public/styles/_legacy/_base.scss
+++ b/src/legacy/ui/public/styles/_legacy/_base.scss
@@ -4,13 +4,14 @@
input.ng-invalid,
textarea.ng-invalid,
select.ng-invalid {
- &.ng-dirty, &.ng-touched {
+ &.ng-dirty,
+ &.ng-touched {
border-color: $euiColorDanger !important;
}
}
-input[type="radio"],
-input[type="checkbox"],
+input[type='radio'],
+input[type='checkbox'],
.radio,
.radio-inline,
.checkbox,
@@ -18,7 +19,7 @@ input[type="checkbox"],
&[disabled],
fieldset[disabled] & {
cursor: default;
- opacity: .8;
+ opacity: 0.8;
}
}
@@ -27,7 +28,7 @@ input[type="checkbox"],
align-items: center;
padding-left: 0 !important;
- input[type="checkbox"] {
+ input[type='checkbox'] {
float: none;
margin: 0 $euiSizeXS;
position: static;
@@ -95,7 +96,6 @@ input[type="checkbox"],
}
}
-
// Too overused in many places to be moved elsewhere
.page-row {
@@ -114,7 +114,7 @@ input[type="checkbox"],
// state. This is useful when you've already hand crafted your own
// focus states in Kibana.
:focus {
- &:not([class^="eui"]):not(.kbn-resetFocusState) {
+ &:not([class^='eui']):not(.kbn-resetFocusState) {
@include euiFocusRing;
}
}
@@ -122,7 +122,8 @@ input[type="checkbox"],
// A neccessary hack so that the above focus policy doesn't polute some EUI
// entrenched inputs.
.euiComboBox {
- input:focus {
+ // :not() specificity needed to override the above
+ input:not([class^='eui']):focus {
animation: none !important;
}
}
diff --git a/src/legacy/ui/public/vis/default_feedback_message.js b/src/legacy/ui/public/vis/default_feedback_message.js
index f840ba961b9c3..8b8491d397aad 100644
--- a/src/legacy/ui/public/vis/default_feedback_message.js
+++ b/src/legacy/ui/public/vis/default_feedback_message.js
@@ -19,9 +19,10 @@
import { i18n } from '@kbn/i18n';
-export const defaultFeedbackMessage = i18n.translate('common.ui.vis.defaultFeedbackMessage',
- {
- defaultMessage: 'Have feedback? Please create an issue in {link}.',
- values: { link: '
GitHub ' }
- }
-);
+export const defaultFeedbackMessage = i18n.translate('common.ui.vis.defaultFeedbackMessage', {
+ defaultMessage: 'Have feedback? Please create an issue in {link}.',
+ values: {
+ link:
+ '
GitHub ',
+ },
+});
diff --git a/src/legacy/ui/public/vis/editors/default/components/agg.test.tsx b/src/legacy/ui/public/vis/editors/default/components/agg.test.tsx
index 5dfb14156deee..7806b1c0f78fb 100644
--- a/src/legacy/ui/public/vis/editors/default/components/agg.test.tsx
+++ b/src/legacy/ui/public/vis/editors/default/components/agg.test.tsx
@@ -156,7 +156,7 @@ describe('DefaultEditorAgg component', () => {
it('should add schema component', () => {
defaultProps.agg.schema = {
- editorComponent: () =>
,
+ editorComponent: () =>
,
} as any;
const comp = mount(
);
diff --git a/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx b/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx
index 6d3b5fc4e6355..528914f4fd006 100644
--- a/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx
+++ b/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx
@@ -26,7 +26,9 @@ import {
EuiDraggable,
EuiSpacer,
EuiPanel,
+ EuiFormErrorText,
} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
import { AggConfig } from '../../../../agg_types/agg_config';
import { aggGroupNamesMap, AggGroupNames } from '../agg_groups';
@@ -80,7 +82,15 @@ function DefaultEditorAggGroup({
const [aggsState, setAggsState] = useReducer(aggGroupReducer, group, initAggsState);
- const isGroupValid = Object.values(aggsState).every(item => item.valid);
+ const bucketsError =
+ lastParentPipelineAggTitle && groupName === AggGroupNames.Buckets && !group.length
+ ? i18n.translate('common.ui.aggTypes.buckets.mustHaveBucketErrorMessage', {
+ defaultMessage: 'Add a bucket with "Date Histogram" or "Histogram" aggregation.',
+ description: 'Date Histogram and Histogram should not be translated',
+ })
+ : undefined;
+
+ const isGroupValid = !bucketsError && Object.values(aggsState).every(item => item.valid);
const isAllAggsTouched = isInvalidAggsTouched(aggsState);
const isMetricAggregationDisabled = useMemo(
() => groupName === AggGroupNames.Metrics && getEnabledMetricAggsCount(group) === 1,
@@ -144,6 +154,12 @@ function DefaultEditorAggGroup({
{groupNameLabel}
+ {bucketsError && (
+ <>
+
{bucketsError}
+
+ >
+ )}
<>
{group.map((agg: AggConfig, index: number) => (
diff --git a/src/legacy/ui/public/vis/editors/default/controls/filter.tsx b/src/legacy/ui/public/vis/editors/default/controls/filter.tsx
index 2c0a2b6be37f8..4ebe7b0d835d7 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/filter.tsx
+++ b/src/legacy/ui/public/vis/editors/default/controls/filter.tsx
@@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n';
import { Query, QueryBarInput } from 'plugins/data';
import { AggConfig } from '../../..';
import { npStart } from '../../../../new_platform';
-import { Storage } from '../../../../storage';
+import { Storage } from '../../../../../../../plugins/kibana_utils/public';
import { KibanaContextProvider } from '../../../../../../../plugins/kibana_react/public';
const localStorage = new Storage(window.localStorage);
@@ -94,7 +94,7 @@ function FilterRow({
{
@@ -66,7 +67,7 @@ const defaultEditor = function ($rootScope, $compile) {
//$scope.$apply();
};
- return new Promise(resolve => {
+ return new Promise(async (resolve) => {
if (!this.$scope) {
this.$scope = $scope = $rootScope.$new();
@@ -157,23 +158,21 @@ const defaultEditor = function ($rootScope, $compile) {
if (!this._handler) {
const visualizationEl = this.el.find('.visEditor__canvas')[0];
- getVisualizeLoader().then(loader => {
- if (!visualizationEl) {
- return;
- }
- this._loader = loader;
- this._handler = this._loader.embedVisualizationWithSavedObject(visualizationEl, this.savedObj, {
- uiState: uiState,
- listenOnChange: false,
- timeRange: timeRange,
- filters: filters,
- appState: appState,
- });
+
+ this._handler = await embeddables.getEmbeddableFactory('visualization').createFromObject(this.savedObj, {
+ uiState: uiState,
+ appState: getAppState(),
+ timeRange: timeRange,
+ filters: filters || [],
+ query: query,
});
+ this._handler.render(visualizationEl);
+
} else {
- this._handler.update({
+ this._handler.updateInput({
timeRange: timeRange,
- filters: filters,
+ filters: filters || [],
+ query: query,
});
}
diff --git a/src/legacy/ui/public/vis/vis_filters/brush_event.js b/src/legacy/ui/public/vis/vis_filters/brush_event.js
index 90cbaf7c048ee..17ab302a20cb1 100644
--- a/src/legacy/ui/public/vis/vis_filters/brush_event.js
+++ b/src/legacy/ui/public/vis/vis_filters/brush_event.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import moment from 'moment';
-import { buildRangeFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../plugins/data/public';
export function onBrushEvent(event) {
const isNumber = event.data.ordered;
@@ -56,7 +56,7 @@ export function onBrushEvent(event) {
};
}
- const newFilter = buildRangeFilter(
+ const newFilter = esFilters.buildRangeFilter(
field,
range,
indexPattern,
diff --git a/src/legacy/ui/public/vis/vis_filters/vis_filters.js b/src/legacy/ui/public/vis/vis_filters/vis_filters.js
index f19e2440a21e9..e879d040125f1 100644
--- a/src/legacy/ui/public/vis/vis_filters/vis_filters.js
+++ b/src/legacy/ui/public/vis/vis_filters/vis_filters.js
@@ -20,8 +20,8 @@
import _ from 'lodash';
import { pushFilterBarFilters } from '../push_filters';
import { onBrushEvent } from './brush_event';
-import { uniqFilters } from '../../../../core_plugins/data/public';
-import { toggleFilterNegated } from '@kbn/es-query';
+import { uniqFilters, esFilters } from '../../../../../plugins/data/public';
+
/**
* For terms aggregations on `__other__` buckets, this assembles a list of applicable filter
* terms based on a specific cell in the tabified data.
@@ -94,7 +94,7 @@ const createFiltersFromEvent = (event) => {
if (filter) {
filter.forEach(f => {
if (event.negate) {
- f = toggleFilterNegated(f);
+ f = esFilters.toggleFilterNegated(f);
}
filters.push(f);
});
diff --git a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.ts b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.ts
index bc2152911d1ec..fb16e095b3418 100644
--- a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.ts
+++ b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.ts
@@ -22,13 +22,13 @@ import { debounce, forEach, get, isEqual } from 'lodash';
import * as Rx from 'rxjs';
import { share } from 'rxjs/operators';
import { i18n } from '@kbn/i18n';
-import { Filter } from '@kbn/es-query';
import { toastNotifications } from 'ui/notify';
// @ts-ignore untyped dependency
import { AggConfigs } from 'ui/agg_types/agg_configs';
import { SearchSource } from 'ui/courier';
import { QueryFilter } from 'ui/filter_manager/query_filter';
-import { TimeRange } from 'src/plugins/data/public';
+
+import { TimeRange, onlyDisabledFiltersChanged } from '../../../../../plugins/data/public';
import { registries } from '../../../../core_plugins/interpreter/public/registries';
import { Inspector } from '../../inspector';
import { Adapters } from '../../inspector/types';
@@ -42,7 +42,8 @@ import { Vis } from '../../vis';
import { VisFiltersProvider } from '../../vis/vis_filters';
import { PipelineDataLoader } from './pipeline_data_loader';
import { visualizationLoader } from './visualization_loader';
-import { onlyDisabledFiltersChanged, Query } from '../../../../core_plugins/data/public';
+import { Query } from '../../../../core_plugins/data/public';
+import { esFilters } from '../../../../../plugins/data/public';
import { DataAdapter, RequestAdapter } from '../../inspector/adapters';
@@ -66,7 +67,7 @@ export interface RequestHandlerParams {
aggs: AggConfigs;
timeRange?: TimeRange;
query?: Query;
- filters?: Filter[];
+ filters?: esFilters.Filter[];
forceFetch: boolean;
queryFilter: QueryFilter;
uiState?: PersistedState;
@@ -537,16 +538,16 @@ export class EmbeddedVisualizeHandler {
private rendererProvider = (response: VisResponseData | null) => {
const renderer = registries.renderers.get(get(response || {}, 'as', 'visualization'));
- const args = [
- this.element,
- get(response, 'value', { visType: this.vis.type.name }),
- this.handlers,
- ];
if (!renderer) {
return null;
}
- return () => renderer.render(...args);
+ return () =>
+ renderer.render(
+ this.element,
+ get(response, 'value', { visType: this.vis.type.name }),
+ this.handlers
+ );
};
}
diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/build_pipeline.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/build_pipeline.ts
index 17ec224f4c7de..21b13abea440e 100644
--- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/build_pipeline.ts
+++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/build_pipeline.ts
@@ -24,7 +24,7 @@ import { SearchSource } from 'ui/courier';
import { AggConfig, Vis, VisParams, VisState } from 'ui/vis';
import { isDateHistogramBucketAggConfig } from 'ui/agg_types/buckets/date_histogram';
import moment from 'moment';
-import { SerializedFieldFormat } from 'src/plugins/expressions/common/expressions/types/common';
+import { SerializedFieldFormat } from 'src/plugins/expressions/public';
import { createFormat } from './utilities';
interface SchemaConfigParams {
diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts
index c12bd222663ae..c5ebc75973d0c 100644
--- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts
+++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts
@@ -20,7 +20,7 @@
import { i18n } from '@kbn/i18n';
import { identity } from 'lodash';
import { AggConfig, Vis } from 'ui/vis';
-import { SerializedFieldFormat } from 'src/plugins/expressions/common/expressions/types/common';
+import { SerializedFieldFormat } from 'src/plugins/expressions/public';
import { FieldFormat } from '../../../../../../plugins/data/common/field_formats';
diff --git a/src/legacy/ui/public/visualize/loader/types.ts b/src/legacy/ui/public/visualize/loader/types.ts
index 87183d839e637..525ec35834ecd 100644
--- a/src/legacy/ui/public/visualize/loader/types.ts
+++ b/src/legacy/ui/public/visualize/loader/types.ts
@@ -17,7 +17,6 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { TimeRange } from 'src/plugins/data/public';
import { Query } from 'src/legacy/core_plugins/data/public';
import { SavedObject } from 'ui/saved_objects/saved_object';
@@ -26,6 +25,7 @@ import { SearchSource } from '../../courier';
import { PersistedState } from '../../persisted_state';
import { AppState } from '../../state_management/app_state';
import { Vis } from '../../vis';
+import { esFilters } from '../../../../../plugins/data/public';
export interface VisSavedObject extends SavedObject {
vis: Vis;
@@ -68,7 +68,7 @@ export interface VisualizeLoaderParams {
/**
* Specifies the filters that should be applied to that visualization.
*/
- filters?: Filter[];
+ filters?: esFilters.Filter[];
/**
* The query that should apply to that visualization.
*/
diff --git a/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts b/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts
index ec612f7dd0373..9f3aa190917d7 100644
--- a/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts
+++ b/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts
@@ -22,13 +22,13 @@ import { get } from 'lodash';
import { toastNotifications } from 'ui/notify';
import { AggConfig } from 'ui/vis';
-import { Filter } from '@kbn/es-query';
import { Query } from 'src/legacy/core_plugins/data/public';
import { timefilter } from 'ui/timefilter';
import { Vis } from '../../../vis';
+import { esFilters } from '../../../../../../plugins/data/public';
interface QueryGeohashBoundsParams {
- filters?: Filter[];
+ filters?: esFilters.Filter[];
query?: Query;
}
@@ -76,7 +76,7 @@ export async function queryGeohashBounds(vis: Vis, params: QueryGeohashBoundsPar
const useTimeFilter = !!indexPattern.timeFieldName;
if (useTimeFilter) {
const filter = timefilter.createFilter(indexPattern);
- if (filter) activeFilters.push((filter as any) as Filter);
+ if (filter) activeFilters.push((filter as any) as esFilters.Filter);
}
return activeFilters;
});
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/kibana.json b/src/plugins/dashboard_embeddable_container/kibana.json
similarity index 90%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/kibana.json
rename to src/plugins/dashboard_embeddable_container/kibana.json
index 417168ba61dd9..aab23316f606c 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/kibana.json
+++ b/src/plugins/dashboard_embeddable_container/kibana.json
@@ -4,7 +4,7 @@
"requiredPlugins": [
"embeddable",
"inspector",
- "ui_actions"
+ "uiActions"
],
"server": false,
"ui": true
diff --git a/src/plugins/dashboard_embeddable_container/public/_index.scss b/src/plugins/dashboard_embeddable_container/public/_index.scss
new file mode 100644
index 0000000000000..ccb8299072fb7
--- /dev/null
+++ b/src/plugins/dashboard_embeddable_container/public/_index.scss
@@ -0,0 +1,5 @@
+@import '../../embeddable/public/variables';
+
+@import './embeddable/grid/index';
+@import './embeddable/panel/index';
+@import './embeddable/viewport/index';
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.test.tsx b/src/plugins/dashboard_embeddable_container/public/actions/expand_panel_action.test.tsx
similarity index 97%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.test.tsx
rename to src/plugins/dashboard_embeddable_container/public/actions/expand_panel_action.test.tsx
index 0fa34817bee86..f8c05170e8f67 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.test.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/actions/expand_panel_action.test.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import { isErrorEmbeddable, EmbeddableFactory } from '../embeddable_api';
+import { isErrorEmbeddable, EmbeddableFactory } from '../embeddable_plugin';
import { ExpandPanelAction } from './expand_panel_action';
import { DashboardContainer } from '../embeddable';
import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helpers';
@@ -27,7 +27,7 @@ import {
ContactCardEmbeddable,
ContactCardEmbeddableInput,
ContactCardEmbeddableOutput,
-} from '../../../../../../embeddable_api/public/np_ready/public/lib/test_samples';
+} from '../embeddable_plugin_test_samples';
import { DashboardOptions } from '../embeddable/dashboard_container_factory';
const embeddableFactories = new Map();
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.tsx b/src/plugins/dashboard_embeddable_container/public/actions/expand_panel_action.tsx
similarity index 93%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.tsx
rename to src/plugins/dashboard_embeddable_container/public/actions/expand_panel_action.tsx
index f05d0b0efc2ee..68f68f8a53bcc 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/actions/expand_panel_action.tsx
@@ -18,12 +18,9 @@
*/
import { i18n } from '@kbn/i18n';
-import { IEmbeddable } from '../../../../../../embeddable_api/public/np_ready/public';
+import { IEmbeddable } from '../embeddable_plugin';
+import { IAction, IncompatibleActionError } from '../ui_actions_plugin';
import { DASHBOARD_CONTAINER_TYPE, DashboardContainer } from '../embeddable';
-import {
- IAction,
- IncompatibleActionError,
-} from '../../../../../../../../../src/plugins/ui_actions/public';
export const EXPAND_PANEL_ACTION = 'togglePanel';
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/index.ts b/src/plugins/dashboard_embeddable_container/public/actions/index.ts
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/index.ts
rename to src/plugins/dashboard_embeddable_container/public/actions/index.ts
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/open_replace_panel_flyout.tsx b/src/plugins/dashboard_embeddable_container/public/actions/open_replace_panel_flyout.tsx
similarity index 78%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/open_replace_panel_flyout.tsx
rename to src/plugins/dashboard_embeddable_container/public/actions/open_replace_panel_flyout.tsx
index b6652caf3ab83..cb354375e7a68 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/open_replace_panel_flyout.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/actions/open_replace_panel_flyout.tsx
@@ -17,26 +17,32 @@
* under the License.
*/
import React from 'react';
-import { CoreStart } from 'src/core/public';
+import { CoreStart } from '../../../../core/public';
import { ReplacePanelFlyout } from './replace_panel_flyout';
-
import {
IEmbeddable,
EmbeddableInput,
EmbeddableOutput,
-} from '../../../../../../embeddable_api/public/np_ready/public';
-
-import { IContainer } from '../../../../../../embeddable_api/public/np_ready/public';
-import { NotificationsStart } from '../../../../../../../../core/public';
+ Start as EmbeddableStart,
+ IContainer,
+} from '../embeddable_plugin';
export async function openReplacePanelFlyout(options: {
embeddable: IContainer;
core: CoreStart;
savedObjectFinder: React.ComponentType;
- notifications: NotificationsStart;
+ notifications: CoreStart['notifications'];
panelToRemove: IEmbeddable;
+ getEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
}) {
- const { embeddable, core, panelToRemove, savedObjectFinder, notifications } = options;
+ const {
+ embeddable,
+ core,
+ panelToRemove,
+ savedObjectFinder,
+ notifications,
+ getEmbeddableFactories,
+ } = options;
const flyoutSession = core.overlays.openFlyout(
,
{
'data-test-subj': 'replacePanelFlyout',
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.test.tsx b/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_action.test.tsx
similarity index 83%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.test.tsx
rename to src/plugins/dashboard_embeddable_container/public/actions/replace_panel_action.test.tsx
index e1d2e3609570c..de29e1dec85a8 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.test.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_action.test.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import { isErrorEmbeddable, EmbeddableFactory } from '../embeddable_api';
+import { isErrorEmbeddable, EmbeddableFactory } from '../embeddable_plugin';
import { ReplacePanelAction } from './replace_panel_action';
import { DashboardContainer } from '../embeddable';
import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helpers';
@@ -27,7 +27,7 @@ import {
ContactCardEmbeddable,
ContactCardEmbeddableInput,
ContactCardEmbeddableOutput,
-} from '../../../../../../embeddable_api/public/np_ready/public/lib/test_samples';
+} from '../embeddable_plugin_test_samples';
import { DashboardOptions } from '../embeddable/dashboard_container_factory';
const embeddableFactories = new Map();
@@ -35,6 +35,7 @@ embeddableFactories.set(
CONTACT_CARD_EMBEDDABLE,
new ContactCardEmbeddableFactory({} as any, (() => null) as any, {} as any)
);
+const getEmbeddableFactories = () => embeddableFactories.values();
let container: DashboardContainer;
let embeddable: ContactCardEmbeddable;
@@ -82,7 +83,12 @@ test('Executes the replace panel action', async () => {
let core: any;
let SavedObjectFinder: any;
let notifications: any;
- const action = new ReplacePanelAction(core, SavedObjectFinder, notifications);
+ const action = new ReplacePanelAction(
+ core,
+ SavedObjectFinder,
+ notifications,
+ getEmbeddableFactories
+ );
action.execute({ embeddable });
});
@@ -90,7 +96,12 @@ test('Is not compatible when embeddable is not in a dashboard container', async
let core: any;
let SavedObjectFinder: any;
let notifications: any;
- const action = new ReplacePanelAction(core, SavedObjectFinder, notifications);
+ const action = new ReplacePanelAction(
+ core,
+ SavedObjectFinder,
+ notifications,
+ getEmbeddableFactories
+ );
expect(
await action.isCompatible({
embeddable: new ContactCardEmbeddable(
@@ -105,7 +116,12 @@ test('Execute throws an error when called with an embeddable not in a parent', a
let core: any;
let SavedObjectFinder: any;
let notifications: any;
- const action = new ReplacePanelAction(core, SavedObjectFinder, notifications);
+ const action = new ReplacePanelAction(
+ core,
+ SavedObjectFinder,
+ notifications,
+ getEmbeddableFactories
+ );
async function check() {
await action.execute({ embeddable: container });
}
@@ -116,7 +132,12 @@ test('Returns title', async () => {
let core: any;
let SavedObjectFinder: any;
let notifications: any;
- const action = new ReplacePanelAction(core, SavedObjectFinder, notifications);
+ const action = new ReplacePanelAction(
+ core,
+ SavedObjectFinder,
+ notifications,
+ getEmbeddableFactories
+ );
expect(action.getDisplayName({ embeddable })).toBeDefined();
});
@@ -124,6 +145,11 @@ test('Returns an icon', async () => {
let core: any;
let SavedObjectFinder: any;
let notifications: any;
- const action = new ReplacePanelAction(core, SavedObjectFinder, notifications);
+ const action = new ReplacePanelAction(
+ core,
+ SavedObjectFinder,
+ notifications,
+ getEmbeddableFactories
+ );
expect(action.getIconType({ embeddable })).toBeDefined();
});
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.tsx b/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_action.tsx
similarity index 87%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.tsx
rename to src/plugins/dashboard_embeddable_container/public/actions/replace_panel_action.tsx
index f36efc498b15f..f6d2fcbcd57fd 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_action.tsx
@@ -18,15 +18,10 @@
*/
import { i18n } from '@kbn/i18n';
-import { CoreStart } from 'src/core/public';
-
-import { IEmbeddable, ViewMode } from '../../../../../../embeddable_api/public/np_ready/public';
+import { CoreStart } from '../../../../core/public';
+import { IEmbeddable, ViewMode, Start as EmbeddableStart } from '../embeddable_plugin';
import { DASHBOARD_CONTAINER_TYPE, DashboardContainer } from '../embeddable';
-import {
- IAction,
- IncompatibleActionError,
-} from '../../../../../../../../plugins/ui_actions/public';
-import { NotificationsStart } from '../../../../../../../../core/public';
+import { IAction, IncompatibleActionError } from '../ui_actions_plugin';
import { openReplacePanelFlyout } from './open_replace_panel_flyout';
export const REPLACE_PANEL_ACTION = 'replacePanel';
@@ -47,7 +42,8 @@ export class ReplacePanelAction implements IAction {
constructor(
private core: CoreStart,
private savedobjectfinder: React.ComponentType,
- private notifications: NotificationsStart
+ private notifications: CoreStart['notifications'],
+ private getEmbeddableFactories: EmbeddableStart['getEmbeddableFactories']
) {}
public getDisplayName({ embeddable }: ActionContext) {
@@ -89,6 +85,7 @@ export class ReplacePanelAction implements IAction {
savedObjectFinder: this.savedobjectfinder,
notifications: this.notifications,
panelToRemove: view,
+ getEmbeddableFactories: this.getEmbeddableFactories,
});
}
}
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_flyout.tsx b/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_flyout.tsx
similarity index 90%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_flyout.tsx
rename to src/plugins/dashboard_embeddable_container/public/actions/replace_panel_flyout.tsx
index 0e738556372ce..02e5f45fae3bd 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_flyout.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_flyout.tsx
@@ -19,10 +19,6 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
-
-import { NotificationsStart } from 'src/core/public';
-import { DashboardPanelState } from 'src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public';
-
import {
EuiFlyout,
EuiFlyoutBody,
@@ -30,15 +26,15 @@ import {
EuiTitle,
EuiGlobalToastListToast as Toast,
} from '@elastic/eui';
-
-import { IContainer } from '../../../../../../embeddable_api/public/np_ready/public';
+import { DashboardPanelState } from '../embeddable';
+import { NotificationsStart } from '../../../../core/public';
import {
+ IContainer,
IEmbeddable,
EmbeddableInput,
EmbeddableOutput,
-} from '../../../../../../embeddable_api/public/np_ready/public';
-
-import { start } from '../../../../../../embeddable_api/public/np_ready/public/legacy';
+ Start as EmbeddableStart,
+} from '../embeddable_plugin';
interface Props {
container: IContainer;
@@ -46,6 +42,7 @@ interface Props {
onClose: () => void;
notifications: NotificationsStart;
panelToRemove: IEmbeddable;
+ getEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
}
export class ReplacePanelFlyout extends React.Component {
@@ -117,7 +114,7 @@ export class ReplacePanelFlyout extends React.Component {
defaultMessage: 'No matching objects found.',
}
)}
- savedObjectMetaData={[...start.getEmbeddableFactories()]
+ savedObjectMetaData={[...this.props.getEmbeddableFactories()]
.filter(
embeddableFactory =>
Boolean(embeddableFactory.savedObjectMetaData) && !embeddableFactory.isContainerType
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_constants.ts b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_constants.ts
similarity index 94%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_constants.ts
rename to src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_constants.ts
index 941ddd3c5efec..34cd8d42a1188 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_constants.ts
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_constants.ts
@@ -21,3 +21,4 @@ export const DASHBOARD_GRID_COLUMN_COUNT = 48;
export const DASHBOARD_GRID_HEIGHT = 20;
export const DEFAULT_PANEL_WIDTH = DASHBOARD_GRID_COLUMN_COUNT / 2;
export const DEFAULT_PANEL_HEIGHT = 15;
+export const DASHBOARD_CONTAINER_TYPE = 'dashboard';
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.test.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.test.tsx
similarity index 97%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.test.tsx
rename to src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.test.tsx
index 06bc696b95193..770c46c62e42f 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.test.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.test.tsx
@@ -20,7 +20,7 @@
// @ts-ignore
import { findTestSubject } from '@elastic/eui/lib/test';
import { nextTick } from 'test_utils/enzyme_helpers';
-import { isErrorEmbeddable, ViewMode, EmbeddableFactory } from '../embeddable_api';
+import { isErrorEmbeddable, ViewMode, EmbeddableFactory } from '../embeddable_plugin';
import { DashboardContainer, DashboardContainerOptions } from './dashboard_container';
import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helpers';
import {
@@ -29,7 +29,7 @@ import {
ContactCardEmbeddableInput,
ContactCardEmbeddable,
ContactCardEmbeddableOutput,
-} from '../../../../../../embeddable_api/public/np_ready/public/lib/test_samples';
+} from '../embeddable_plugin_test_samples';
const options: DashboardContainerOptions = {
application: {} as any,
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx
similarity index 83%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.tsx
rename to src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx
index 919995f544960..8b258f3558438 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx
@@ -20,9 +20,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
-import { Filter } from '@kbn/es-query';
-import { RefreshInterval, TimeRange } from 'src/plugins/data/public';
-import { IUiActionsStart } from '../../../../../../../../plugins/ui_actions/public';
+import { RefreshInterval, TimeRange, Query } from '../../../data/public';
+import { CoreStart } from '../../../../core/public';
+import { IUiActionsStart } from '../ui_actions_plugin';
import {
Container,
ContainerInput,
@@ -30,24 +30,23 @@ import {
ViewMode,
EmbeddableFactory,
IEmbeddable,
-} from '../../../../../../embeddable_api/public/np_ready/public';
-import { DASHBOARD_CONTAINER_TYPE } from './dashboard_container_factory';
+ Start as EmbeddableStartContract,
+} from '../embeddable_plugin';
+import { DASHBOARD_CONTAINER_TYPE } from './dashboard_constants';
import { createPanelState } from './panel';
import { DashboardPanelState } from './types';
import { DashboardViewport } from './viewport/dashboard_viewport';
-import { Query } from '../../../../../../data/public';
-import { CoreStart } from '../../../../../../../../core/public';
-import { Start as InspectorStartContract } from '../../../../../../../../plugins/inspector/public';
-import { Start as EmbeddableStartContract } from '../../../../../../embeddable_api/public/np_ready/public';
+import { Start as InspectorStartContract } from '../../../inspector/public';
+import { esFilters } from '../../../../plugins/data/public';
import {
+ KibanaContextProvider,
KibanaReactContext,
KibanaReactContextValue,
- KibanaContextProvider,
-} from '../../../../../../../../plugins/kibana_react/public';
+} from '../../../kibana_react/public';
export interface DashboardContainerInput extends ContainerInput {
viewMode: ViewMode;
- filters: Filter[];
+ filters: esFilters.Filter[];
query: Query;
timeRange: TimeRange;
refreshConfig?: RefreshInterval;
@@ -66,7 +65,7 @@ interface IndexSignature {
}
export interface InheritedChildInput extends IndexSignature {
- filters: Filter[];
+ filters: esFilters.Filter[];
query: Query;
timeRange: TimeRange;
refreshConfig?: RefreshInterval;
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container_factory.ts b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container_factory.tsx
similarity index 91%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container_factory.ts
rename to src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container_factory.tsx
index 29ce9bcb0da2e..c8a2837fd77d0 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container_factory.ts
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container_factory.tsx
@@ -18,17 +18,21 @@
*/
import { i18n } from '@kbn/i18n';
-import { SavedObjectAttributes } from '../../../../../../../../core/server';
+import { SavedObjectAttributes } from '../../../../core/public';
import { SavedObjectMetaData } from '../types';
-import { ContainerOutput, EmbeddableFactory, ErrorEmbeddable, Container } from '../embeddable_api';
+import {
+ ContainerOutput,
+ EmbeddableFactory,
+ ErrorEmbeddable,
+ Container,
+} from '../embeddable_plugin';
import {
DashboardContainer,
DashboardContainerInput,
DashboardContainerOptions,
} from './dashboard_container';
import { DashboardCapabilities } from '../types';
-
-export const DASHBOARD_CONTAINER_TYPE = 'dashboard';
+import { DASHBOARD_CONTAINER_TYPE } from './dashboard_constants';
export interface DashboardOptions extends DashboardContainerOptions {
savedObjectMetaData?: SavedObjectMetaData;
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/_dashboard_grid.scss b/src/plugins/dashboard_embeddable_container/public/embeddable/grid/_dashboard_grid.scss
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/_dashboard_grid.scss
rename to src/plugins/dashboard_embeddable_container/public/embeddable/grid/_dashboard_grid.scss
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/_index.scss b/src/plugins/dashboard_embeddable_container/public/embeddable/grid/_index.scss
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/_index.scss
rename to src/plugins/dashboard_embeddable_container/public/embeddable/grid/_index.scss
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.test.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/grid/dashboard_grid.test.tsx
similarity index 96%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.test.tsx
rename to src/plugins/dashboard_embeddable_container/public/embeddable/grid/dashboard_grid.test.tsx
index 386aae9ddcf78..e4338dc89153d 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.test.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/grid/dashboard_grid.test.tsx
@@ -23,15 +23,15 @@ import sizeMe from 'react-sizeme';
import React from 'react';
import { nextTick, mountWithIntl } from 'test_utils/enzyme_helpers';
import { skip } from 'rxjs/operators';
-import { EmbeddableFactory, GetEmbeddableFactory } from '../../embeddable_api';
+import { EmbeddableFactory, GetEmbeddableFactory } from '../../embeddable_plugin';
import { DashboardGrid, DashboardGridProps } from './dashboard_grid';
import { DashboardContainer, DashboardContainerOptions } from '../dashboard_container';
import { getSampleDashboardInput } from '../../test_helpers';
import {
CONTACT_CARD_EMBEDDABLE,
ContactCardEmbeddableFactory,
-} from '../../../../../../../embeddable_api/public/np_ready/public/lib/test_samples';
-import { KibanaContextProvider } from '../../../../../../../../../plugins/kibana_react/public';
+} from '../../embeddable_plugin_test_samples';
+import { KibanaContextProvider } from '../../../../kibana_react/public';
let dashboardContainer: DashboardContainer | undefined;
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/grid/dashboard_grid.tsx
similarity index 95%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.tsx
rename to src/plugins/dashboard_embeddable_container/public/embeddable/grid/dashboard_grid.tsx
index 291bef15641f3..40db43427339d 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/grid/dashboard_grid.tsx
@@ -20,19 +20,21 @@
import 'react-grid-layout/css/styles.css';
import 'react-resizable/css/styles.css';
+// @ts-ignore
+import sizeMe from 'react-sizeme';
+
import { injectI18n } from '@kbn/i18n/react';
import classNames from 'classnames';
import _ from 'lodash';
import React from 'react';
import { Subscription } from 'rxjs';
import ReactGridLayout, { Layout } from 'react-grid-layout';
-// @ts-ignore
-import sizeMe from 'react-sizeme';
-import { ViewMode, EmbeddableChildPanel } from '../../embeddable_api';
+import { ViewMode, EmbeddableChildPanel } from '../../embeddable_plugin';
import { DASHBOARD_GRID_COLUMN_COUNT, DASHBOARD_GRID_HEIGHT } from '../dashboard_constants';
-import { DashboardContainer, DashboardReactContextValue } from '../dashboard_container';
import { DashboardPanelState, GridData } from '../types';
-import { withKibana } from '../../../../../../../../../plugins/kibana_react/public';
+import { withKibana } from '../../../../kibana_react/public';
+import { DashboardContainerInput } from '../dashboard_container';
+import { DashboardContainer, DashboardReactContextValue } from '../dashboard_container';
let lastValidGridSize = 0;
@@ -174,16 +176,18 @@ class DashboardGridUi extends React.Component {
isLayoutInvalid,
});
- this.subscription = this.props.container.getInput$().subscribe(input => {
- if (this.mounted) {
- this.setState({
- panels: input.panels,
- viewMode: input.viewMode,
- useMargins: input.useMargins,
- expandedPanelId: input.expandedPanelId,
- });
- }
- });
+ this.subscription = this.props.container
+ .getInput$()
+ .subscribe((input: DashboardContainerInput) => {
+ if (this.mounted) {
+ this.setState({
+ panels: input.panels,
+ viewMode: input.viewMode,
+ useMargins: input.useMargins,
+ expandedPanelId: input.expandedPanelId,
+ });
+ }
+ });
}
public componentWillUnmount() {
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/index.ts b/src/plugins/dashboard_embeddable_container/public/embeddable/grid/index.ts
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/index.ts
rename to src/plugins/dashboard_embeddable_container/public/embeddable/grid/index.ts
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/index.ts b/src/plugins/dashboard_embeddable_container/public/embeddable/index.ts
similarity index 91%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/index.ts
rename to src/plugins/dashboard_embeddable_container/public/embeddable/index.ts
index 2a6a56e3300bc..58bfd5eedefcb 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/index.ts
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/index.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-export { DASHBOARD_CONTAINER_TYPE, DashboardContainerFactory } from './dashboard_container_factory';
+export { DashboardContainerFactory } from './dashboard_container_factory';
export { DashboardContainer, DashboardContainerInput } from './dashboard_container';
export { createPanelState } from './panel';
@@ -27,4 +27,5 @@ export {
DASHBOARD_GRID_COLUMN_COUNT,
DEFAULT_PANEL_HEIGHT,
DEFAULT_PANEL_WIDTH,
+ DASHBOARD_CONTAINER_TYPE,
} from './dashboard_constants';
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/_dashboard_panel.scss b/src/plugins/dashboard_embeddable_container/public/embeddable/panel/_dashboard_panel.scss
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/_dashboard_panel.scss
rename to src/plugins/dashboard_embeddable_container/public/embeddable/panel/_dashboard_panel.scss
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/_index.scss b/src/plugins/dashboard_embeddable_container/public/embeddable/panel/_index.scss
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/_index.scss
rename to src/plugins/dashboard_embeddable_container/public/embeddable/panel/_index.scss
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/create_panel_state.test.ts b/src/plugins/dashboard_embeddable_container/public/embeddable/panel/create_panel_state.test.ts
similarity index 93%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/create_panel_state.test.ts
rename to src/plugins/dashboard_embeddable_container/public/embeddable/panel/create_panel_state.test.ts
index e66a25831577c..8889f4dc27544 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/create_panel_state.test.ts
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/panel/create_panel_state.test.ts
@@ -20,9 +20,8 @@
import { DEFAULT_PANEL_HEIGHT, DEFAULT_PANEL_WIDTH } from '../dashboard_constants';
import { DashboardPanelState } from '../types';
import { createPanelState } from './create_panel_state';
-import { EmbeddableInput } from '../../embeddable_api';
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { CONTACT_CARD_EMBEDDABLE } from '../../../../../../../embeddable_api/public/np_ready/public/lib/test_samples';
+import { EmbeddableInput } from '../../embeddable_plugin';
+import { CONTACT_CARD_EMBEDDABLE } from '../../embeddable_plugin_test_samples';
interface TestInput extends EmbeddableInput {
test: string;
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/create_panel_state.ts b/src/plugins/dashboard_embeddable_container/public/embeddable/panel/create_panel_state.ts
similarity index 98%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/create_panel_state.ts
rename to src/plugins/dashboard_embeddable_container/public/embeddable/panel/create_panel_state.ts
index 4f3de4a9b2bfb..7139cddf02b33 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/create_panel_state.ts
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/panel/create_panel_state.ts
@@ -18,7 +18,7 @@
*/
import _ from 'lodash';
-import { PanelState, EmbeddableInput } from '../../embeddable_api';
+import { PanelState, EmbeddableInput } from '../../embeddable_plugin';
import {
DASHBOARD_GRID_COLUMN_COUNT,
DEFAULT_PANEL_HEIGHT,
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/index.ts b/src/plugins/dashboard_embeddable_container/public/embeddable/panel/index.ts
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/panel/index.ts
rename to src/plugins/dashboard_embeddable_container/public/embeddable/panel/index.ts
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/types.ts b/src/plugins/dashboard_embeddable_container/public/embeddable/types.ts
similarity index 94%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/types.ts
rename to src/plugins/dashboard_embeddable_container/public/embeddable/types.ts
index 6e5257f0d1ee0..480d03552ca68 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/types.ts
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/types.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { PanelState, EmbeddableInput } from '../embeddable_api';
+import { PanelState, EmbeddableInput } from '../embeddable_plugin';
export type PanelId = string;
export type SavedObjectId = string;
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/_dashboard_viewport.scss b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/_dashboard_viewport.scss
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/_dashboard_viewport.scss
rename to src/plugins/dashboard_embeddable_container/public/embeddable/viewport/_dashboard_viewport.scss
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/_index.scss b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/_index.scss
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/_index.scss
rename to src/plugins/dashboard_embeddable_container/public/embeddable/viewport/_index.scss
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.test.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.test.tsx
similarity index 95%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.test.tsx
rename to src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.test.tsx
index 01bde21f91d3b..7b83407bf8063 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.test.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.test.tsx
@@ -24,15 +24,15 @@ import { skip } from 'rxjs/operators';
import { mount } from 'enzyme';
import { I18nProvider } from '@kbn/i18n/react';
import { nextTick } from 'test_utils/enzyme_helpers';
-import { EmbeddableFactory } from '../../embeddable_api';
+import { EmbeddableFactory } from '../../embeddable_plugin';
import { DashboardViewport, DashboardViewportProps } from './dashboard_viewport';
import { DashboardContainer, DashboardContainerOptions } from '../dashboard_container';
import { getSampleDashboardInput } from '../../test_helpers';
import {
CONTACT_CARD_EMBEDDABLE,
ContactCardEmbeddableFactory,
-} from '../../../../../../../embeddable_api/public/np_ready/public/lib/test_samples';
-import { KibanaContextProvider } from '../../../../../../../../../plugins/kibana_react/public';
+} from '../../embeddable_plugin_test_samples';
+import { KibanaContextProvider } from '../../../../../plugins/kibana_react/public';
let dashboardContainer: DashboardContainer | undefined;
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.tsx
similarity index 95%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.tsx
rename to src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.tsx
index 59accb225238b..13407e5e33725 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.tsx
@@ -19,10 +19,10 @@
import React from 'react';
import { Subscription } from 'rxjs';
-import { PanelState } from '../../embeddable_api';
+import { PanelState } from '../../embeddable_plugin';
import { DashboardContainer, DashboardReactContextValue } from '../dashboard_container';
import { DashboardGrid } from '../grid';
-import { context } from '../../../../../../../../../plugins/kibana_react/public';
+import { context } from '../../../../kibana_react/public';
export interface DashboardViewportProps {
container: DashboardContainer;
diff --git a/src/legacy/ui/public/storage/web_storage.ts b/src/plugins/dashboard_embeddable_container/public/embeddable_plugin.ts
similarity index 93%
rename from src/legacy/ui/public/storage/web_storage.ts
rename to src/plugins/dashboard_embeddable_container/public/embeddable_plugin.ts
index d5f775431143d..30c0ec4975141 100644
--- a/src/legacy/ui/public/storage/web_storage.ts
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable_plugin.ts
@@ -17,4 +17,4 @@
* under the License.
*/
-export type WebStorage = Storage;
+export * from '../../../plugins/embeddable/public';
diff --git a/src/plugins/dashboard_embeddable_container/public/embeddable_plugin_test_samples.ts b/src/plugins/dashboard_embeddable_container/public/embeddable_plugin_test_samples.ts
new file mode 100644
index 0000000000000..0e49a94278dfc
--- /dev/null
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable_plugin_test_samples.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.
+ */
+
+// eslint-disable-next-line
+export * from '../../../plugins/embeddable/public/lib/test_samples';
diff --git a/src/plugins/dashboard_embeddable_container/public/index.ts b/src/plugins/dashboard_embeddable_container/public/index.ts
new file mode 100644
index 0000000000000..73597525105db
--- /dev/null
+++ b/src/plugins/dashboard_embeddable_container/public/index.ts
@@ -0,0 +1,31 @@
+/*
+ * 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 { PluginInitializerContext } from '../../../core/public';
+import { DashboardEmbeddableContainerPublicPlugin } from './plugin';
+
+export * from './types';
+export * from './actions';
+export * from './embeddable';
+
+export function plugin(initializerContext: PluginInitializerContext) {
+ return new DashboardEmbeddableContainerPublicPlugin(initializerContext);
+}
+
+export { DashboardEmbeddableContainerPublicPlugin as Plugin };
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts b/src/plugins/dashboard_embeddable_container/public/plugin.tsx
similarity index 61%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts
rename to src/plugins/dashboard_embeddable_container/public/plugin.tsx
index bb18d109b0de7..eadf70a36416a 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts
+++ b/src/plugins/dashboard_embeddable_container/public/plugin.tsx
@@ -17,11 +17,21 @@
* under the License.
*/
+/* eslint-disable max-classes-per-file */
+
+import * as React from 'react';
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public';
-import { IUiActionsSetup, IUiActionsStart } from '../../../../../../plugins/ui_actions/public';
-import { CONTEXT_MENU_TRIGGER, Plugin as EmbeddablePlugin } from './lib/embeddable_api';
-import { ExpandPanelAction, ReplacePanelAction, DashboardContainerFactory } from './lib';
-import { Start as InspectorStartContract } from '../../../../../../plugins/inspector/public';
+import { IUiActionsSetup, IUiActionsStart } from '../../../plugins/ui_actions/public';
+import { CONTEXT_MENU_TRIGGER, Plugin as EmbeddablePlugin } from './embeddable_plugin';
+import { ExpandPanelAction, ReplacePanelAction } from '.';
+import { DashboardContainerFactory } from './embeddable/dashboard_container_factory';
+import { Start as InspectorStartContract } from '../../../plugins/inspector/public';
+import {
+ SavedObjectFinder as SavedObjectFinderUi,
+ SavedObjectFinderProps,
+ ExitFullScreenButton as ExitFullScreenButtonUi,
+ ExitFullScreenButtonProps,
+} from '../../../plugins/kibana_react/public';
interface SetupDependencies {
embeddable: ReturnType;
@@ -32,10 +42,6 @@ interface StartDependencies {
embeddable: ReturnType;
inspector: InspectorStartContract;
uiActions: IUiActionsStart;
- __LEGACY: {
- SavedObjectFinder: React.ComponentType;
- ExitFullScreenButton: React.ComponentType;
- };
}
export type Setup = void;
@@ -53,12 +59,35 @@ export class DashboardEmbeddableContainerPublicPlugin
public start(core: CoreStart, plugins: StartDependencies): Start {
const { application, notifications, overlays } = core;
- const { embeddable, inspector, __LEGACY, uiActions } = plugins;
+ const { embeddable, inspector, uiActions } = plugins;
+
+ const SavedObjectFinder: React.FC<
+ Exclude
+ > = props => (
+
+ );
+
+ const useHideChrome = () => {
+ React.useEffect(() => {
+ core.chrome.setIsVisible(false);
+ return () => core.chrome.setIsVisible(true);
+ }, []);
+ };
+
+ const ExitFullScreenButton: React.FC = props => {
+ useHideChrome();
+ return ;
+ };
const changeViewAction = new ReplacePanelAction(
core,
- __LEGACY.SavedObjectFinder,
- notifications
+ SavedObjectFinder,
+ notifications,
+ plugins.embeddable.getEmbeddableFactories
);
uiActions.registerAction(changeViewAction);
uiActions.attachAction(CONTEXT_MENU_TRIGGER, changeViewAction.id);
@@ -69,8 +98,8 @@ export class DashboardEmbeddableContainerPublicPlugin
overlays,
embeddable,
inspector,
- SavedObjectFinder: __LEGACY.SavedObjectFinder,
- ExitFullScreenButton: __LEGACY.ExitFullScreenButton,
+ SavedObjectFinder,
+ ExitFullScreenButton,
uiActions,
});
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/test_helpers/get_sample_dashboard_input.ts b/src/plugins/dashboard_embeddable_container/public/test_helpers/get_sample_dashboard_input.ts
similarity index 96%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/test_helpers/get_sample_dashboard_input.ts
rename to src/plugins/dashboard_embeddable_container/public/test_helpers/get_sample_dashboard_input.ts
index 98eb0636f9aad..09478d8e8af35 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/test_helpers/get_sample_dashboard_input.ts
+++ b/src/plugins/dashboard_embeddable_container/public/test_helpers/get_sample_dashboard_input.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { ViewMode, EmbeddableInput } from '../embeddable_api';
+import { ViewMode, EmbeddableInput } from '../embeddable_plugin';
import { DashboardContainerInput, DashboardPanelState } from '../embeddable';
export function getSampleDashboardInput(
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/test_helpers/index.ts b/src/plugins/dashboard_embeddable_container/public/test_helpers/index.ts
similarity index 100%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/test_helpers/index.ts
rename to src/plugins/dashboard_embeddable_container/public/test_helpers/index.ts
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/tests/dashboard_container.test.tsx b/src/plugins/dashboard_embeddable_container/public/tests/dashboard_container.test.tsx
similarity index 83%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/tests/dashboard_container.test.tsx
rename to src/plugins/dashboard_embeddable_container/public/tests/dashboard_container.test.tsx
index 6cf409581b76d..6a3b69af60d6b 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/tests/dashboard_container.test.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/tests/dashboard_container.test.tsx
@@ -23,28 +23,24 @@ import React from 'react';
import { mount } from 'enzyme';
import { nextTick } from 'test_utils/enzyme_helpers';
import { I18nProvider } from '@kbn/i18n/react';
-import { ViewMode, CONTEXT_MENU_TRIGGER, EmbeddablePanel } from '../lib/embeddable_api';
-import {
- DashboardContainer,
- DashboardContainerOptions,
-} from '../lib/embeddable/dashboard_container';
-import { getSampleDashboardInput } from '../lib/test_helpers';
+import { ViewMode, CONTEXT_MENU_TRIGGER, EmbeddablePanel } from '../embeddable_plugin';
+import { DashboardContainer, DashboardContainerOptions } from '../embeddable/dashboard_container';
+import { getSampleDashboardInput } from '../test_helpers';
import {
CONTACT_CARD_EMBEDDABLE,
ContactCardEmbeddableFactory,
-} from '../../../../../embeddable_api/public/np_ready/public/lib/test_samples';
-import {
ContactCardEmbeddableInput,
ContactCardEmbeddable,
ContactCardEmbeddableOutput,
-} from '../../../../../embeddable_api/public/np_ready/public/lib/test_samples';
-import { embeddablePluginMock } from '../../../../../embeddable_api/public/np_ready/public/mocks';
-import { createEditModeAction } from '../../../../../embeddable_api/public/np_ready/public/lib/test_samples';
+ createEditModeAction,
+} from '../embeddable_plugin_test_samples';
+// eslint-disable-next-line
+import { embeddablePluginMock } from '../../../embeddable/public/mocks';
// eslint-disable-next-line
-import { inspectorPluginMock } from '../../../../../../../plugins/inspector/public/mocks';
-import { KibanaContextProvider } from '../../../../../../../plugins/kibana_react/public';
+import { inspectorPluginMock } from '../../../inspector/public/mocks';
+import { KibanaContextProvider } from '../../../kibana_react/public';
// eslint-disable-next-line
-import { uiActionsPluginMock } from 'src/plugins/ui_actions/public/mocks';
+import { uiActionsPluginMock } from '../../../ui_actions/public/mocks';
test('DashboardContainer in edit mode shows edit mode actions', async () => {
const inspector = inspectorPluginMock.createStartContract();
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/types.ts b/src/plugins/dashboard_embeddable_container/public/types.ts
similarity index 91%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/types.ts
rename to src/plugins/dashboard_embeddable_container/public/types.ts
index fe6f4bcdafec9..9c2d6c0ab388d 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/types.ts
+++ b/src/plugins/dashboard_embeddable_container/public/types.ts
@@ -18,10 +18,7 @@
*/
import { IconType } from '@elastic/eui';
-import {
- SavedObject as SavedObjectType,
- SavedObjectAttributes,
-} from '../../../../../../../core/server';
+import { SavedObject as SavedObjectType, SavedObjectAttributes } from '../../../core/public';
export interface DashboardCapabilities {
showWriteControls: boolean;
@@ -61,6 +58,11 @@ export interface SavedObjectMetaData {
showSavedObject?(savedObject: SimpleSavedObject): boolean;
}
+interface FieldSubType {
+ multi?: { parent: string };
+ nested?: { path: string };
+}
+
export interface Field {
name: string;
type: string;
@@ -70,6 +72,5 @@ export interface Field {
aggregatable: boolean;
filterable: boolean;
searchable: boolean;
- parent?: string;
- subType?: string;
+ subType?: FieldSubType;
}
diff --git a/src/plugins/dashboard_embeddable_container/public/ui_actions_plugin.ts b/src/plugins/dashboard_embeddable_container/public/ui_actions_plugin.ts
new file mode 100644
index 0000000000000..c8778025e7713
--- /dev/null
+++ b/src/plugins/dashboard_embeddable_container/public/ui_actions_plugin.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 '../../../plugins/ui_actions/public';
diff --git a/src/plugins/data/common/es_query/__tests__/fields_mock.ts b/src/plugins/data/common/es_query/__tests__/fields_mock.ts
new file mode 100644
index 0000000000000..83fdf588af00c
--- /dev/null
+++ b/src/plugins/data/common/es_query/__tests__/fields_mock.ts
@@ -0,0 +1,320 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export const fields = [
+ {
+ name: 'bytes',
+ type: 'number',
+ esTypes: ['long'],
+ count: 10,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'ssl',
+ type: 'boolean',
+ esTypes: ['boolean'],
+ count: 20,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: '@timestamp',
+ type: 'date',
+ esTypes: ['date'],
+ count: 30,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'time',
+ type: 'date',
+ esTypes: ['date'],
+ count: 30,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: '@tags',
+ type: 'string',
+ esTypes: ['keyword'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'utc_time',
+ type: 'date',
+ esTypes: ['date'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'phpmemory',
+ type: 'number',
+ esTypes: ['integer'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'ip',
+ type: 'ip',
+ esTypes: ['ip'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'request_body',
+ type: 'attachment',
+ esTypes: ['attachment'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'point',
+ type: 'geo_point',
+ esTypes: ['geo_point'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'area',
+ type: 'geo_shape',
+ esTypes: ['geo_shape'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'hashed',
+ type: 'murmur3',
+ esTypes: ['murmur3'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: false,
+ readFromDocValues: false,
+ },
+ {
+ name: 'geo.coordinates',
+ type: 'geo_point',
+ esTypes: ['geo_point'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'extension',
+ type: 'string',
+ esTypes: ['keyword'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'machine.os',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'machine.os.raw',
+ type: 'string',
+ esTypes: ['keyword'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ subType: { multi: { parent: 'machine.os' } },
+ },
+ {
+ name: 'geo.src',
+ type: 'string',
+ esTypes: ['keyword'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: '_id',
+ type: 'string',
+ esTypes: ['_id'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: '_type',
+ type: 'string',
+ esTypes: ['_type'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: '_source',
+ type: '_source',
+ esTypes: ['_source'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'non-filterable',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: false,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'non-sortable',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: false,
+ aggregatable: false,
+ readFromDocValues: false,
+ },
+ {
+ name: 'custom_user_field',
+ type: 'conflict',
+ esTypes: ['long', 'text'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'script string',
+ type: 'string',
+ count: 0,
+ scripted: true,
+ script: "'i am a string'",
+ lang: 'expression',
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'script number',
+ type: 'number',
+ count: 0,
+ scripted: true,
+ script: '1234',
+ lang: 'expression',
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'script date',
+ type: 'date',
+ count: 0,
+ scripted: true,
+ script: '1234',
+ lang: 'painless',
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'script murmur3',
+ type: 'murmur3',
+ count: 0,
+ scripted: true,
+ script: '1234',
+ lang: 'expression',
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'nestedField.child',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: false,
+ readFromDocValues: false,
+ subType: { nested: { path: 'nestedField' } },
+ },
+ {
+ name: 'nestedField.nestedChild.doublyNestedChild',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: false,
+ readFromDocValues: false,
+ subType: { nested: { path: 'nestedField.nestedChild' } },
+ },
+];
+
+export const getField = (name: string) => fields.find(field => field.name === name);
diff --git a/packages/kbn-es-query/src/filters/lib/custom_filter.ts b/src/plugins/data/common/es_query/filters/custom_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/custom_filter.ts
rename to src/plugins/data/common/es_query/filters/custom_filter.ts
diff --git a/packages/kbn-es-query/src/filters/lib/exists_filter.ts b/src/plugins/data/common/es_query/filters/exists_filter.ts
similarity index 81%
rename from packages/kbn-es-query/src/filters/lib/exists_filter.ts
rename to src/plugins/data/common/es_query/filters/exists_filter.ts
index 5843c25c43cff..9125048e5f6cd 100644
--- a/packages/kbn-es-query/src/filters/lib/exists_filter.ts
+++ b/src/plugins/data/common/es_query/filters/exists_filter.ts
@@ -18,6 +18,7 @@
*/
import { Filter, FilterMeta } from './meta_filter';
+import { IndexPattern, Field } from './types';
export type ExistsFilterMeta = FilterMeta;
@@ -31,3 +32,14 @@ export type ExistsFilter = Filter & {
};
export const isExistsFilter = (filter: any): filter is ExistsFilter => filter && filter.exists;
+
+export const buildExistsFilter = (field: Field, indexPattern: IndexPattern) => {
+ return {
+ meta: {
+ index: indexPattern.id,
+ },
+ exists: {
+ field: field.name,
+ },
+ } as ExistsFilter;
+};
diff --git a/packages/kbn-es-query/src/filters/lib/geo_bounding_box_filter.ts b/src/plugins/data/common/es_query/filters/geo_bounding_box_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/geo_bounding_box_filter.ts
rename to src/plugins/data/common/es_query/filters/geo_bounding_box_filter.ts
diff --git a/packages/kbn-es-query/src/filters/lib/geo_polygon_filter.ts b/src/plugins/data/common/es_query/filters/geo_polygon_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/geo_polygon_filter.ts
rename to src/plugins/data/common/es_query/filters/geo_polygon_filter.ts
diff --git a/src/plugins/expressions/common/expressions/index.ts b/src/plugins/data/common/es_query/filters/index.ts
similarity index 68%
rename from src/plugins/expressions/common/expressions/index.ts
rename to src/plugins/data/common/es_query/filters/index.ts
index 8c8dd7eb26ca5..e28ce9ba74975 100644
--- a/src/plugins/expressions/common/expressions/index.ts
+++ b/src/plugins/data/common/es_query/filters/index.ts
@@ -17,7 +17,16 @@
* under the License.
*/
+export * from './custom_filter';
+export * from './exists_filter';
+export * from './geo_bounding_box_filter';
+export * from './geo_polygon_filter';
+export * from './match_all_filter';
+export * from './meta_filter';
+export * from './missing_filter';
+export * from './phrase_filter';
+export * from './phrases_filter';
+export * from './query_string_filter';
+export * from './range_filter';
+
export * from './types';
-export { Type } from './interpreter';
-export { interpreterProvider } from './interpreter_provider';
-export { serializeProvider, getType } from './serialize_provider';
diff --git a/packages/kbn-es-query/src/filters/lib/match_all_filter.ts b/src/plugins/data/common/es_query/filters/match_all_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/match_all_filter.ts
rename to src/plugins/data/common/es_query/filters/match_all_filter.ts
diff --git a/packages/kbn-es-query/src/filters/lib/meta_filter.ts b/src/plugins/data/common/es_query/filters/meta_filter.ts
similarity index 75%
rename from packages/kbn-es-query/src/filters/lib/meta_filter.ts
rename to src/plugins/data/common/es_query/filters/meta_filter.ts
index 8f6aef782cea2..9adfdc4eedcb3 100644
--- a/packages/kbn-es-query/src/filters/lib/meta_filter.ts
+++ b/src/plugins/data/common/es_query/filters/meta_filter.ts
@@ -55,7 +55,7 @@ export interface LatLon {
lon: number;
}
-export function buildEmptyFilter(isPinned: boolean, index?: string): Filter {
+export const buildEmptyFilter = (isPinned: boolean, index?: string): Filter => {
const meta: FilterMeta = {
disabled: false,
negate: false,
@@ -65,43 +65,43 @@ export function buildEmptyFilter(isPinned: boolean, index?: string): Filter {
const $state: FilterState = {
store: isPinned ? FilterStateStore.GLOBAL_STATE : FilterStateStore.APP_STATE,
};
+
return { meta, $state };
-}
+};
-export function isFilterPinned(filter: Filter) {
+export const isFilterPinned = (filter: Filter) => {
return filter.$state && filter.$state.store === FilterStateStore.GLOBAL_STATE;
-}
+};
-export function toggleFilterDisabled(filter: Filter) {
+export const toggleFilterDisabled = (filter: Filter) => {
const disabled = !filter.meta.disabled;
const meta = { ...filter.meta, disabled };
+
return { ...filter, meta };
-}
+};
-export function toggleFilterNegated(filter: Filter) {
+export const toggleFilterNegated = (filter: Filter) => {
const negate = !filter.meta.negate;
const meta = { ...filter.meta, negate };
+
return { ...filter, meta };
-}
+};
-export function toggleFilterPinned(filter: Filter) {
+export const toggleFilterPinned = (filter: Filter) => {
const store = isFilterPinned(filter) ? FilterStateStore.APP_STATE : FilterStateStore.GLOBAL_STATE;
const $state = { ...filter.$state, store };
+
return { ...filter, $state };
-}
+};
-export function enableFilter(filter: Filter) {
- return !filter.meta.disabled ? filter : toggleFilterDisabled(filter);
-}
+export const enableFilter = (filter: Filter) =>
+ !filter.meta.disabled ? filter : toggleFilterDisabled(filter);
-export function disableFilter(filter: Filter) {
- return filter.meta.disabled ? filter : toggleFilterDisabled(filter);
-}
+export const disableFilter = (filter: Filter) =>
+ filter.meta.disabled ? filter : toggleFilterDisabled(filter);
-export function pinFilter(filter: Filter) {
- return isFilterPinned(filter) ? filter : toggleFilterPinned(filter);
-}
+export const pinFilter = (filter: Filter) =>
+ isFilterPinned(filter) ? filter : toggleFilterPinned(filter);
-export function unpinFilter(filter: Filter) {
- return !isFilterPinned(filter) ? filter : toggleFilterPinned(filter);
-}
+export const unpinFilter = (filter: Filter) =>
+ !isFilterPinned(filter) ? filter : toggleFilterPinned(filter);
diff --git a/packages/kbn-es-query/src/filters/lib/missing_filter.ts b/src/plugins/data/common/es_query/filters/missing_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/missing_filter.ts
rename to src/plugins/data/common/es_query/filters/missing_filter.ts
diff --git a/src/plugins/data/common/es_query/filters/phrase_filter.test.ts b/src/plugins/data/common/es_query/filters/phrase_filter.test.ts
new file mode 100644
index 0000000000000..ec13e28c583d1
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/phrase_filter.test.ts
@@ -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 { buildInlineScriptForPhraseFilter, buildPhraseFilter } from './phrase_filter';
+import { IndexPattern } from './types';
+import { getField } from '../__tests__/fields_mock';
+
+describe('Phrase filter builder', () => {
+ let indexPattern: IndexPattern;
+
+ beforeEach(() => {
+ indexPattern = {
+ id: 'id',
+ };
+ });
+
+ it('should be a function', () => {
+ expect(typeof buildPhraseFilter).toBe('function');
+ });
+
+ it('should return a match query filter when passed a standard field', () => {
+ const field = getField('bytes');
+
+ expect(buildPhraseFilter(field, 5, indexPattern)).toEqual({
+ meta: {
+ index: 'id',
+ },
+ query: {
+ match_phrase: {
+ bytes: 5,
+ },
+ },
+ });
+ });
+
+ it('should return a script filter when passed a scripted field', () => {
+ const field = getField('script number');
+
+ expect(buildPhraseFilter(field, 5, indexPattern)).toEqual({
+ meta: {
+ index: 'id',
+ field: 'script number',
+ },
+ script: {
+ script: {
+ lang: 'expression',
+ params: {
+ value: 5,
+ },
+ source: '(1234) == value',
+ },
+ },
+ });
+ });
+});
+
+describe('buildInlineScriptForPhraseFilter', () => {
+ it('should wrap painless scripts in a lambda', () => {
+ const field = {
+ lang: 'painless',
+ script: 'return foo;',
+ };
+
+ const expected =
+ `boolean compare(Supplier s, def v) {return s.get() == v;}` +
+ `compare(() -> { return foo; }, params.value);`;
+
+ expect(buildInlineScriptForPhraseFilter(field)).toBe(expected);
+ });
+
+ it('should create a simple comparison for other langs', () => {
+ const field = {
+ lang: 'expression',
+ script: 'doc[bytes].value',
+ };
+
+ const expected = `(doc[bytes].value) == value`;
+
+ expect(buildInlineScriptForPhraseFilter(field)).toBe(expected);
+ });
+});
diff --git a/src/plugins/data/common/es_query/filters/phrase_filter.ts b/src/plugins/data/common/es_query/filters/phrase_filter.ts
new file mode 100644
index 0000000000000..15c5c9d4ad2e6
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/phrase_filter.ts
@@ -0,0 +1,144 @@
+/*
+ * 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 { get, isPlainObject } from 'lodash';
+import { Filter, FilterMeta } from './meta_filter';
+import { IndexPattern, Field } from './types';
+
+export type PhraseFilterMeta = FilterMeta & {
+ params?: {
+ query: string; // The unformatted value
+ };
+ script?: {
+ script: {
+ source?: any;
+ lang?: string;
+ params: any;
+ };
+ };
+ field?: any;
+ index?: any;
+};
+
+export type PhraseFilter = Filter & {
+ meta: PhraseFilterMeta;
+};
+
+type PhraseFilterValue = string | number | boolean;
+
+export const isPhraseFilter = (filter: any): filter is PhraseFilter => {
+ const isMatchPhraseQuery = filter && filter.query && filter.query.match_phrase;
+
+ const isDeprecatedMatchPhraseQuery =
+ filter &&
+ filter.query &&
+ filter.query.match &&
+ Object.values(filter.query.match).find((params: any) => params.type === 'phrase');
+
+ return !!(isMatchPhraseQuery || isDeprecatedMatchPhraseQuery);
+};
+
+export const isScriptedPhraseFilter = (filter: any): filter is PhraseFilter =>
+ Boolean(get(filter, 'script.script.params.value'));
+
+export const getPhraseFilterField = (filter: PhraseFilter) => {
+ const queryConfig = filter.query.match_phrase || filter.query.match;
+ return Object.keys(queryConfig)[0];
+};
+
+export const getPhraseFilterValue = (filter: PhraseFilter): PhraseFilterValue => {
+ const queryConfig = filter.query.match_phrase || filter.query.match;
+ const queryValue = Object.values(queryConfig)[0] as any;
+ return isPlainObject(queryValue) ? queryValue.query : queryValue;
+};
+
+export const buildPhraseFilter = (
+ field: Field,
+ value: any,
+ indexPattern: IndexPattern
+): PhraseFilter => {
+ const convertedValue = getConvertedValueForField(field, value);
+
+ if (field.scripted) {
+ return {
+ meta: { index: indexPattern.id, field: field.name } as PhraseFilterMeta,
+ script: getPhraseScript(field, value),
+ } as PhraseFilter;
+ } else {
+ return {
+ meta: { index: indexPattern.id },
+ query: {
+ match_phrase: {
+ [field.name]: convertedValue,
+ },
+ },
+ } as PhraseFilter;
+ }
+};
+
+export const getPhraseScript = (field: Field, value: string) => {
+ const convertedValue = getConvertedValueForField(field, value);
+ const script = buildInlineScriptForPhraseFilter(field);
+
+ return {
+ script: {
+ source: script,
+ lang: field.lang,
+ params: {
+ value: convertedValue,
+ },
+ },
+ };
+};
+
+// See https://github.com/elastic/elasticsearch/issues/20941 and https://github.com/elastic/kibana/issues/8677
+// and https://github.com/elastic/elasticsearch/pull/22201
+// for the reason behind this change. Aggs now return boolean buckets with a key of 1 or 0.
+export const getConvertedValueForField = (field: Field, value: any) => {
+ if (typeof value !== 'boolean' && field.type === 'boolean') {
+ if ([1, 'true'].includes(value)) {
+ return true;
+ } else if ([0, 'false'].includes(value)) {
+ return false;
+ } else {
+ throw new Error(`${value} is not a valid boolean value for boolean field ${field.name}`);
+ }
+ }
+ return value;
+};
+
+/**
+ * Takes a scripted field and returns an inline script appropriate for use in a script query.
+ * Handles lucene expression and Painless scripts. Other langs aren't guaranteed to generate valid
+ * scripts.
+ *
+ * @param {object} scriptedField A Field object representing a scripted field
+ * @returns {string} The inline script string
+ */
+export const buildInlineScriptForPhraseFilter = (scriptedField: any) => {
+ // We must wrap painless scripts in a lambda in case they're more than a simple expression
+ if (scriptedField.lang === 'painless') {
+ return (
+ `boolean compare(Supplier s, def v) {return s.get() == v;}` +
+ `compare(() -> { ${scriptedField.script} }, params.value);`
+ );
+ } else {
+ return `(${scriptedField.script}) == value`;
+ }
+};
diff --git a/packages/kbn-es-query/src/filters/phrases.js b/src/plugins/data/common/es_query/filters/phrases_filter.ts
similarity index 51%
rename from packages/kbn-es-query/src/filters/phrases.js
rename to src/plugins/data/common/es_query/filters/phrases_filter.ts
index f02b3763f37bb..e4606695c0f6a 100644
--- a/packages/kbn-es-query/src/filters/phrases.js
+++ b/src/plugins/data/common/es_query/filters/phrases_filter.ts
@@ -17,47 +17,54 @@
* under the License.
*/
-import { getPhraseScript } from './phrase';
+import { Filter, FilterMeta } from './meta_filter';
+import { Field, IndexPattern } from './types';
+import { getPhraseScript } from './phrase_filter';
+
+export type PhrasesFilterMeta = FilterMeta & {
+ params: string[]; // The unformatted values
+ field?: string;
+};
+
+export type PhrasesFilter = Filter & {
+ meta: PhrasesFilterMeta;
+};
+
+export const isPhrasesFilter = (filter: any): filter is PhrasesFilter =>
+ filter && filter.meta.type === 'phrases';
// Creates a filter where the given field matches one or more of the given values
// params should be an array of values
-export function buildPhrasesFilter(field, params, indexPattern) {
+export const buildPhrasesFilter = (field: Field, params: any, indexPattern: IndexPattern) => {
const index = indexPattern.id;
const type = 'phrases';
const key = field.name;
- const value = params
- .map(value => format(field, value))
- .join(', ');
- const filter = {
- meta: { index, type, key, value, params }
- };
+ const format = (f: Field, value: any) =>
+ f && f.format && f.format.convert ? f.format.convert(value) : value;
+
+ const value = params.map((v: any) => format(field, v)).join(', ');
let should;
if (field.scripted) {
- should = params.map((value) => ({
- script: getPhraseScript(field, value)
+ should = params.map((v: any) => ({
+ script: getPhraseScript(field, v),
}));
} else {
- should = params.map((value) => ({
+ should = params.map((v: any) => ({
match_phrase: {
- [field.name]: value
- }
+ [field.name]: v,
+ },
}));
}
- filter.query = {
- bool: {
- should,
- minimum_should_match: 1
- }
- };
-
- return filter;
-}
-
-function format(field, value) {
- return field && field.format && field.format.convert
- ? field.format.convert(value)
- : value;
-}
+ return {
+ meta: { index, type, key, value, params },
+ query: {
+ bool: {
+ should,
+ minimum_should_match: 1,
+ },
+ },
+ } as PhrasesFilter;
+};
diff --git a/src/plugins/data/common/es_query/filters/query_string_filter.test.ts b/src/plugins/data/common/es_query/filters/query_string_filter.test.ts
new file mode 100644
index 0000000000000..839e4f6359257
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/query_string_filter.test.ts
@@ -0,0 +1,47 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { buildQueryFilter } from './query_string_filter';
+import { IndexPattern } from './types';
+
+describe('Phrase filter builder', () => {
+ let indexPattern: IndexPattern;
+
+ beforeEach(() => {
+ indexPattern = {
+ id: 'id',
+ };
+ });
+
+ it('should be a function', () => {
+ expect(typeof buildQueryFilter).toBe('function');
+ });
+
+ it('should return a query filter when passed a standard field', () => {
+ expect(buildQueryFilter({ foo: 'bar' }, indexPattern.id, '')).toEqual({
+ meta: {
+ alias: '',
+ index: 'id',
+ },
+ query: {
+ foo: 'bar',
+ },
+ });
+ });
+});
diff --git a/packages/kbn-es-query/src/filters/lib/query_string_filter.ts b/src/plugins/data/common/es_query/filters/query_string_filter.ts
similarity index 78%
rename from packages/kbn-es-query/src/filters/lib/query_string_filter.ts
rename to src/plugins/data/common/es_query/filters/query_string_filter.ts
index 3b3b97fafba9b..901dc724aa4e4 100644
--- a/packages/kbn-es-query/src/filters/lib/query_string_filter.ts
+++ b/src/plugins/data/common/es_query/filters/query_string_filter.ts
@@ -18,6 +18,7 @@
*/
import { Filter, FilterMeta } from './meta_filter';
+import { IndexPattern } from './types';
export type QueryStringFilterMeta = FilterMeta;
@@ -32,3 +33,17 @@ export type QueryStringFilter = Filter & {
export const isQueryStringFilter = (filter: any): filter is QueryStringFilter =>
filter && filter.query && filter.query.query_string;
+
+// Creates a filter corresponding to a raw Elasticsearch query DSL object
+export const buildQueryFilter = (
+ query: QueryStringFilter['query'],
+ index: IndexPattern,
+ alias: string
+) =>
+ ({
+ query,
+ meta: {
+ index,
+ alias,
+ },
+ } as QueryStringFilter);
diff --git a/src/plugins/data/common/es_query/filters/range_filter.test.ts b/src/plugins/data/common/es_query/filters/range_filter.test.ts
new file mode 100644
index 0000000000000..9008dc2a67294
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/range_filter.test.ts
@@ -0,0 +1,174 @@
+/*
+ * 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 { each } from 'lodash';
+import { buildRangeFilter, RangeFilter } from './range_filter';
+import { IndexPattern, Field } from './types';
+import { getField } from '../__tests__/fields_mock';
+
+describe('Range filter builder', () => {
+ let indexPattern: IndexPattern;
+
+ beforeEach(() => {
+ indexPattern = {
+ id: 'id',
+ };
+ });
+
+ it('should be a function', () => {
+ expect(typeof buildRangeFilter).toBe('function');
+ });
+
+ it('should return a range filter when passed a standard field', () => {
+ const field = getField('bytes');
+
+ expect(buildRangeFilter(field, { gte: 1, lte: 3 }, indexPattern)).toEqual({
+ meta: {
+ index: 'id',
+ params: {},
+ },
+ range: {
+ bytes: {
+ gte: 1,
+ lte: 3,
+ },
+ },
+ });
+ });
+
+ it('should return a script filter when passed a scripted field', () => {
+ const field = getField('script number');
+
+ expect(buildRangeFilter(field, { gte: 1, lte: 3 }, indexPattern)).toEqual({
+ meta: {
+ field: 'script number',
+ index: 'id',
+ params: {},
+ },
+ script: {
+ script: {
+ lang: 'expression',
+ source: '(' + field!.script + ')>=gte && (' + field!.script + ')<=lte',
+ params: {
+ value: '>=1 <=3',
+ gte: 1,
+ lte: 3,
+ },
+ },
+ },
+ });
+ });
+
+ it('should wrap painless scripts in comparator lambdas', () => {
+ const field = getField('script date');
+ const expected =
+ `boolean gte(Supplier s, def v) {return !s.get().toInstant().isBefore(Instant.parse(v))} ` +
+ `boolean lte(Supplier s, def v) {return !s.get().toInstant().isAfter(Instant.parse(v))}` +
+ `gte(() -> { ${field!.script} }, params.gte) && ` +
+ `lte(() -> { ${field!.script} }, params.lte)`;
+
+ const rangeFilter = buildRangeFilter(field, { gte: 1, lte: 3 }, indexPattern);
+
+ expect(rangeFilter.script!.script.source).toBe(expected);
+ });
+
+ it('should throw an error when gte and gt, or lte and lt are both passed', () => {
+ const field = getField('script number');
+
+ expect(() => {
+ buildRangeFilter(field, { gte: 1, gt: 3 }, indexPattern);
+ }).toThrowError();
+
+ expect(() => {
+ buildRangeFilter(field, { lte: 1, lt: 3 }, indexPattern);
+ }).toThrowError();
+ });
+
+ it('to use the right operator for each of gte, gt, lt and lte', () => {
+ const field = getField('script number');
+
+ each({ gte: '>=', gt: '>', lte: '<=', lt: '<' }, (operator: string, key: any) => {
+ const params = {
+ [key]: 5,
+ };
+
+ const filter = buildRangeFilter(field, params, indexPattern);
+ const script = filter.script!.script;
+
+ expect(script.source).toBe('(' + field!.script + ')' + operator + key);
+ expect(script.params[key]).toBe(5);
+ expect(script.params.value).toBe(operator + 5);
+ });
+ });
+
+ describe('when given params where one side is infinite', () => {
+ let field: Field;
+ let filter: RangeFilter;
+
+ beforeEach(() => {
+ field = getField('script number');
+ filter = buildRangeFilter(field, { gte: 0, lt: Infinity }, indexPattern);
+ });
+
+ describe('returned filter', () => {
+ it('is a script filter', () => {
+ expect(filter).toHaveProperty('script');
+ });
+
+ it('contain a param for the finite side', () => {
+ expect(filter.script!.script.params).toHaveProperty('gte', 0);
+ });
+
+ it('does not contain a param for the infinite side', () => {
+ expect(filter.script!.script.params).not.toHaveProperty('lt');
+ });
+
+ it('does not contain a script condition for the infinite side', () => {
+ const script = field!.script;
+
+ expect(filter.script!.script.source).toEqual(`(${script})>=gte`);
+ });
+ });
+ });
+
+ describe('when given params where both sides are infinite', () => {
+ let field: Field;
+ let filter: RangeFilter;
+
+ beforeEach(() => {
+ field = getField('script number');
+ filter = buildRangeFilter(field, { gte: -Infinity, lt: Infinity }, indexPattern);
+ });
+
+ describe('returned filter', () => {
+ it('is a match_all filter', () => {
+ expect(filter).not.toHaveProperty('script');
+ expect(filter).toHaveProperty('match_all');
+ });
+
+ it('does not contain params', () => {
+ expect(filter).not.toHaveProperty('params');
+ });
+
+ it('meta field is set to field name', () => {
+ expect(filter.meta.field).toEqual('script number');
+ });
+ });
+ });
+});
diff --git a/packages/kbn-es-query/src/filters/range.js b/src/plugins/data/common/es_query/filters/range_filter.ts
similarity index 51%
rename from packages/kbn-es-query/src/filters/range.js
rename to src/plugins/data/common/es_query/filters/range_filter.ts
index 357f9209c50de..d7931f191e52b 100644
--- a/packages/kbn-es-query/src/filters/range.js
+++ b/src/plugins/data/common/es_query/filters/range_filter.ts
@@ -16,9 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
+import { map, reduce, mapValues, get, keys, pick } from 'lodash';
+import { Filter, FilterMeta } from './meta_filter';
+import { Field, IndexPattern } from './types';
-import _ from 'lodash';
const OPERANDS_IN_RANGE = 2;
+
const operators = {
gt: '>',
gte: '>=',
@@ -39,33 +42,85 @@ const dateComparators = {
lt: 'boolean lt(Supplier s, def v) {return s.get().toInstant().isBefore(Instant.parse(v))}',
};
-function formatValue(field, params) {
- return _.map(params, (val, key) => operators[key] + format(field, val)).join(' ');
+export interface RangeFilterParams {
+ from?: number | string;
+ to?: number | string;
+ gt?: number | string;
+ lt?: number | string;
+ gte?: number | string;
+ lte?: number | string;
+ format?: string;
}
+const hasRangeKeys = (params: RangeFilterParams) =>
+ Boolean(
+ keys(params).find((key: string) => ['gte', 'gt', 'lte', 'lt', 'from', 'to'].includes(key))
+ );
+
+export type RangeFilterMeta = FilterMeta & {
+ params: RangeFilterParams;
+ field?: any;
+ formattedValue?: string;
+};
+
+export type RangeFilter = Filter & {
+ meta: RangeFilterMeta;
+ script?: {
+ script: {
+ params: any;
+ lang: string;
+ source: any;
+ };
+ };
+ match_all?: any;
+ range: { [key: string]: RangeFilterParams };
+};
+
+export const isRangeFilter = (filter: any): filter is RangeFilter => filter && filter.range;
+
+export const isScriptedRangeFilter = (filter: any): filter is RangeFilter => {
+ const params: RangeFilterParams = get(filter, 'script.script.params', {});
+
+ return hasRangeKeys(params);
+};
+
+const formatValue = (field: Field, params: any[]) =>
+ map(params, (val: any, key: string) => get(operators, key) + format(field, val)).join(' ');
+
+const format = (field: Field, value: any) =>
+ field && field.format && field.format.convert ? field.format.convert(value) : value;
+
// Creates a filter where the value for the given field is in the given range
// params should be an object containing `lt`, `lte`, `gt`, and/or `gte`
-export function buildRangeFilter(field, params, indexPattern, formattedValue) {
- const filter = { meta: { index: indexPattern.id } };
- if (formattedValue) filter.meta.formattedValue = formattedValue;
+export const buildRangeFilter = (
+ field: Field,
+ params: RangeFilterParams,
+ indexPattern: IndexPattern,
+ formattedValue?: string
+): RangeFilter => {
+ const filter: any = { meta: { index: indexPattern.id, params: {} } };
+
+ if (formattedValue) {
+ filter.meta.formattedValue = formattedValue;
+ }
- params = _.mapValues(params, (value) => {
- return (field.type === 'number') ? parseFloat(value) : value;
- });
+ params = mapValues(params, value => (field.type === 'number' ? parseFloat(value) : value));
if ('gte' in params && 'gt' in params) throw new Error('gte and gt are mutually exclusive');
if ('lte' in params && 'lt' in params) throw new Error('lte and lt are mutually exclusive');
- const totalInfinite = ['gt', 'lt'].reduce((totalInfinite, op) => {
+ const totalInfinite = ['gt', 'lt'].reduce((acc: number, op: any) => {
const key = op in params ? op : `${op}e`;
- const isInfinite = Math.abs(params[key]) === Infinity;
+ const isInfinite = Math.abs(get(params, key)) === Infinity;
if (isInfinite) {
- totalInfinite++;
+ acc++;
+
+ // @ts-ignore
delete params[key];
}
- return totalInfinite;
+ return acc;
}, 0);
if (totalInfinite === OPERANDS_IN_RANGE) {
@@ -81,25 +136,29 @@ export function buildRangeFilter(field, params, indexPattern, formattedValue) {
filter.range[field.name] = params;
}
- return filter;
-}
+ return filter as RangeFilter;
+};
-export function getRangeScript(field, params) {
- const knownParams = _.pick(params, (val, key) => {
- return key in operators;
- });
- let script = _.map(knownParams, function (val, key) {
- return '(' + field.script + ')' + operators[key] + key;
- }).join(' && ');
+export const getRangeScript = (field: IndexPattern, params: RangeFilterParams) => {
+ const knownParams = pick(params, (val, key: any) => key in operators);
+ let script = map(
+ knownParams,
+ (val: any, key: string) => '(' + field.script + ')' + get(operators, key) + key
+ ).join(' && ');
// We must wrap painless scripts in a lambda in case they're more than a simple expression
if (field.lang === 'painless') {
const comp = field.type === 'date' ? dateComparators : comparators;
- const currentComparators = _.reduce(knownParams, (acc, val, key) => acc.concat(comp[key]), []).join(' ');
+ const currentComparators = reduce(
+ knownParams,
+ (acc, val, key) => acc.concat(get(comp, key)),
+ []
+ ).join(' ');
- const comparisons = _.map(knownParams, function (val, key) {
- return `${key}(() -> { ${field.script} }, params.${key})`;
- }).join(' && ');
+ const comparisons = map(
+ knownParams,
+ (val, key) => `${key}(() -> { ${field.script} }, params.${key})`
+ ).join(' && ');
script = `${currentComparators}${comparisons}`;
}
@@ -108,14 +167,7 @@ export function getRangeScript(field, params) {
script: {
source: script,
params: knownParams,
- lang: field.lang
- }
+ lang: field.lang,
+ },
};
-}
-
-function format(field, value) {
- return field && field.format && field.format.convert
- ? field.format.convert(value)
- : value;
-}
-
+};
diff --git a/src/plugins/data/common/es_query/filters/types.ts b/src/plugins/data/common/es_query/filters/types.ts
new file mode 100644
index 0000000000000..2814735061999
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/types.ts
@@ -0,0 +1,57 @@
+/*
+ * 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 { ExistsFilter } from './exists_filter';
+import { GeoBoundingBoxFilter } from './geo_bounding_box_filter';
+import { GeoPolygonFilter } from './geo_polygon_filter';
+import { PhrasesFilter } from './phrases_filter';
+import { PhraseFilter } from './phrase_filter';
+import { RangeFilter } from './range_filter';
+import { MatchAllFilter } from './match_all_filter';
+import { MissingFilter } from './missing_filter';
+
+// Any filter associated with a field (used in the filter bar/editor)
+export type FieldFilter =
+ | ExistsFilter
+ | GeoBoundingBoxFilter
+ | GeoPolygonFilter
+ | PhraseFilter
+ | PhrasesFilter
+ | RangeFilter
+ | MatchAllFilter
+ | MissingFilter;
+
+export enum FILTERS {
+ CUSTOM = 'custom',
+ PHRASES = 'phrases',
+ PHRASE = 'phrase',
+ EXISTS = 'exists',
+ MATCH_ALL = 'match_all',
+ MISSING = 'missing',
+ QUERY_STRING = 'query_string',
+ RANGE = 'range',
+ GEO_BOUNDING_BOX = 'geo_bounding_box',
+ GEO_POLYGON = 'geo_polygon',
+}
+
+// We can't import the real types from the data plugin, so need to either duplicate
+// them here or figure out another solution, perhaps housing them in this package
+// will be replaces after Fieds / IndexPattern will be moved into new platform
+export type Field = any;
+export type IndexPattern = any;
diff --git a/src/plugins/data/common/es_query/index.ts b/src/plugins/data/common/es_query/index.ts
new file mode 100644
index 0000000000000..88e14a43cfaae
--- /dev/null
+++ b/src/plugins/data/common/es_query/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.
+ */
+import * as esFilters from './filters';
+
+export { esFilters };
diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts
index dca7897bd2766..42b5a03fcc926 100644
--- a/src/plugins/data/common/index.ts
+++ b/src/plugins/data/common/index.ts
@@ -20,5 +20,6 @@
export * from './query';
export * from './field_formats';
export * from './kbn_field_types';
+export * from './es_query';
export * from './types';
diff --git a/src/plugins/data/public/autocomplete_provider/types.ts b/src/plugins/data/public/autocomplete_provider/types.ts
index 4b1c5dfbd3528..1f2d8f914dde3 100644
--- a/src/plugins/data/public/autocomplete_provider/types.ts
+++ b/src/plugins/data/public/autocomplete_provider/types.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { StaticIndexPattern } from 'ui/index_patterns';
+import { StaticIndexPattern, Field } from 'ui/index_patterns';
import { AutocompleteProviderRegister } from '.';
export type AutocompletePublicPluginSetup = Pick<
@@ -50,11 +50,22 @@ export type AutocompleteSuggestionType =
| 'conjunction'
| 'recentSearch';
+// A union type allows us to do easy type guards in the code. For example, if I want to ensure I'm
+// working with a FieldAutocompleteSuggestion, I can just do `if ('field' in suggestion)` and the
+// TypeScript compiler will narrow the type to the parts of the union that have a field prop.
/** @public **/
-export interface AutocompleteSuggestion {
+export type AutocompleteSuggestion = BasicAutocompleteSuggestion | FieldAutocompleteSuggestion;
+
+interface BasicAutocompleteSuggestion {
description?: string;
end: number;
start: number;
text: string;
type: AutocompleteSuggestionType;
+ cursorIndex?: number;
}
+
+export type FieldAutocompleteSuggestion = BasicAutocompleteSuggestion & {
+ type: 'field';
+ field: Field;
+};
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 7e1b3801b62a4..32153df69f367 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -34,3 +34,4 @@ export * from './types';
export { IRequestTypesMap, IResponseTypesMap } from './search';
export * from './search';
+export * from './query';
diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts
index 5e60ca93378d9..2269ba3c55bce 100644
--- a/src/plugins/data/public/mocks.ts
+++ b/src/plugins/data/public/mocks.ts
@@ -18,6 +18,7 @@
*/
import { Plugin } from '.';
import { searchSetupMock } from './search/mocks';
+import { queryServiceMock } from './query/mocks';
export type Setup = jest.Mocked>;
export type Start = jest.Mocked>;
@@ -29,19 +30,23 @@ const autocompleteMock: any = {
};
const createSetupContract = (): Setup => {
+ const querySetupMock = queryServiceMock.createSetupContract();
const setupContract: Setup = {
autocomplete: autocompleteMock as Setup['autocomplete'],
search: searchSetupMock,
+ query: querySetupMock,
};
return setupContract;
};
const createStartContract = (): Start => {
+ const queryStartMock = queryServiceMock.createStartContract();
const startContract: Start = {
autocomplete: autocompleteMock as Start['autocomplete'],
getSuggestions: jest.fn(),
search: { search: jest.fn() },
+ query: queryStartMock,
};
return startContract;
};
diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts
index 935a3c5754503..a13e912e77846 100644
--- a/src/plugins/data/public/plugin.ts
+++ b/src/plugins/data/public/plugin.ts
@@ -18,23 +18,29 @@
*/
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
-import { AutocompleteProviderRegister } from './autocomplete_provider';
import { DataPublicPluginSetup, DataPublicPluginStart } from './types';
-import { SearchService } from './search/search_service';
+import { AutocompleteProviderRegister } from './autocomplete_provider';
import { getSuggestionsProvider } from './suggestions_provider';
+import { SearchService } from './search/search_service';
+import { QueryService } from './query';
export class DataPublicPlugin implements Plugin {
private readonly autocomplete = new AutocompleteProviderRegister();
private readonly searchService: SearchService;
+ private readonly queryService: QueryService;
constructor(initializerContext: PluginInitializerContext) {
this.searchService = new SearchService(initializerContext);
+ this.queryService = new QueryService();
}
public setup(core: CoreSetup): DataPublicPluginSetup {
return {
autocomplete: this.autocomplete,
search: this.searchService.setup(core),
+ query: this.queryService.setup({
+ uiSettings: core.uiSettings,
+ }),
};
}
@@ -43,6 +49,7 @@ export class DataPublicPlugin implements Plugin {
@@ -38,32 +34,17 @@ setupMock.uiSettings.get.mockImplementation((key: string) => {
});
describe('filter_manager', () => {
- let appStateStub: StubState;
- let globalStateStub: StubState;
-
let updateSubscription: Subscription | undefined;
let fetchSubscription: Subscription | undefined;
let updateListener: sinon.SinonSpy;
let filterManager: FilterManager;
- let readyFilters: Filter[];
+ let readyFilters: esFilters.Filter[];
beforeEach(() => {
updateListener = sinon.stub();
- appStateStub = new StubState();
- globalStateStub = new StubState();
filterManager = new FilterManager(setupMock.uiSettings);
readyFilters = getFiltersArray();
-
- // FilterStateManager is tested indirectly.
- // Therefore, we don't need it's instance.
- new FilterStateManager(
- globalStateStub,
- () => {
- return appStateStub;
- },
- filterManager
- );
});
afterEach(async () => {
@@ -84,32 +65,6 @@ describe('filter_manager', () => {
expect(updateSubscription).toBeInstanceOf(Subscription);
expect(fetchSubscription).toBeInstanceOf(Subscription);
});
-
- test('should observe global state', done => {
- updateSubscription = filterManager.getUpdates$().subscribe(() => {
- expect(filterManager.getGlobalFilters()).toHaveLength(1);
- if (updateSubscription) {
- updateSubscription.unsubscribe();
- }
- done();
- });
-
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, true, true, 'age', 34);
- globalStateStub.filters.push(f1);
- });
-
- test('should observe app state', done => {
- updateSubscription = filterManager.getUpdates$().subscribe(() => {
- expect(filterManager.getAppFilters()).toHaveLength(1);
- if (updateSubscription) {
- updateSubscription.unsubscribe();
- }
- done();
- });
-
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- appStateStub.filters.push(f1);
- });
});
describe('get \\ set filters', () => {
@@ -127,7 +82,7 @@ describe('filter_manager', () => {
test('app state should be set', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.setFilters([f1]);
expect(filterManager.getAppFilters()).toHaveLength(1);
expect(filterManager.getGlobalFilters()).toHaveLength(0);
@@ -141,7 +96,7 @@ describe('filter_manager', () => {
test('global state should be set', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.setFilters([f1]);
expect(filterManager.getAppFilters()).toHaveLength(0);
expect(filterManager.getGlobalFilters()).toHaveLength(1);
@@ -155,8 +110,8 @@ describe('filter_manager', () => {
test('both states should be set', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
filterManager.setFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(1);
expect(filterManager.getGlobalFilters()).toHaveLength(1);
@@ -173,8 +128,8 @@ describe('filter_manager', () => {
test('set state should override previous state', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
filterManager.setFilters([f1]);
filterManager.setFilters([f2]);
@@ -195,7 +150,7 @@ describe('filter_manager', () => {
test('changing a disabled filter should fire only update event', async function() {
const updateStub = jest.fn();
const fetchStub = jest.fn();
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, true, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, true, false, 'age', 34);
filterManager.setFilters([f1]);
@@ -220,47 +175,63 @@ describe('filter_manager', () => {
describe('add filters', () => {
test('app state should accept a single filter', async function() {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.addFilters(f1);
- expect(filterManager.getAppFilters()).toHaveLength(1);
+ const appFilters = filterManager.getAppFilters();
+ expect(appFilters).toHaveLength(1);
+ expect(appFilters[0]).toEqual(f1);
expect(filterManager.getGlobalFilters()).toHaveLength(0);
expect(updateListener.callCount).toBe(1);
- expect(appStateStub.filters.length).toBe(1);
});
test('app state should accept array', async () => {
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'female');
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'female');
filterManager.addFilters([f1]);
filterManager.addFilters([f2]);
- expect(filterManager.getAppFilters()).toHaveLength(2);
+ const appFilters = filterManager.getAppFilters();
+ expect(appFilters).toHaveLength(2);
+ expect(appFilters).toEqual([f2, f1]);
expect(filterManager.getGlobalFilters()).toHaveLength(0);
- expect(appStateStub.filters.length).toBe(2);
});
test('global state should accept a single filer', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.addFilters(f1);
expect(filterManager.getAppFilters()).toHaveLength(0);
- expect(filterManager.getGlobalFilters()).toHaveLength(1);
+ const globalFilters = filterManager.getGlobalFilters();
+ expect(globalFilters).toHaveLength(1);
+ expect(globalFilters[0]).toEqual(f1);
expect(updateListener.callCount).toBe(1);
- expect(globalStateStub.filters.length).toBe(1);
});
test('global state should be accept array', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'gender', 'female');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(
+ esFilters.FilterStateStore.GLOBAL_STATE,
+ false,
+ false,
+ 'gender',
+ 'female'
+ );
filterManager.addFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(0);
- expect(filterManager.getGlobalFilters()).toHaveLength(2);
- expect(globalStateStub.filters.length).toBe(2);
+ const globalFilters = filterManager.getGlobalFilters();
+ expect(globalFilters).toHaveLength(2);
+ expect(globalFilters).toEqual([f2, f1]);
});
test('add multiple filters at once', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'gender', 'female');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(
+ esFilters.FilterStateStore.GLOBAL_STATE,
+ false,
+ false,
+ 'gender',
+ 'female'
+ );
filterManager.addFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(0);
expect(filterManager.getGlobalFilters()).toHaveLength(2);
@@ -269,8 +240,8 @@ describe('filter_manager', () => {
test('add same filter to global and app', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.addFilters([f1, f2]);
// FILTER SHOULD BE ADDED ONLY ONCE, TO GLOBAL
@@ -281,8 +252,8 @@ describe('filter_manager', () => {
test('add same filter with different values to global and app', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.addFilters([f1, f2]);
// FILTER SHOULD BE ADDED TWICE
@@ -292,7 +263,7 @@ describe('filter_manager', () => {
});
test('add filter with no state, and force pin', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
f1.$state = undefined;
filterManager.addFilters([f1], true);
@@ -301,12 +272,12 @@ describe('filter_manager', () => {
const f1Output = filterManager.getFilters()[0];
expect(f1Output.$state).toBeDefined();
if (f1Output.$state) {
- expect(f1Output.$state.store).toBe(FilterStateStore.GLOBAL_STATE);
+ expect(f1Output.$state.store).toBe(esFilters.FilterStateStore.GLOBAL_STATE);
}
});
test('add filter with no state, and dont force pin', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
f1.$state = undefined;
filterManager.addFilters([f1], false);
@@ -315,7 +286,7 @@ describe('filter_manager', () => {
const f1Output = filterManager.getFilters()[0];
expect(f1Output.$state).toBeDefined();
if (f1Output.$state) {
- expect(f1Output.$state.store).toBe(FilterStateStore.APP_STATE);
+ expect(f1Output.$state.store).toBe(esFilters.FilterStateStore.APP_STATE);
}
});
@@ -327,11 +298,11 @@ describe('filter_manager', () => {
// global filters should be listed first
let res = filterManager.getFilters();
expect(res).toHaveLength(2);
- expect(res[0].$state && res[0].$state.store).toEqual(FilterStateStore.GLOBAL_STATE);
+ expect(res[0].$state && res[0].$state.store).toEqual(esFilters.FilterStateStore.GLOBAL_STATE);
expect(res[0].meta.disabled).toEqual(filters[1].meta.disabled);
expect(res[0].query).toEqual(filters[1].query);
- expect(res[1].$state && res[1].$state.store).toEqual(FilterStateStore.APP_STATE);
+ expect(res[1].$state && res[1].$state.store).toEqual(esFilters.FilterStateStore.APP_STATE);
expect(res[1].meta.disabled).toEqual(filters[0].meta.disabled);
expect(res[1].query).toEqual(filters[0].query);
@@ -351,7 +322,7 @@ describe('filter_manager', () => {
const res = filterManager.getFilters();
expect(res).toHaveLength(3);
_.each(res, function(filter) {
- expect(filter.$state && filter.$state.store).toBe(FilterStateStore.GLOBAL_STATE);
+ expect(filter.$state && filter.$state.store).toBe(esFilters.FilterStateStore.GLOBAL_STATE);
});
});
@@ -370,7 +341,6 @@ describe('filter_manager', () => {
filterManager.addFilters(negatedFilter);
// The negated filter should overwrite the positive one
- expect(globalStateStub.filters.length).toBe(1);
expect(filterManager.getFilters()).toHaveLength(1);
expect(filterManager.getFilters()[0]).toEqual(negatedFilter);
});
@@ -383,16 +353,16 @@ describe('filter_manager', () => {
filterManager.addFilters(negatedFilter);
// The negated filter should overwrite the positive one
- expect(globalStateStub.filters.length).toBe(1);
- expect(globalStateStub.filters[0]).toEqual(negatedFilter);
+ expect(filterManager.getFilters()).toHaveLength(1);
+ expect(filterManager.getFilters()[0]).toEqual(negatedFilter);
// Add negate: false version of the filter
const filter = _.cloneDeep(readyFilters[0]);
filter.meta.negate = false;
filterManager.addFilters(filter);
- expect(globalStateStub.filters.length).toBe(1);
- expect(globalStateStub.filters[0]).toEqual(filter);
+ expect(filterManager.getFilters()).toHaveLength(1);
+ expect(filterManager.getFilters()[0]).toEqual(filter);
});
test('should fire the update and fetch events', async function() {
@@ -409,10 +379,6 @@ describe('filter_manager', () => {
filterManager.addFilters(readyFilters);
- // updates should trigger state saves
- expect(appStateStub.save.callCount).toBe(1);
- expect(globalStateStub.save.callCount).toBe(1);
-
// this time, events should be emitted
expect(fetchStub).toBeCalledTimes(1);
expect(updateStub).toBeCalledTimes(1);
@@ -420,26 +386,26 @@ describe('filter_manager', () => {
});
describe('filter reconciliation', function() {
- test('should de-dupe appStateStub filters being added', async function() {
+ test('should de-dupe app filters being added', async function() {
const newFilter = _.cloneDeep(readyFilters[1]);
filterManager.addFilters(readyFilters, false);
- expect(appStateStub.filters.length).toBe(3);
+ expect(filterManager.getFilters()).toHaveLength(3);
filterManager.addFilters(newFilter, false);
- expect(appStateStub.filters.length).toBe(3);
+ expect(filterManager.getFilters()).toHaveLength(3);
});
- test('should de-dupe globalStateStub filters being added', async function() {
+ test('should de-dupe global filters being added', async function() {
const newFilter = _.cloneDeep(readyFilters[1]);
filterManager.addFilters(readyFilters, true);
- expect(globalStateStub.filters.length).toBe(3);
+ expect(filterManager.getFilters()).toHaveLength(3);
filterManager.addFilters(newFilter, true);
- expect(globalStateStub.filters.length).toBe(3);
+ expect(filterManager.getFilters()).toHaveLength(3);
});
- test('should de-dupe globalStateStub filters being set', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ test('should de-dupe global filters being set', async () => {
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
const f2 = _.cloneDeep(f1);
filterManager.setFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(0);
@@ -447,8 +413,8 @@ describe('filter_manager', () => {
expect(filterManager.getFilters()).toHaveLength(1);
});
- test('should de-dupe appStateStub filters being set', async () => {
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ test('should de-dupe app filters being set', async () => {
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
const f2 = _.cloneDeep(f1);
filterManager.setFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(1);
@@ -463,7 +429,7 @@ describe('filter_manager', () => {
const appFilter = _.cloneDeep(readyFilters[idx]);
appFilter.meta.negate = true;
appFilter.$state = {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
};
filterManager.addFilters(appFilter);
const res = filterManager.getFilters();
@@ -475,12 +441,12 @@ describe('filter_manager', () => {
});
});
- test('should merge conflicting appStateStub filters', async function() {
+ test('should merge conflicting app filters', async function() {
filterManager.addFilters(readyFilters, true);
const appFilter = _.cloneDeep(readyFilters[1]);
appFilter.meta.negate = true;
appFilter.$state = {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
};
filterManager.addFilters(appFilter, false);
@@ -489,7 +455,7 @@ describe('filter_manager', () => {
expect(res).toHaveLength(3);
expect(
res.filter(function(filter) {
- return filter.$state && filter.$state.store === FilterStateStore.GLOBAL_STATE;
+ return filter.$state && filter.$state.store === esFilters.FilterStateStore.GLOBAL_STATE;
}).length
).toBe(3);
});
@@ -542,8 +508,8 @@ describe('filter_manager', () => {
});
test('remove on full should clean and fire events', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
filterManager.setFilters([f1, f2]);
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
@@ -553,9 +519,9 @@ describe('filter_manager', () => {
});
test('remove non existing filter should do nothing and not fire events', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
- const f3 = getFilter(FilterStateStore.APP_STATE, false, false, 'country', 'US');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f3 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'country', 'US');
filterManager.setFilters([f1, f2]);
expect(filterManager.getFilters()).toHaveLength(2);
@@ -566,9 +532,9 @@ describe('filter_manager', () => {
});
test('remove existing filter should remove and fire events', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
- const f3 = getFilter(FilterStateStore.APP_STATE, false, false, 'country', 'US');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f3 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'country', 'US');
filterManager.setFilters([f1, f2, f3]);
expect(filterManager.getFilters()).toHaveLength(3);
@@ -580,16 +546,16 @@ describe('filter_manager', () => {
test('should remove the filter from appStateStub', async function() {
filterManager.addFilters(readyFilters, false);
- expect(appStateStub.filters).toHaveLength(3);
+ expect(filterManager.getAppFilters()).toHaveLength(3);
filterManager.removeFilter(readyFilters[0]);
- expect(appStateStub.filters).toHaveLength(2);
+ expect(filterManager.getAppFilters()).toHaveLength(2);
});
test('should remove the filter from globalStateStub', async function() {
filterManager.addFilters(readyFilters, true);
- expect(globalStateStub.filters).toHaveLength(3);
+ expect(filterManager.getGlobalFilters()).toHaveLength(3);
filterManager.removeFilter(readyFilters[0]);
- expect(globalStateStub.filters).toHaveLength(2);
+ expect(filterManager.getGlobalFilters()).toHaveLength(2);
});
test('should fire the update and fetch events', async function() {
@@ -619,8 +585,8 @@ describe('filter_manager', () => {
filterManager.removeFilter(readyFilters[0]);
- expect(globalStateStub.filters).toHaveLength(1);
- expect(appStateStub.filters).toHaveLength(1);
+ expect(filterManager.getAppFilters()).toHaveLength(1);
+ expect(filterManager.getGlobalFilters()).toHaveLength(1);
});
test('should remove matching filters by comparison', async function() {
@@ -629,12 +595,12 @@ describe('filter_manager', () => {
filterManager.removeFilter(_.cloneDeep(readyFilters[0]));
- expect(globalStateStub.filters).toHaveLength(1);
- expect(appStateStub.filters).toHaveLength(1);
+ expect(filterManager.getAppFilters()).toHaveLength(1);
+ expect(filterManager.getGlobalFilters()).toHaveLength(1);
filterManager.removeFilter(_.cloneDeep(readyFilters[2]));
- expect(globalStateStub.filters).toHaveLength(1);
- expect(appStateStub.filters).toHaveLength(0);
+ expect(filterManager.getAppFilters()).toHaveLength(0);
+ expect(filterManager.getGlobalFilters()).toHaveLength(1);
});
test('should do nothing with a non-matching filter', async function() {
@@ -645,19 +611,19 @@ describe('filter_manager', () => {
missedFilter.meta.negate = !readyFilters[0].meta.negate;
filterManager.removeFilter(missedFilter);
- expect(globalStateStub.filters).toHaveLength(2);
- expect(appStateStub.filters).toHaveLength(1);
+ expect(filterManager.getAppFilters()).toHaveLength(1);
+ expect(filterManager.getGlobalFilters()).toHaveLength(2);
});
test('should remove all the filters from both states', async function() {
filterManager.addFilters([readyFilters[0], readyFilters[1]], true);
filterManager.addFilters([readyFilters[2]], false);
- expect(globalStateStub.filters).toHaveLength(2);
- expect(appStateStub.filters).toHaveLength(1);
+ expect(filterManager.getAppFilters()).toHaveLength(1);
+ expect(filterManager.getGlobalFilters()).toHaveLength(2);
filterManager.removeAll();
- expect(globalStateStub.filters).toHaveLength(0);
- expect(appStateStub.filters).toHaveLength(0);
+ expect(filterManager.getAppFilters()).toHaveLength(0);
+ expect(filterManager.getGlobalFilters()).toHaveLength(0);
});
});
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.ts b/src/plugins/data/public/query/filter_manager/filter_manager.ts
similarity index 80%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.ts
rename to src/plugins/data/public/query/filter_manager/filter_manager.ts
index b3d6bd6873f50..f691398fb91d3 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_manager.ts
+++ b/src/plugins/data/public/query/filter_manager/filter_manager.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import { Filter, isFilterPinned, FilterStateStore } from '@kbn/es-query';
-
import _ from 'lodash';
import { Subject } from 'rxjs';
@@ -28,10 +26,11 @@ import { compareFilters } from './lib/compare_filters';
import { mapAndFlattenFilters } from './lib/map_and_flatten_filters';
import { uniqFilters } from './lib/uniq_filters';
import { onlyDisabledFiltersChanged } from './lib/only_disabled';
-import { PartitionedFilters } from './partitioned_filters';
+import { PartitionedFilters } from './types';
+import { esFilters } from '../../../common/es_query';
export class FilterManager {
- private filters: Filter[] = [];
+ private filters: esFilters.Filter[] = [];
private updated$: Subject = new Subject();
private fetch$: Subject = new Subject();
private uiSettings: UiSettingsClientContract;
@@ -40,7 +39,7 @@ export class FilterManager {
this.uiSettings = uiSettings;
}
- private mergeIncomingFilters(partitionedFilters: PartitionedFilters): Filter[] {
+ private mergeIncomingFilters(partitionedFilters: PartitionedFilters): esFilters.Filter[] {
const globalFilters = partitionedFilters.globalFilters;
const appFilters = partitionedFilters.appFilters;
@@ -61,23 +60,26 @@ export class FilterManager {
return FilterManager.mergeFilters(appFilters, globalFilters);
}
- private static mergeFilters(appFilters: Filter[], globalFilters: Filter[]): Filter[] {
+ private static mergeFilters(
+ appFilters: esFilters.Filter[],
+ globalFilters: esFilters.Filter[]
+ ): esFilters.Filter[] {
return uniqFilters(appFilters.reverse().concat(globalFilters.reverse())).reverse();
}
- private static partitionFilters(filters: Filter[]): PartitionedFilters {
- const [globalFilters, appFilters] = _.partition(filters, isFilterPinned);
+ private static partitionFilters(filters: esFilters.Filter[]): PartitionedFilters {
+ const [globalFilters, appFilters] = _.partition(filters, esFilters.isFilterPinned);
return {
globalFilters,
appFilters,
};
}
- private handleStateUpdate(newFilters: Filter[]) {
+ private handleStateUpdate(newFilters: esFilters.Filter[]) {
// global filters should always be first
- newFilters.sort(({ $state: a }: Filter, { $state: b }: Filter): number => {
- return a!.store === FilterStateStore.GLOBAL_STATE &&
- b!.store !== FilterStateStore.GLOBAL_STATE
+ newFilters.sort(({ $state: a }: esFilters.Filter, { $state: b }: esFilters.Filter): number => {
+ return a!.store === esFilters.FilterStateStore.GLOBAL_STATE &&
+ b!.store !== esFilters.FilterStateStore.GLOBAL_STATE
? -1
: 1;
});
@@ -124,7 +126,7 @@ export class FilterManager {
/* Setters */
- public addFilters(filters: Filter[] | Filter, pinFilterStatus?: boolean) {
+ public addFilters(filters: esFilters.Filter[] | esFilters.Filter, pinFilterStatus?: boolean) {
if (!Array.isArray(filters)) {
filters = [filters];
}
@@ -139,7 +141,10 @@ export class FilterManager {
// Set the store of all filters. For now.
// In the future, all filters should come in with filter state store already set.
- const store = pinFilterStatus ? FilterStateStore.GLOBAL_STATE : FilterStateStore.APP_STATE;
+ const store = pinFilterStatus
+ ? esFilters.FilterStateStore.GLOBAL_STATE
+ : esFilters.FilterStateStore.APP_STATE;
+
FilterManager.setFiltersStore(filters, store);
const mappedFilters = mapAndFlattenFilters(filters);
@@ -154,14 +159,14 @@ export class FilterManager {
this.handleStateUpdate(newFilters);
}
- public setFilters(newFilters: Filter[]) {
+ public setFilters(newFilters: esFilters.Filter[]) {
const mappedFilters = mapAndFlattenFilters(newFilters);
const newPartitionedFilters = FilterManager.partitionFilters(mappedFilters);
const mergedFilters = this.mergeIncomingFilters(newPartitionedFilters);
this.handleStateUpdate(mergedFilters);
}
- public removeFilter(filter: Filter) {
+ public removeFilter(filter: esFilters.Filter) {
const filterIndex = _.findIndex(this.filters, item => {
return _.isEqual(item.meta, filter.meta) && _.isEqual(item.query, filter.query);
});
@@ -177,8 +182,8 @@ export class FilterManager {
this.setFilters([]);
}
- public static setFiltersStore(filters: Filter[], store: FilterStateStore) {
- _.map(filters, (filter: Filter) => {
+ public static setFiltersStore(filters: esFilters.Filter[], store: esFilters.FilterStateStore) {
+ _.map(filters, (filter: esFilters.Filter) => {
// Override status only for filters that didn't have state in the first place.
if (filter.$state === undefined) {
filter.$state = { store };
diff --git a/test/api_integration/services/chance.js b/src/plugins/data/public/query/filter_manager/index.ts
similarity index 77%
rename from test/api_integration/services/chance.js
rename to src/plugins/data/public/query/filter_manager/index.ts
index 3c5d9dc704aae..7955cdd825ee6 100644
--- a/test/api_integration/services/chance.js
+++ b/src/plugins/data/public/query/filter_manager/index.ts
@@ -17,13 +17,8 @@
* under the License.
*/
-import Chance from 'chance';
+export { FilterManager } from './filter_manager';
-export function ChanceProvider({ getService }) {
- const log = getService('log');
-
- const seed = Date.now();
- log.debug('randomness seed: %j', seed);
-
- return new Chance(seed);
-}
+export { uniqFilters } from './lib/uniq_filters';
+export { mapAndFlattenFilters } from './lib/map_and_flatten_filters';
+export { onlyDisabledFiltersChanged } from './lib/only_disabled';
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/compare_filters.test.ts b/src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts
similarity index 67%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/compare_filters.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts
index e8244feb988b6..6bde6b528d07b 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/compare_filters.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts
@@ -16,42 +16,48 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { buildQueryFilter, buildEmptyFilter, FilterStateStore } from '@kbn/es-query';
+
import { compareFilters } from './compare_filters';
+import { esFilters } from '../../../../common/es_query';
describe('filter manager utilities', () => {
describe('compare filters', () => {
test('should compare filters', () => {
- const f1 = buildQueryFilter(
+ const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index'
+ 'index',
+ ''
);
- const f2 = buildEmptyFilter(true);
+ const f2 = esFilters.buildEmptyFilter(true);
expect(compareFilters(f1, f2)).toBeFalsy();
});
test('should compare duplicates', () => {
- const f1 = buildQueryFilter(
+ const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index'
+ 'index',
+ ''
);
- const f2 = buildQueryFilter(
+ const f2 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index'
+ 'index',
+ ''
);
expect(compareFilters(f1, f2)).toBeTruthy();
});
test('should compare duplicates, ignoring meta attributes', () => {
- const f1 = buildQueryFilter(
+ const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index1'
+ 'index1',
+ ''
);
- const f2 = buildQueryFilter(
+ const f2 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index2'
+ 'index2',
+ ''
);
expect(compareFilters(f1, f2)).toBeTruthy();
@@ -59,12 +65,20 @@ describe('filter manager utilities', () => {
test('should compare duplicates, ignoring $state attributes', () => {
const f1 = {
- $state: { store: FilterStateStore.APP_STATE },
- ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
+ ...esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
};
const f2 = {
- $state: { store: FilterStateStore.GLOBAL_STATE },
- ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ $state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
+ ...esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
};
expect(compareFilters(f1, f2)).toBeTruthy();
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/compare_filters.ts b/src/plugins/data/public/query/filter_manager/lib/compare_filters.ts
similarity index 84%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/compare_filters.ts
rename to src/plugins/data/public/query/filter_manager/lib/compare_filters.ts
index 44bc333ae2b4f..2a7cbe6e3303b 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/compare_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/compare_filters.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { Filter, FilterMeta } from '@kbn/es-query';
import { defaults, isEqual, omit } from 'lodash';
+import { esFilters } from '../../../../common/es_query';
/**
* Compare two filters to see if they match
@@ -29,10 +29,14 @@ import { defaults, isEqual, omit } from 'lodash';
*
* @returns {bool} Filters are the same
*/
-export const compareFilters = (first: Filter, second: Filter, comparatorOptions: any = {}) => {
+export const compareFilters = (
+ first: esFilters.Filter,
+ second: esFilters.Filter,
+ comparatorOptions: any = {}
+) => {
let comparators: any = {};
- const mapFilter = (filter: Filter) => {
- const cleaned: FilterMeta = omit(filter, excludedAttributes);
+ const mapFilter = (filter: esFilters.Filter) => {
+ const cleaned: esFilters.FilterMeta = omit(filter, excludedAttributes);
if (comparators.negate) cleaned.negate = filter.meta && Boolean(filter.meta.negate);
if (comparators.disabled) cleaned.disabled = filter.meta && Boolean(filter.meta.disabled);
diff --git a/src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts b/src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts
new file mode 100644
index 0000000000000..9b493add0886c
--- /dev/null
+++ b/src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts
@@ -0,0 +1,103 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { dedupFilters } from './dedup_filters';
+import { esFilters } from '../../../../common/es_query';
+
+describe('filter manager utilities', () => {
+ describe('dedupFilters(existing, filters)', () => {
+ test('should return only filters which are not in the existing', () => {
+ const existing: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index', ''),
+ esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
+ ];
+ const filters: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index', ''),
+ esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
+ ];
+ const results = dedupFilters(existing, filters);
+
+ expect(results).toContain(filters[0]);
+ expect(results).not.toContain(filters[1]);
+ });
+
+ test('should ignore the disabled attribute when comparing ', () => {
+ const existing: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index', ''),
+ {
+ ...esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index1',
+ ''
+ ),
+ meta: { disabled: true, negate: false, alias: null },
+ },
+ ];
+ const filters: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index', ''),
+ esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index1',
+ ''
+ ),
+ ];
+ const results = dedupFilters(existing, filters);
+
+ expect(results).toContain(filters[0]);
+ expect(results).not.toContain(filters[1]);
+ });
+
+ test('should ignore $state attribute', () => {
+ const existing: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index', ''),
+ {
+ ...esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
+ },
+ ];
+ const filters: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index', ''),
+ {
+ ...esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
+ $state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
+ },
+ ];
+ const results = dedupFilters(existing, filters);
+
+ expect(results).toContain(filters[0]);
+ expect(results).not.toContain(filters[1]);
+ });
+ });
+});
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/dedup_filters.ts b/src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts
similarity index 86%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/dedup_filters.ts
rename to src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts
index 9565cbd80b779..6d6f49cb5e833 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/dedup_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { filter, find } from 'lodash';
import { compareFilters } from './compare_filters';
+import { esFilters } from '../../../../../../plugins/data/public';
/**
* Combine 2 filter collections, removing duplicates
@@ -31,8 +31,8 @@ import { compareFilters } from './compare_filters';
* @returns {object} An array of filters that were not in existing
*/
export const dedupFilters = (
- existingFilters: Filter[],
- filters: Filter[],
+ existingFilters: esFilters.Filter[],
+ filters: esFilters.Filter[],
comparatorOptions: any = {}
) => {
if (!Array.isArray(filters)) {
@@ -41,8 +41,8 @@ export const dedupFilters = (
return filter(
filters,
- (f: Filter) =>
- !find(existingFilters, (existingFilter: Filter) =>
+ (f: esFilters.Filter) =>
+ !find(existingFilters, (existingFilter: esFilters.Filter) =>
compareFilters(existingFilter, f, comparatorOptions)
)
);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/generate_mapping_chain.test.ts b/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.test.ts
similarity index 89%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/generate_mapping_chain.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.test.ts
index c0c509634aba2..dfe3a093c6614 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/generate_mapping_chain.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.test.ts
@@ -18,8 +18,8 @@
*/
import sinon from 'sinon';
-import { Filter, buildEmptyFilter } from '@kbn/es-query';
import { generateMappingChain } from './generate_mapping_chain';
+import { esFilters } from '../../../../../../plugins/data/public';
describe('filter manager utilities', () => {
let mapping: any;
@@ -32,7 +32,7 @@ describe('filter manager utilities', () => {
describe('generateMappingChain()', () => {
test('should create a chaining function which calls the next function if the error is thrown', async () => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.throws(filter);
next.returns('good');
@@ -45,7 +45,7 @@ describe('filter manager utilities', () => {
});
test('should create a chaining function which DOES NOT call the next function if the result is returned', async () => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.returns('good');
next.returns('bad');
@@ -57,7 +57,7 @@ describe('filter manager utilities', () => {
});
test('should resolve result for the mapping function', async () => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.returns({ key: 'test', value: 'example' });
@@ -70,7 +70,7 @@ describe('filter manager utilities', () => {
test('should call the mapping function with the argument to the chain', async () => {
// @ts-ignore
- const filter: Filter = { test: 'example' };
+ const filter: esFilters.Filter = { test: 'example' };
mapping.returns({ key: 'test', value: 'example' });
@@ -84,7 +84,7 @@ describe('filter manager utilities', () => {
});
test('should resolve result for the next function', async () => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.throws(filter);
next.returns({ key: 'test', value: 'example' });
@@ -98,7 +98,7 @@ describe('filter manager utilities', () => {
});
test('should throw an error if no functions match', async done => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.throws(filter);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/generate_mapping_chain.ts b/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.ts
similarity index 91%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/generate_mapping_chain.ts
rename to src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.ts
index 760270edd7170..b6764389e0db9 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/generate_mapping_chain.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.ts
@@ -16,14 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
const noop = () => {
throw new Error('No mappings have been found for filter.');
};
export const generateMappingChain = (fn: Function, next: Function = noop) => {
- return (filter: Filter) => {
+ return (filter: esFilters.Filter) => {
try {
return fn(filter);
} catch (result) {
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_and_flatten_filters.test.ts b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts
similarity index 93%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_and_flatten_filters.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts
index fce2aa0373ebe..9a0d0d93698f6 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_and_flatten_filters.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { mapAndFlattenFilters } from './map_and_flatten_filters';
+import { esFilters } from '../../../../../data/public';
describe('filter manager utilities', () => {
describe('mapAndFlattenFilters()', () => {
let filters: unknown;
- function getDisplayName(filter: Filter) {
+ function getDisplayName(filter: esFilters.Filter) {
return typeof filter.meta.value === 'function' ? filter.meta.value() : filter.meta.value;
}
@@ -45,7 +45,7 @@ describe('filter manager utilities', () => {
});
test('should map and flatten the filters', () => {
- const results = mapAndFlattenFilters(filters as Filter[]);
+ const results = mapAndFlattenFilters(filters as esFilters.Filter[]);
expect(results).toHaveLength(5);
expect(results[0]).toHaveProperty('meta');
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_and_flatten_filters.ts b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.ts
similarity index 80%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_and_flatten_filters.ts
rename to src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.ts
index b350c3957b142..5326d59f3e32b 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_and_flatten_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.ts
@@ -18,9 +18,9 @@
*/
import { compact, flatten } from 'lodash';
-import { Filter } from '@kbn/es-query';
import { mapFilter } from './map_filter';
+import { esFilters } from '../../../../../data/public';
-export const mapAndFlattenFilters = (filters: Filter[]) => {
- return compact(flatten(filters)).map((item: Filter) => mapFilter(item));
+export const mapAndFlattenFilters = (filters: esFilters.Filter[]) => {
+ return compact(flatten(filters)).map((item: esFilters.Filter) => mapFilter(item));
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_filter.test.ts b/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts
similarity index 89%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_filter.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts
index c1d4ebfd3f7fc..0d115125451ee 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_filter.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts
@@ -17,11 +17,11 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { mapFilter } from './map_filter';
+import { esFilters } from '../../../../../data/public';
describe('filter manager utilities', () => {
- function getDisplayName(filter: Filter) {
+ function getDisplayName(filter: esFilters.Filter) {
return typeof filter.meta.value === 'function' ? filter.meta.value() : filter.meta.value;
}
@@ -31,7 +31,7 @@ describe('filter manager utilities', () => {
meta: { index: 'logstash-*' },
query: { match: { _type: { query: 'apache', type: 'phrase' } } },
};
- const after = mapFilter(before as Filter);
+ const after = mapFilter(before as esFilters.Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', '_type');
@@ -43,7 +43,7 @@ describe('filter manager utilities', () => {
test('should map exists filters', async () => {
const before: any = { meta: { index: 'logstash-*' }, exists: { field: '@timestamp' } };
- const after = mapFilter(before as Filter);
+ const after = mapFilter(before as esFilters.Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', '@timestamp');
@@ -55,7 +55,7 @@ describe('filter manager utilities', () => {
test('should map missing filters', async () => {
const before: any = { meta: { index: 'logstash-*' }, missing: { field: '@timestamp' } };
- const after = mapFilter(before as Filter);
+ const after = mapFilter(before as esFilters.Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', '@timestamp');
@@ -67,7 +67,7 @@ describe('filter manager utilities', () => {
test('should map json filter', async () => {
const before: any = { meta: { index: 'logstash-*' }, query: { match_all: {} } };
- const after = mapFilter(before as Filter);
+ const after = mapFilter(before as esFilters.Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', 'query');
@@ -81,7 +81,7 @@ describe('filter manager utilities', () => {
const before: any = { meta: { index: 'logstash-*' } };
try {
- mapFilter(before as Filter);
+ mapFilter(before as esFilters.Filter);
} catch (e) {
expect(e).toBeInstanceOf(Error);
expect(e.message).toBe('No mappings have been found for filter.');
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_filter.ts b/src/plugins/data/public/query/filter_manager/lib/map_filter.ts
similarity index 81%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_filter.ts
rename to src/plugins/data/public/query/filter_manager/lib/map_filter.ts
index c0d251e647fd1..2dc855caabfd3 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_filter.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/map_filter.ts
@@ -17,22 +17,22 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { reduceRight } from 'lodash';
-import { mapMatchAll } from './map_match_all';
-import { mapPhrase } from './map_phrase';
-import { mapPhrases } from './map_phrases';
-import { mapRange } from './map_range';
-import { mapExists } from './map_exists';
-import { mapMissing } from './map_missing';
-import { mapQueryString } from './map_query_string';
-import { mapGeoBoundingBox } from './map_geo_bounding_box';
-import { mapGeoPolygon } from './map_geo_polygon';
-import { mapDefault } from './map_default';
+import { mapMatchAll } from './mappers/map_match_all';
+import { mapPhrase } from './mappers/map_phrase';
+import { mapPhrases } from './mappers/map_phrases';
+import { mapRange } from './mappers/map_range';
+import { mapExists } from './mappers/map_exists';
+import { mapMissing } from './mappers/map_missing';
+import { mapQueryString } from './mappers/map_query_string';
+import { mapGeoBoundingBox } from './mappers/map_geo_bounding_box';
+import { mapGeoPolygon } from './mappers/map_geo_polygon';
+import { mapDefault } from './mappers/map_default';
import { generateMappingChain } from './generate_mapping_chain';
+import { esFilters } from '../../../../../data/public';
-export function mapFilter(filter: Filter) {
+export function mapFilter(filter: esFilters.Filter) {
/** Mappers **/
// Each mapper is a simple promise function that test if the mapper can
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_default.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.test.ts
similarity index 85%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_default.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_default.test.ts
index acb6e89711033..f10766901e5b7 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_default.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.test.ts
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { CustomFilter, buildEmptyFilter, buildQueryFilter } from '@kbn/es-query';
+
import { mapDefault } from './map_default';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapDefault()', () => {
test('should return the key and value for matching filters', async () => {
- const filter: CustomFilter = buildQueryFilter({ match_all: {} }, 'index');
+ const filter = esFilters.buildQueryFilter({ match_all: {} }, 'index', '');
const result = mapDefault(filter);
expect(result).toHaveProperty('key', 'query');
@@ -30,7 +31,7 @@ describe('filter manager utilities', () => {
});
test('should return undefined if there is no valid key', async () => {
- const filter = buildEmptyFilter(true) as CustomFilter;
+ const filter = esFilters.buildEmptyFilter(true);
try {
mapDefault(filter);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_default.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.ts
similarity index 86%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_default.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_default.ts
index 70c191879c22e..fd84c5c742589 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_default.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.ts
@@ -17,15 +17,15 @@
* under the License.
*/
-import { Filter, FILTERS } from '@kbn/es-query';
import { find, keys, get } from 'lodash';
+import { esFilters } from '../../../../../common/es_query';
-export const mapDefault = (filter: Filter) => {
+export const mapDefault = (filter: esFilters.Filter) => {
const metaProperty = /(^\$|meta)/;
const key = find(keys(filter), item => !item.match(metaProperty));
if (key) {
- const type = FILTERS.CUSTOM;
+ const type = esFilters.FILTERS.CUSTOM;
const value = JSON.stringify(get(filter, key, {}));
return { type, key, value };
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_exists.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.test.ts
similarity index 86%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_exists.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.test.ts
index c352d3e2b9a73..ff0ed4f4e4d94 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_exists.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.test.ts
@@ -16,14 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { ExistsFilter, buildEmptyFilter, buildExistsFilter } from '@kbn/es-query';
+
import { mapExists } from './map_exists';
import { mapQueryString } from './map_query_string';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapExists()', () => {
test('should return the key and value for matching filters', async () => {
- const filter: ExistsFilter = buildExistsFilter({ name: '_type' }, 'index');
+ const filter = esFilters.buildExistsFilter({ name: '_type' }, 'index');
const result = mapExists(filter);
expect(result).toHaveProperty('key', '_type');
@@ -31,7 +32,7 @@ describe('filter manager utilities', () => {
});
test('should return undefined for none matching', async done => {
- const filter = buildEmptyFilter(true) as ExistsFilter;
+ const filter = esFilters.buildEmptyFilter(true);
try {
mapQueryString(filter);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_exists.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.ts
similarity index 79%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_exists.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.ts
index d539219a1ca24..63665bdd88ccb 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_exists.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-import { Filter, isExistsFilter, FILTERS } from '@kbn/es-query';
import { get } from 'lodash';
+import { esFilters } from '../../../../../common/es_query';
-export const mapExists = (filter: Filter) => {
- if (isExistsFilter(filter)) {
+export const mapExists = (filter: esFilters.Filter) => {
+ if (esFilters.isExistsFilter(filter)) {
return {
- type: FILTERS.EXISTS,
- value: FILTERS.EXISTS,
+ type: esFilters.FILTERS.EXISTS,
+ value: esFilters.FILTERS.EXISTS,
key: get(filter, 'exists.field'),
};
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_bounding_box.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.test.ts
similarity index 94%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_bounding_box.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.test.ts
index c3c99e6f6c4a3..5fca4a652bad8 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_bounding_box.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.test.ts
@@ -18,7 +18,7 @@
*/
import { mapGeoBoundingBox } from './map_geo_bounding_box';
-import { Filter, GeoBoundingBoxFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapGeoBoundingBox()', () => {
@@ -34,7 +34,7 @@ describe('filter manager utilities', () => {
bottom_right: { lat: 15, lon: 20 },
},
},
- } as GeoBoundingBoxFilter;
+ } as esFilters.GeoBoundingBoxFilter;
const result = mapGeoBoundingBox(filter);
@@ -63,7 +63,8 @@ describe('filter manager utilities', () => {
bottom_right: { lat: 15, lon: 20 },
},
},
- } as GeoBoundingBoxFilter;
+ } as esFilters.GeoBoundingBoxFilter;
+
const result = mapGeoBoundingBox(filter);
expect(result).toHaveProperty('key', 'point');
@@ -82,7 +83,7 @@ describe('filter manager utilities', () => {
const filter = {
meta: { index: 'logstash-*' },
query: { query_string: { query: 'foo:bar' } },
- } as Filter;
+ } as esFilters.Filter;
try {
mapGeoBoundingBox(filter);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_bounding_box.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.ts
similarity index 80%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_bounding_box.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.ts
index 1f9b8cd842509..091e9a3f34000 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_bounding_box.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.ts
@@ -16,16 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-import {
- GeoBoundingBoxFilter,
- Filter,
- FILTERS,
- isGeoBoundingBoxFilter,
- FilterValueFormatter,
-} from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
const getFormattedValueFn = (params: any) => {
- return (formatter?: FilterValueFormatter) => {
+ return (formatter?: esFilters.FilterValueFormatter) => {
const corners = formatter
? {
topLeft: formatter.convert(params.top_left),
@@ -40,20 +34,20 @@ const getFormattedValueFn = (params: any) => {
};
};
-const getParams = (filter: GeoBoundingBoxFilter) => {
+const getParams = (filter: esFilters.GeoBoundingBoxFilter) => {
const key = Object.keys(filter.geo_bounding_box).filter(k => k !== 'ignore_unmapped')[0];
const params = filter.geo_bounding_box[key];
return {
key,
params,
- type: FILTERS.GEO_BOUNDING_BOX,
+ type: esFilters.FILTERS.GEO_BOUNDING_BOX,
value: getFormattedValueFn(params),
};
};
-export const mapGeoBoundingBox = (filter: Filter) => {
- if (!isGeoBoundingBoxFilter(filter)) {
+export const mapGeoBoundingBox = (filter: esFilters.Filter) => {
+ if (!esFilters.isGeoBoundingBoxFilter(filter)) {
throw filter;
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_polygon.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.test.ts
similarity index 77%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_polygon.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.test.ts
index ee4f9b295d682..3afa3891a24bb 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_polygon.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.test.ts
@@ -16,23 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { mapGeoPolygon } from './map_geo_polygon';
-import { GeoPolygonFilter, Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
- describe('mapGeoPolygon()', () => {
- test('should return the key and value for matching filters with bounds', async () => {
- const filter = {
- meta: {
- index: 'logstash-*',
- },
- geo_polygon: {
- point: {
- points: [{ lat: 5, lon: 10 }, { lat: 15, lon: 20 }],
- },
+ let filter: esFilters.GeoPolygonFilter;
+
+ beforeEach(() => {
+ filter = {
+ meta: {
+ index: 'logstash-*',
+ },
+ geo_polygon: {
+ point: {
+ points: [{ lat: 5, lon: 10 }, { lat: 15, lon: 20 }],
},
- } as GeoPolygonFilter;
+ },
+ } as esFilters.GeoPolygonFilter;
+ });
+ describe('mapGeoPolygon()', () => {
+ test('should return the key and value for matching filters with bounds', async () => {
const result = mapGeoPolygon(filter);
expect(result).toHaveProperty('key', 'point');
@@ -48,17 +53,6 @@ describe('filter manager utilities', () => {
});
test('should return the key and value even when using ignore_unmapped', async () => {
- const filter = {
- meta: {
- index: 'logstash-*',
- },
- geo_polygon: {
- ignore_unmapped: true,
- point: {
- points: [{ lat: 5, lon: 10 }, { lat: 15, lon: 20 }],
- },
- },
- } as GeoPolygonFilter;
const result = mapGeoPolygon(filter);
expect(result).toHaveProperty('key', 'point');
@@ -74,15 +68,15 @@ describe('filter manager utilities', () => {
});
test('should return undefined for none matching', async done => {
- const filter = {
+ const wrongFilter = {
meta: { index: 'logstash-*' },
query: { query_string: { query: 'foo:bar' } },
- } as Filter;
+ } as esFilters.Filter;
try {
- mapGeoPolygon(filter);
+ mapGeoPolygon(wrongFilter);
} catch (e) {
- expect(e).toBe(filter);
+ expect(e).toBe(wrongFilter);
done();
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_polygon.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.ts
similarity index 79%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_polygon.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.ts
index 03ce4130d0c97..a7881b4a145a1 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_geo_polygon.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.ts
@@ -16,38 +16,33 @@
* specific language governing permissions and limitations
* under the License.
*/
-import {
- GeoPolygonFilter,
- Filter,
- FILTERS,
- isGeoPolygonFilter,
- FilterValueFormatter,
-} from '@kbn/es-query';
+
+import { esFilters } from '../../../../../common/es_query';
const POINTS_SEPARATOR = ', ';
const getFormattedValueFn = (points: string[]) => {
- return (formatter?: FilterValueFormatter) => {
+ return (formatter?: esFilters.FilterValueFormatter) => {
return points
.map((point: string) => (formatter ? formatter.convert(point) : JSON.stringify(point)))
.join(POINTS_SEPARATOR);
};
};
-function getParams(filter: GeoPolygonFilter) {
+function getParams(filter: esFilters.GeoPolygonFilter) {
const key = Object.keys(filter.geo_polygon).filter(k => k !== 'ignore_unmapped')[0];
const params = filter.geo_polygon[key];
return {
key,
params,
- type: FILTERS.GEO_POLYGON,
+ type: esFilters.FILTERS.GEO_POLYGON,
value: getFormattedValueFn(params.points || []),
};
}
-export function mapGeoPolygon(filter: Filter) {
- if (!isGeoPolygonFilter(filter)) {
+export function mapGeoPolygon(filter: esFilters.Filter) {
+ if (!esFilters.isGeoPolygonFilter(filter)) {
throw filter;
}
return getParams(filter);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_match_all.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.test.ts
similarity index 94%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_match_all.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.test.ts
index 2f0641598a2ce..4fc6d0b492414 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_match_all.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.test.ts
@@ -16,12 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { MatchAllFilter } from '@kbn/es-query';
+
import { mapMatchAll } from './map_match_all';
+import { esFilters } from '../../../../../common/es_query';
describe('filter_manager/lib', () => {
describe('mapMatchAll()', () => {
- let filter: MatchAllFilter;
+ let filter: esFilters.MatchAllFilter;
beforeEach(() => {
filter = {
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_match_all.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.ts
similarity index 81%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_match_all.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.ts
index a1387e6dbe457..4e93b1d41e9a8 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_match_all.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.ts
@@ -16,12 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter, FILTERS, isMatchAllFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
-export const mapMatchAll = (filter: Filter) => {
- if (isMatchAllFilter(filter)) {
+export const mapMatchAll = (filter: esFilters.Filter) => {
+ if (esFilters.isMatchAllFilter(filter)) {
return {
- type: FILTERS.MATCH_ALL,
+ type: esFilters.FILTERS.MATCH_ALL,
key: filter.meta.field,
value: filter.meta.formattedValue || 'all',
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_missing.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.test.ts
similarity index 86%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_missing.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.test.ts
index ca23f25826906..1847eb37ca42f 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_missing.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.test.ts
@@ -16,15 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { MissingFilter, buildEmptyFilter, ExistsFilter } from '@kbn/es-query';
+
import { mapMissing } from './map_missing';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapMissing()', () => {
test('should return the key and value for matching filters', async () => {
- const filter: MissingFilter = {
+ const filter: esFilters.MissingFilter = {
missing: { field: '_type' },
- ...buildEmptyFilter(true),
+ ...esFilters.buildEmptyFilter(true),
};
const result = mapMissing(filter);
@@ -33,7 +34,7 @@ describe('filter manager utilities', () => {
});
test('should return undefined for none matching', async done => {
- const filter = buildEmptyFilter(true) as ExistsFilter;
+ const filter = esFilters.buildEmptyFilter(true);
try {
mapMissing(filter);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_missing.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.ts
similarity index 78%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_missing.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.ts
index 861a84ed61646..51dee89ad884b 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_missing.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.ts
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter, FILTERS, isMissingFilter } from '@kbn/es-query';
-export const mapMissing = (filter: Filter) => {
- if (isMissingFilter(filter)) {
+import { esFilters } from '../../../../../common/es_query';
+
+export const mapMissing = (filter: esFilters.Filter) => {
+ if (esFilters.isMissingFilter(filter)) {
return {
- type: FILTERS.MISSING,
- value: FILTERS.MISSING,
+ type: esFilters.FILTERS.MISSING,
+ value: esFilters.FILTERS.MISSING,
key: filter.missing.field,
};
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_phrase.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts
similarity index 93%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_phrase.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts
index c95a2529add14..05372d37264b0 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_phrase.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
import { mapPhrase } from './map_phrase';
-import { PhraseFilter, Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapPhrase()', () => {
@@ -25,11 +25,13 @@ describe('filter manager utilities', () => {
const filter = {
meta: { index: 'logstash-*' },
query: { match: { _type: { query: 'apache', type: 'phrase' } } },
- } as PhraseFilter;
+ } as esFilters.PhraseFilter;
+
const result = mapPhrase(filter);
expect(result).toHaveProperty('value');
expect(result).toHaveProperty('key', '_type');
+
if (result.value) {
const displayName = result.value();
expect(displayName).toBe('apache');
@@ -40,7 +42,7 @@ describe('filter manager utilities', () => {
const filter = {
meta: { index: 'logstash-*' },
query: { query_string: { query: 'foo:bar' } },
- } as Filter;
+ } as esFilters.Filter;
try {
mapPhrase(filter);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_phrase.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts
similarity index 65%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_phrase.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts
index efa348c9ad320..b6e9c2007db97 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_phrase.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts
@@ -18,45 +18,36 @@
*/
import { get } from 'lodash';
-import {
- PhraseFilter,
- Filter,
- FILTERS,
- isPhraseFilter,
- isScriptedPhraseFilter,
- getPhraseFilterField,
- getPhraseFilterValue,
- FilterValueFormatter,
-} from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
-const getScriptedPhraseValue = (filter: PhraseFilter) =>
+const getScriptedPhraseValue = (filter: esFilters.PhraseFilter) =>
get(filter, ['script', 'script', 'params', 'value']);
const getFormattedValueFn = (value: any) => {
- return (formatter?: FilterValueFormatter) => {
+ return (formatter?: esFilters.FilterValueFormatter) => {
return formatter ? formatter.convert(value) : value;
};
};
-const getParams = (filter: PhraseFilter) => {
+const getParams = (filter: esFilters.PhraseFilter) => {
const scriptedPhraseValue = getScriptedPhraseValue(filter);
const isScriptedFilter = Boolean(scriptedPhraseValue);
- const key = isScriptedFilter ? filter.meta.field || '' : getPhraseFilterField(filter);
- const query = scriptedPhraseValue || getPhraseFilterValue(filter);
+ const key = isScriptedFilter ? filter.meta.field || '' : esFilters.getPhraseFilterField(filter);
+ const query = scriptedPhraseValue || esFilters.getPhraseFilterValue(filter);
const params = { query };
return {
key,
params,
- type: FILTERS.PHRASE,
+ type: esFilters.FILTERS.PHRASE,
value: getFormattedValueFn(query),
};
};
-export const isMapPhraseFilter = (filter: any): filter is PhraseFilter =>
- isPhraseFilter(filter) || isScriptedPhraseFilter(filter);
+export const isMapPhraseFilter = (filter: any): filter is esFilters.PhraseFilter =>
+ esFilters.isPhraseFilter(filter) || esFilters.isScriptedPhraseFilter(filter);
-export const mapPhrase = (filter: Filter) => {
+export const mapPhrase = (filter: esFilters.Filter) => {
if (!isMapPhraseFilter(filter)) {
throw filter;
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_phrases.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts
similarity index 85%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_phrases.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts
index c17ff11d49fd4..7240d87d02b5a 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_phrases.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts
@@ -17,10 +17,10 @@
* under the License.
*/
-import { Filter, isPhrasesFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
-export const mapPhrases = (filter: Filter) => {
- if (!isPhrasesFilter(filter)) {
+export const mapPhrases = (filter: esFilters.Filter) => {
+ if (!esFilters.isPhrasesFilter(filter)) {
throw filter;
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_query_string.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.test.ts
similarity index 81%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_query_string.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.test.ts
index 4b1a5d39c405d..c60e7d3454fe0 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_query_string.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.test.ts
@@ -17,27 +17,28 @@
* under the License.
*/
-import { QueryStringFilter, buildQueryFilter, buildEmptyFilter } from '@kbn/es-query';
import { mapQueryString } from './map_query_string';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapQueryString()', () => {
test('should return the key and value for matching filters', async () => {
- const filter: QueryStringFilter = buildQueryFilter(
+ const filter = esFilters.buildQueryFilter(
{ query_string: { query: 'foo:bar' } },
- 'index'
+ 'index',
+ ''
);
- const result = mapQueryString(filter);
+ const result = mapQueryString(filter as esFilters.Filter);
expect(result).toHaveProperty('key', 'query');
expect(result).toHaveProperty('value', 'foo:bar');
});
test('should return undefined for none matching', async done => {
- const filter = buildEmptyFilter(true) as QueryStringFilter;
+ const filter = esFilters.buildEmptyFilter(true);
try {
- mapQueryString(filter);
+ mapQueryString(filter as esFilters.Filter);
} catch (e) {
expect(e).toBe(filter);
done();
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_query_string.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.ts
similarity index 81%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_query_string.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.ts
index 94da8074edd04..20c3555639a3e 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_query_string.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.ts
@@ -16,12 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter, FILTERS, isQueryStringFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
-export const mapQueryString = (filter: Filter) => {
- if (isQueryStringFilter(filter)) {
+export const mapQueryString = (filter: esFilters.Filter) => {
+ if (esFilters.isQueryStringFilter(filter)) {
return {
- type: FILTERS.QUERY_STRING,
+ type: esFilters.FILTERS.QUERY_STRING,
key: 'query',
value: filter.query.query_string.query,
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_range.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts
similarity index 71%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_range.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts
index 12d2919e2d47b..c0d5773d6f2c1 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_range.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts
@@ -18,30 +18,15 @@
*/
import { mapRange } from './map_range';
-import { RangeFilter, Filter, FilterMeta } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapRange()', () => {
test('should return the key and value for matching filters with gt/lt', async () => {
const filter = {
- meta: { index: 'logstash-*' } as FilterMeta,
+ meta: { index: 'logstash-*' } as esFilters.FilterMeta,
range: { bytes: { lt: 2048, gt: 1024 } },
- } as RangeFilter;
- const result = mapRange(filter);
-
- expect(result).toHaveProperty('key', 'bytes');
- expect(result).toHaveProperty('value');
- if (result.value) {
- const displayName = result.value();
- expect(displayName).toBe('1024 to 2048');
- }
- });
-
- test('should return the key and value for matching filters with gte/lte', async () => {
- const filter = {
- meta: { index: 'logstash-*' } as FilterMeta,
- range: { bytes: { lte: 2048, gte: 1024 } },
- } as RangeFilter;
+ } as esFilters.RangeFilter;
const result = mapRange(filter);
expect(result).toHaveProperty('key', 'bytes');
@@ -56,7 +41,7 @@ describe('filter manager utilities', () => {
const filter = {
meta: { index: 'logstash-*' },
query: { query_string: { query: 'foo:bar' } },
- } as Filter;
+ } as esFilters.Filter;
try {
mapRange(filter);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_range.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts
similarity index 69%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_range.ts
rename to src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts
index 76f9d3621e171..51fb970f5f03e 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/map_range.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts
@@ -17,18 +17,11 @@
* under the License.
*/
-import {
- Filter,
- RangeFilter,
- FILTERS,
- isRangeFilter,
- isScriptedRangeFilter,
- FilterValueFormatter,
-} from '@kbn/es-query';
import { get, has } from 'lodash';
+import { esFilters } from '../../../../../common/es_query';
const getFormattedValueFn = (left: any, right: any) => {
- return (formatter?: FilterValueFormatter) => {
+ return (formatter?: esFilters.FilterValueFormatter) => {
let displayValue = `${left} to ${right}`;
if (formatter) {
const convert = formatter.getConverterFor('text');
@@ -38,11 +31,12 @@ const getFormattedValueFn = (left: any, right: any) => {
};
};
-const getFirstRangeKey = (filter: RangeFilter) => filter.range && Object.keys(filter.range)[0];
-const getRangeByKey = (filter: RangeFilter, key: string) => get(filter, ['range', key]);
+const getFirstRangeKey = (filter: esFilters.RangeFilter) =>
+ filter.range && Object.keys(filter.range)[0];
+const getRangeByKey = (filter: esFilters.RangeFilter, key: string) => get(filter, ['range', key]);
-function getParams(filter: RangeFilter) {
- const isScriptedRange = isScriptedRangeFilter(filter);
+function getParams(filter: esFilters.RangeFilter) {
+ const isScriptedRange = esFilters.isScriptedRangeFilter(filter);
const key: string = (isScriptedRange ? filter.meta.field : getFirstRangeKey(filter)) || '';
const params: any = isScriptedRange
? get(filter, 'script.script.params')
@@ -56,13 +50,13 @@ function getParams(filter: RangeFilter) {
const value = getFormattedValueFn(left, right);
- return { type: FILTERS.RANGE, key, value, params };
+ return { type: esFilters.FILTERS.RANGE, key, value, params };
}
-export const isMapRangeFilter = (filter: any): filter is RangeFilter =>
- isRangeFilter(filter) || isScriptedRangeFilter(filter);
+export const isMapRangeFilter = (filter: any): filter is esFilters.RangeFilter =>
+ esFilters.isRangeFilter(filter) || esFilters.isScriptedRangeFilter(filter);
-export const mapRange = (filter: Filter) => {
+export const mapRange = (filter: esFilters.Filter) => {
if (!isMapRangeFilter(filter)) {
throw filter;
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/only_disabled.test.ts b/src/plugins/data/public/query/filter_manager/lib/only_disabled.test.ts
similarity index 77%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/only_disabled.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/only_disabled.test.ts
index 3fedcf97a625a..b9731797c9ee3 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/only_disabled.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/only_disabled.test.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { onlyDisabledFiltersChanged } from './only_disabled';
+import { esFilters } from '../../../../../data/public';
describe('filter manager utilities', () => {
describe('onlyDisabledFiltersChanged()', () => {
@@ -27,20 +27,20 @@ describe('filter manager utilities', () => {
{ meta: { disabled: true } },
{ meta: { disabled: true } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: true } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: true } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(true);
});
test('should return false if there are no old filters', () => {
- const newFilters = [{ meta: { disabled: false } }] as Filter[];
+ const newFilters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, undefined)).toBe(false);
});
test('should return false if there are no new filters', () => {
- const filters = [{ meta: { disabled: false } }] as Filter[];
+ const filters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(undefined, filters)).toBe(false);
});
@@ -50,8 +50,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: false } },
{ meta: { disabled: false } },
{ meta: { disabled: false } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: false } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -61,8 +61,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: true } },
{ meta: { disabled: true } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: false } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -72,8 +72,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: false } },
{ meta: { disabled: false } },
{ meta: { disabled: false } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: true } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: true } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -83,8 +83,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: true } },
{ meta: { disabled: true } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(true);
});
@@ -94,8 +94,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: false } },
{ meta: { disabled: false } },
{ meta: { disabled: false } },
- ] as Filter[];
- const newFilters = [] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -104,11 +104,11 @@ describe('filter manager utilities', () => {
const filters = [
{ meta: { disabled: true, negate: false } },
{ meta: { disabled: true, negate: false } },
- ] as Filter[];
+ ] as esFilters.Filter[];
const newFilters = [
{ meta: { disabled: true, negate: true } },
{ meta: { disabled: true, negate: true } },
- ] as Filter[];
+ ] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(true);
});
@@ -118,8 +118,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: false } },
{ meta: { disabled: false } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: false } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -129,15 +129,15 @@ describe('filter manager utilities', () => {
{ meta: { disabled: true } },
{ meta: { disabled: false } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
test('should not throw with null filters', () => {
- const filters = [null, { meta: { disabled: true } }] as Filter[];
- const newFilters = [] as Filter[];
+ const filters = [null, { meta: { disabled: true } }] as esFilters.Filter[];
+ const newFilters = [] as esFilters.Filter[];
expect(() => {
onlyDisabledFiltersChanged(newFilters, filters);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/only_disabled.ts b/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts
similarity index 82%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/only_disabled.ts
rename to src/plugins/data/public/query/filter_manager/lib/only_disabled.ts
index 9c0b5f43acb3e..0fb6894a297a1 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/only_disabled.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts
@@ -17,17 +17,20 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { filter, isEqual } from 'lodash';
+import { esFilters } from '../../../../../../plugins/data/public';
-const isEnabled = (f: Filter) => f && f.meta && !f.meta.disabled;
+const isEnabled = (f: esFilters.Filter) => f && f.meta && !f.meta.disabled;
/**
* Checks to see if only disabled filters have been changed
*
* @returns {bool} Only disabled filters
*/
-export const onlyDisabledFiltersChanged = (newFilters?: Filter[], oldFilters?: Filter[]) => {
+export const onlyDisabledFiltersChanged = (
+ newFilters?: esFilters.Filter[],
+ oldFilters?: esFilters.Filter[]
+) => {
// If it's the same - compare only enabled filters
const newEnabledFilters = filter(newFilters || [], isEnabled);
const oldEnabledFilters = filter(oldFilters || [], isEnabled);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/uniq_filters.test.ts b/src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts
similarity index 54%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/uniq_filters.test.ts
rename to src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts
index 86f059913cd96..08eeabc1497e3 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/uniq_filters.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts
@@ -16,15 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter, buildQueryFilter, FilterStateStore } from '@kbn/es-query';
+
import { uniqFilters } from './uniq_filters';
+import { esFilters } from '../../../../../data/public';
describe('filter manager utilities', () => {
describe('niqFilter', () => {
test('should filter out dups', () => {
- const before: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ const before: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
];
const results = uniqFilters(before);
@@ -32,9 +41,17 @@ describe('filter manager utilities', () => {
});
test('should filter out duplicates, ignoring meta attributes', () => {
- const before: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index1'),
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index2'),
+ const before: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index1',
+ ''
+ ),
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index2',
+ ''
+ ),
];
const results = uniqFilters(before);
@@ -42,14 +59,22 @@ describe('filter manager utilities', () => {
});
test('should filter out duplicates, ignoring $state attributes', () => {
- const before: Filter[] = [
+ const before: esFilters.Filter[] = [
{
- $state: { store: FilterStateStore.APP_STATE },
- ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
+ ...esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
},
{
- $state: { store: FilterStateStore.GLOBAL_STATE },
- ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ $state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
+ ...esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
},
];
const results = uniqFilters(before);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/uniq_filters.ts b/src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts
similarity index 84%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/lib/uniq_filters.ts
rename to src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts
index 12e793253371e..e96c52e6db3de 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/lib/uniq_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts
@@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { each, union } from 'lodash';
import { dedupFilters } from './dedup_filters';
+import { esFilters } from '../../../../../data/public';
/**
* Remove duplicate filters from an array of filters
@@ -28,10 +28,10 @@ import { dedupFilters } from './dedup_filters';
* @returns {object} The original filters array with duplicates removed
*/
-export const uniqFilters = (filters: Filter[], comparatorOptions: any = {}) => {
- let results: Filter[] = [];
+export const uniqFilters = (filters: esFilters.Filter[], comparatorOptions: any = {}) => {
+ let results: esFilters.Filter[] = [];
- each(filters, (filter: Filter) => {
+ each(filters, (filter: esFilters.Filter) => {
results = union(results, dedupFilters(results, [filter]), comparatorOptions);
});
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_filters_array.ts b/src/plugins/data/public/query/filter_manager/test_helpers/get_filters_array.ts
similarity index 91%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_filters_array.ts
rename to src/plugins/data/public/query/filter_manager/test_helpers/get_filters_array.ts
index 27f627b477c35..aa047647c5751 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_filters_array.ts
+++ b/src/plugins/data/public/query/filter_manager/test_helpers/get_filters_array.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
-export function getFiltersArray(): Filter[] {
+export function getFiltersArray(): esFilters.Filter[] {
return [
{
query: { match: { extension: { query: 'jpg', type: 'phrase' } } },
diff --git a/packages/kbn-es-query/src/filters/exists.js b/src/plugins/data/public/query/filter_manager/test_helpers/get_stub_filter.ts
similarity index 66%
rename from packages/kbn-es-query/src/filters/exists.js
rename to src/plugins/data/public/query/filter_manager/test_helpers/get_stub_filter.ts
index 0c82279fb4417..adc72c961b08b 100644
--- a/packages/kbn-es-query/src/filters/exists.js
+++ b/src/plugins/data/public/query/filter_manager/test_helpers/get_stub_filter.ts
@@ -17,14 +17,29 @@
* under the License.
*/
-// Creates a filter where the given field exists
-export function buildExistsFilter(field, indexPattern) {
+import { esFilters } from '../../../../../../plugins/data/public';
+
+export function getFilter(
+ store: esFilters.FilterStateStore,
+ disabled: boolean,
+ negated: boolean,
+ queryKey: string,
+ queryValue: any
+): esFilters.Filter {
return {
+ $state: {
+ store,
+ },
meta: {
- index: indexPattern.id
+ index: 'logstash-*',
+ disabled,
+ negate: negated,
+ alias: null,
+ },
+ query: {
+ match: {
+ [queryKey]: queryValue,
+ },
},
- exists: {
- field: field.name
- }
};
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/partitioned_filters.ts b/src/plugins/data/public/query/filter_manager/types.ts
similarity index 86%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/partitioned_filters.ts
rename to src/plugins/data/public/query/filter_manager/types.ts
index e74b48b722cc4..0b3dbca2d6e0a 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/partitioned_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/types.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../plugins/data/public';
export interface PartitionedFilters {
- globalFilters: Filter[];
- appFilters: Filter[];
+ globalFilters: esFilters.Filter[];
+ appFilters: esFilters.Filter[];
}
diff --git a/src/plugins/data/public/query/index.tsx b/src/plugins/data/public/query/index.tsx
new file mode 100644
index 0000000000000..42647b9d98201
--- /dev/null
+++ b/src/plugins/data/public/query/index.tsx
@@ -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 './query_service';
+export * from './filter_manager';
diff --git a/src/legacy/core_plugins/data/public/filter/filter_service.mock.ts b/src/plugins/data/public/query/mocks.ts
similarity index 80%
rename from src/legacy/core_plugins/data/public/filter/filter_service.mock.ts
rename to src/plugins/data/public/query/mocks.ts
index 94268ef69c49a..e5030c5765316 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_service.mock.ts
+++ b/src/plugins/data/public/query/mocks.ts
@@ -17,12 +17,12 @@
* under the License.
*/
-import { FilterService, FilterStart, FilterSetup } from '.';
+import { QueryService, QueryStart, QuerySetup } from '.';
-type FilterServiceClientContract = PublicMethodsOf;
+type QueryServiceClientContract = PublicMethodsOf;
const createSetupContractMock = () => {
- const setupContract: jest.Mocked = {
+ const setupContract: jest.Mocked = {
filterManager: jest.fn() as any,
};
@@ -30,7 +30,7 @@ const createSetupContractMock = () => {
};
const createStartContractMock = () => {
- const startContract: jest.Mocked = {
+ const startContract: jest.Mocked = {
filterManager: jest.fn() as any,
};
@@ -38,7 +38,7 @@ const createStartContractMock = () => {
};
const createMock = () => {
- const mocked: jest.Mocked = {
+ const mocked: jest.Mocked = {
setup: jest.fn(),
start: jest.fn(),
stop: jest.fn(),
@@ -49,7 +49,7 @@ const createMock = () => {
return mocked;
};
-export const filterServiceMock = {
+export const queryServiceMock = {
create: createMock,
createSetupContract: createSetupContractMock,
createStartContract: createStartContractMock,
diff --git a/src/legacy/core_plugins/data/public/filter/filter_service.ts b/src/plugins/data/public/query/query_service.ts
similarity index 82%
rename from src/legacy/core_plugins/data/public/filter/filter_service.ts
rename to src/plugins/data/public/query/query_service.ts
index 0c46259ef0e00..d34909a5e03b7 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_service.ts
+++ b/src/plugins/data/public/query/query_service.ts
@@ -21,18 +21,18 @@ import { UiSettingsClientContract } from 'src/core/public';
import { FilterManager } from './filter_manager';
/**
- * Filter Service
+ * Query Service
* @internal
*/
-export interface FilterServiceDependencies {
+export interface QueryServiceDependencies {
uiSettings: UiSettingsClientContract;
}
-export class FilterService {
+export class QueryService {
filterManager!: FilterManager;
- public setup({ uiSettings }: FilterServiceDependencies) {
+ public setup({ uiSettings }: QueryServiceDependencies) {
this.filterManager = new FilterManager(uiSettings);
return {
@@ -52,5 +52,5 @@ export class FilterService {
}
/** @public */
-export type FilterSetup = ReturnType;
-export type FilterStart = ReturnType;
+export type QuerySetup = ReturnType;
+export type QueryStart = ReturnType;
diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts
index 5f94734fef083..9939815c1efd1 100644
--- a/src/plugins/data/public/types.ts
+++ b/src/plugins/data/public/types.ts
@@ -22,15 +22,18 @@ export * from './autocomplete_provider/types';
import { AutocompletePublicPluginSetup, AutocompletePublicPluginStart } from '.';
import { ISearchSetup, ISearchStart } from './search';
import { IGetSuggestions } from './suggestions_provider/types';
+import { QuerySetup, QueryStart } from './query';
export interface DataPublicPluginSetup {
autocomplete: AutocompletePublicPluginSetup;
search: ISearchSetup;
+ query: QuerySetup;
}
export interface DataPublicPluginStart {
autocomplete: AutocompletePublicPluginStart;
getSuggestions: IGetSuggestions;
search: ISearchStart;
+ query: QueryStart;
}
export { IGetSuggestions } from './suggestions_provider/types';
diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts
index df933167cee25..f0b6117b928cd 100644
--- a/src/plugins/data/server/index.ts
+++ b/src/plugins/data/server/index.ts
@@ -25,6 +25,11 @@ export function plugin(initializerContext: PluginInitializerContext) {
}
export { DataServerPlugin as Plugin };
+export {
+ IndexPatternsFetcher,
+ FieldDescriptor,
+ shouldReadFieldFromDocValues,
+} from './index_patterns';
export * from './search';
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/index.ts b/src/plugins/data/server/index_patterns/fetcher/index.ts
similarity index 89%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/index.ts
rename to src/plugins/data/server/index_patterns/fetcher/index.ts
index 03ba836462c60..19306696885db 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/index.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/index.ts
@@ -17,6 +17,5 @@
* under the License.
*/
-export * from './types';
-export * from './actions';
-export * from './embeddable';
+export * from './index_patterns_fetcher';
+export { shouldReadFieldFromDocValues } from './lib';
diff --git a/src/legacy/server/index_patterns/service/index_patterns_service.ts b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts
similarity index 95%
rename from src/legacy/server/index_patterns/service/index_patterns_service.ts
rename to src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts
index 6c32d99ad83f9..5f1493a49ab7d 100644
--- a/src/legacy/server/index_patterns/service/index_patterns_service.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts
@@ -28,11 +28,15 @@ export interface FieldDescriptor {
searchable: boolean;
type: string;
esTypes: string[];
- parent?: string;
- subType?: string;
+ subType?: FieldSubType;
}
-export class IndexPatternsService {
+interface FieldSubType {
+ multi?: { parent: string };
+ nested?: { path: string };
+}
+
+export class IndexPatternsFetcher {
private _callDataCluster: APICaller;
constructor(callDataCluster: APICaller) {
diff --git a/src/legacy/server/index_patterns/service/lib/errors.ts b/src/plugins/data/server/index_patterns/fetcher/lib/errors.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/errors.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/errors.ts
diff --git a/src/legacy/server/index_patterns/service/lib/es_api.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.test.js
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/es_api.test.js
rename to src/plugins/data/server/index_patterns/fetcher/lib/es_api.test.js
diff --git a/src/legacy/server/index_patterns/service/lib/es_api.ts b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts
similarity index 99%
rename from src/legacy/server/index_patterns/service/lib/es_api.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts
index 63c1824784dbd..92b64fafddd66 100644
--- a/src/legacy/server/index_patterns/service/lib/es_api.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts
@@ -18,7 +18,6 @@
*/
import { APICaller } from 'src/core/server';
-// @ts-ignore
import { convertEsError } from './errors';
import { FieldCapsResponse } from './field_capabilities';
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/__fixtures__/es_field_caps_response.json b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json
similarity index 90%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/__fixtures__/es_field_caps_response.json
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json
index 97f8c187e1680..0d70f49b5e6b5 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/__fixtures__/es_field_caps_response.json
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json
@@ -221,6 +221,27 @@
"searchable": true,
"aggregatable": true
}
+ },
+ "nested_object_parent": {
+ "nested": {
+ "type": "nested",
+ "searchable": false,
+ "aggregatable": false
+ }
+ },
+ "nested_object_parent.child": {
+ "text": {
+ "type": "text",
+ "searchable": true,
+ "aggregatable": false
+ }
+ },
+ "nested_object_parent.child.keyword": {
+ "keyword": {
+ "type": "keyword",
+ "searchable": true,
+ "aggregatable": true
+ }
}
}
}
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.test.js
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts
similarity index 97%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts
index 05e8d591f13a9..c275fb714088e 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts
@@ -23,7 +23,7 @@ import { APICaller } from 'src/core/server';
import { callFieldCapsApi } from '../es_api';
import { FieldCapsResponse, readFieldCapsResponse } from './field_caps_response';
import { mergeOverrides } from './overrides';
-import { FieldDescriptor } from '../../index_patterns_service';
+import { FieldDescriptor } from '../../index_patterns_fetcher';
export function concatIfUniq(arr: T[], value: T) {
return arr.includes(value) ? arr : arr.concat(value);
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js
similarity index 76%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.test.js
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js
index dfdafeea3cd78..cf4af615b9577 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.test.js
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js
@@ -24,7 +24,7 @@ import sinon from 'sinon';
import * as shouldReadFieldFromDocValuesNS from './should_read_field_from_doc_values';
import { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values';
-import { getKbnFieldType } from '../../../../../../plugins/data/common';
+import { getKbnFieldType } from '../../../../../../data/common';
import { readFieldCapsResponse } from './field_caps_response';
import esResponse from './__fixtures__/es_field_caps_response.json';
@@ -37,10 +37,10 @@ describe('index_patterns/field_capabilities/field_caps_response', () => {
describe('conflicts', () => {
it('returns a field for each in response, no filtering', () => {
const fields = readFieldCapsResponse(esResponse);
- expect(fields).toHaveLength(22);
+ expect(fields).toHaveLength(24);
});
- it('includes only name, type, esTypes, searchable, aggregatable, readFromDocValues, and maybe conflictDescriptions, parent, ' +
+ it('includes only name, type, esTypes, searchable, aggregatable, readFromDocValues, and maybe conflictDescriptions, ' +
'and subType of each field', () => {
const responseClone = cloneDeep(esResponse);
// try to trick it into including an extra field
@@ -48,7 +48,7 @@ describe('index_patterns/field_capabilities/field_caps_response', () => {
const fields = readFieldCapsResponse(responseClone);
fields.forEach(field => {
- const fieldWithoutOptionalKeys = omit(field, 'conflictDescriptions', 'parent', 'subType');
+ const fieldWithoutOptionalKeys = omit(field, 'conflictDescriptions', 'subType');
expect(Object.keys(fieldWithoutOptionalKeys)).toEqual([
'name',
@@ -65,8 +65,8 @@ describe('index_patterns/field_capabilities/field_caps_response', () => {
sandbox.spy(shouldReadFieldFromDocValuesNS, 'shouldReadFieldFromDocValues');
const fields = readFieldCapsResponse(esResponse);
const conflictCount = fields.filter(f => f.type === 'conflict').length;
- // +1 is for the object field which gets filtered out of the final return value from readFieldCapsResponse
- sinon.assert.callCount(shouldReadFieldFromDocValues, fields.length - conflictCount + 1);
+ // +2 is for the object and nested fields which get filtered out of the final return value from readFieldCapsResponse
+ sinon.assert.callCount(shouldReadFieldFromDocValues, fields.length - conflictCount + 2);
});
it('converts es types to kibana types', () => {
@@ -132,20 +132,41 @@ describe('index_patterns/field_capabilities/field_caps_response', () => {
expect(mixSearchableOther.searchable).toBe(true);
});
- it('returns multi fields with parent and subType keys describing the relationship', () => {
+ it('returns multi fields with a subType key describing the relationship', () => {
const fields = readFieldCapsResponse(esResponse);
const child = fields.find(f => f.name === 'multi_parent.child');
- expect(child).toHaveProperty('parent', 'multi_parent');
- expect(child).toHaveProperty('subType', 'multi');
+ expect(child).toHaveProperty('subType', { multi: { parent: 'multi_parent' } });
});
- it('should not confuse object children for multi field children', () => {
+ it('returns nested sub-fields with a subType key describing the relationship', () => {
+ const fields = readFieldCapsResponse(esResponse);
+ const child = fields.find(f => f.name === 'nested_object_parent.child');
+ expect(child).toHaveProperty('subType', { nested: { path: 'nested_object_parent' } });
+ });
+
+ it('handles fields that are both nested and multi', () => {
+ const fields = readFieldCapsResponse(esResponse);
+ const child = fields.find(f => f.name === 'nested_object_parent.child.keyword');
+ expect(child).toHaveProperty(
+ 'subType',
+ {
+ nested: { path: 'nested_object_parent' },
+ multi: { parent: 'nested_object_parent.child' }
+ });
+ });
+
+ it('does not include the field actually mapped as nested itself', () => {
+ const fields = readFieldCapsResponse(esResponse);
+ const child = fields.find(f => f.name === 'nested_object_parent');
+ expect(child).toBeUndefined();
+ });
+
+ it('should not confuse object children for multi or nested field children', () => {
// We detect multi fields by finding fields that have a dot in their name and then looking
- // to see if their parents are *not* object or nested fields. In the future we may want to
- // add parent and subType info for object and nested fields but for now we don't need it.
+ // to see if their parents are *not* object fields. In the future we may want to
+ // add subType info for object fields but for now we don't need it.
const fields = readFieldCapsResponse(esResponse);
const child = fields.find(f => f.name === 'object_parent.child');
- expect(child).not.toHaveProperty('parent');
expect(child).not.toHaveProperty('subType');
});
});
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts
similarity index 79%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts
index cb67d7c79cfac..06eb30db0b24b 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts
@@ -18,9 +18,9 @@
*/
import { uniq } from 'lodash';
-import { FieldDescriptor } from '../..';
+import { castEsToKbnFieldTypeName } from '../../../../../common';
import { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values';
-import { castEsToKbnFieldTypeName } from '../../../../../../plugins/data/common';
+import { FieldDescriptor } from '../../../fetcher';
interface FieldCapObject {
type: string;
@@ -151,18 +151,38 @@ export function readFieldCapsResponse(fieldCapsResponse: FieldCapsResponse): Fie
return field.name.includes('.');
});
- // Discern which sub fields are multi fields. If the parent field is not an object or nested field
- // the child must be a multi field.
+ // Determine the type of each sub field.
subFields.forEach(field => {
- const parentFieldName = field.name
+ const parentFieldNames = field.name
.split('.')
.slice(0, -1)
- .join('.');
- const parentFieldCaps = kibanaFormattedCaps.find(caps => caps.name === parentFieldName);
+ .map((_, index, parentFieldNameParts) => {
+ return parentFieldNameParts.slice(0, index + 1).join('.');
+ });
+ const parentFieldCaps = parentFieldNames.map(parentFieldName => {
+ return kibanaFormattedCaps.find(caps => caps.name === parentFieldName);
+ });
+ const parentFieldCapsAscending = parentFieldCaps.reverse();
+
+ if (parentFieldCaps && parentFieldCaps.length > 0) {
+ let subType = {};
+ // If the parent field is not an object or nested field the child must be a multi field.
+ const firstParent = parentFieldCapsAscending[0];
+ if (firstParent && !['object', 'nested'].includes(firstParent.type)) {
+ subType = { ...subType, multi: { parent: firstParent.name } };
+ }
+
+ // We need to know if any parent field is nested
+ const nestedParentCaps = parentFieldCapsAscending.find(
+ parentCaps => parentCaps && parentCaps.type === 'nested'
+ );
+ if (nestedParentCaps) {
+ subType = { ...subType, nested: { path: nestedParentCaps.name } };
+ }
- if (parentFieldCaps && !['object', 'nested'].includes(parentFieldCaps.type)) {
- field.parent = parentFieldName;
- field.subType = 'multi';
+ if (Object.keys(subType).length > 0) {
+ field.subType = subType;
+ }
}
});
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/index.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/index.ts
similarity index 91%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/index.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/index.ts
index 8ac4225557784..6a541aff56471 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/index.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/index.ts
@@ -19,3 +19,4 @@
export { getFieldCapabilities } from './field_capabilities';
export { FieldCapsResponse } from './field_caps_response';
+export { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values';
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/overrides.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/overrides.ts
similarity index 95%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/overrides.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/overrides.ts
index 6310bf02e4430..518bfeccac01a 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/overrides.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/overrides.ts
@@ -18,7 +18,7 @@
*/
import { merge } from 'lodash';
-import { FieldDescriptor } from '../../index_patterns_service';
+import { FieldDescriptor } from '../../index_patterns_fetcher';
const OVERRIDES: Record> = {
_source: { type: '_source' },
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/should_read_field_from_doc_values.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/should_read_field_from_doc_values.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/should_read_field_from_doc_values.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/should_read_field_from_doc_values.ts
diff --git a/src/legacy/server/index_patterns/service/lib/index.ts b/src/plugins/data/server/index_patterns/fetcher/lib/index.ts
similarity index 90%
rename from src/legacy/server/index_patterns/service/lib/index.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/index.ts
index cd239b3753aa3..20e74d2b1a579 100644
--- a/src/legacy/server/index_patterns/service/lib/index.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/index.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-export { getFieldCapabilities } from './field_capabilities';
-// @ts-ignore
+export { getFieldCapabilities, shouldReadFieldFromDocValues } from './field_capabilities';
export { resolveTimePattern } from './resolve_time_pattern';
-// @ts-ignore
export { createNoMatchingIndicesError } from './errors';
diff --git a/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.test.js
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/resolve_time_pattern.test.js
rename to src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.test.js
diff --git a/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.ts b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/resolve_time_pattern.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts
diff --git a/src/legacy/server/index_patterns/service/lib/time_pattern_to_wildcard.test.ts b/src/plugins/data/server/index_patterns/fetcher/lib/time_pattern_to_wildcard.test.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/time_pattern_to_wildcard.test.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/time_pattern_to_wildcard.test.ts
diff --git a/src/legacy/server/index_patterns/service/lib/time_pattern_to_wildcard.ts b/src/plugins/data/server/index_patterns/fetcher/lib/time_pattern_to_wildcard.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/time_pattern_to_wildcard.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/time_pattern_to_wildcard.ts
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts b/src/plugins/data/server/index_patterns/index.ts
similarity index 83%
rename from src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts
rename to src/plugins/data/server/index_patterns/index.ts
index 04c99a1547ba9..6937fa22c4e5d 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts
+++ b/src/plugins/data/server/index_patterns/index.ts
@@ -17,10 +17,5 @@
* under the License.
*/
-export const settingsGet = jest.fn();
-
-jest.doMock('ui/chrome', () => ({
- getUiSettingsClient: () => ({
- get: settingsGet,
- }),
-}));
+export { IndexPatternsFetcher, FieldDescriptor, shouldReadFieldFromDocValues } from './fetcher';
+export { IndexPatternsService } from './index_patterns_service';
diff --git a/packages/kbn-es-query/src/filters/query.js b/src/plugins/data/server/index_patterns/index_patterns_service.ts
similarity index 72%
rename from packages/kbn-es-query/src/filters/query.js
rename to src/plugins/data/server/index_patterns/index_patterns_service.ts
index ded877231bf67..30d199c0e522e 100644
--- a/packages/kbn-es-query/src/filters/query.js
+++ b/src/plugins/data/server/index_patterns/index_patterns_service.ts
@@ -17,18 +17,14 @@
* under the License.
*/
-// Creates a filter corresponding to a raw Elasticsearch query DSL object
-export function buildQueryFilter(query, index, alias) {
- const filter = {
- query: query,
- meta: {
- index,
- }
- };
+import { CoreSetup } from 'kibana/server';
+import { Plugin } from '../../../../core/server';
+import { registerRoutes } from './routes';
- if (alias) {
- filter.meta.alias = alias;
+export class IndexPatternsService implements Plugin {
+ public setup({ http, elasticsearch }: CoreSetup) {
+ registerRoutes(http, elasticsearch);
}
- return filter;
+ public start() {}
}
diff --git a/src/legacy/server/index_patterns/routes.ts b/src/plugins/data/server/index_patterns/routes.ts
similarity index 90%
rename from src/legacy/server/index_patterns/routes.ts
rename to src/plugins/data/server/index_patterns/routes.ts
index fb78b94e0f77f..7975e923e219b 100644
--- a/src/legacy/server/index_patterns/routes.ts
+++ b/src/plugins/data/server/index_patterns/routes.ts
@@ -25,18 +25,18 @@ import {
RequestHandlerContext,
APICaller,
CallAPIOptions,
-} from '../../../core/server';
-import { IndexPatternsService } from './service';
+} from '../../../../core/server';
+import { IndexPatternsFetcher } from './fetcher';
-export function registerRoutes(core: CoreSetup) {
- const getIndexPatternsService = async (request: KibanaRequest): Promise => {
- const client = await core.elasticsearch.dataClient$.pipe(first()).toPromise();
+export function registerRoutes(http: CoreSetup['http'], elasticsearch: CoreSetup['elasticsearch']) {
+ const getIndexPatternsService = async (request: KibanaRequest): Promise => {
+ const client = await elasticsearch.dataClient$.pipe(first()).toPromise();
const callCluster: APICaller = (
endpoint: string,
params?: Record,
options?: CallAPIOptions
) => client.asScoped(request).callAsCurrentUser(endpoint, params, options);
- return new Promise(resolve => resolve(new IndexPatternsService(callCluster)));
+ return new Promise(resolve => resolve(new IndexPatternsFetcher(callCluster)));
};
const parseMetaFields = (metaFields: string | string[]) => {
@@ -49,7 +49,7 @@ export function registerRoutes(core: CoreSetup) {
return parsedFields;
};
- const router = core.http.createRouter();
+ const router = http.createRouter();
router.get(
{
path: '/api/index_patterns/_fields_for_wildcard',
diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts
index 9cf08b0702e9e..e81250e653ebd 100644
--- a/src/plugins/data/server/plugin.ts
+++ b/src/plugins/data/server/plugin.ts
@@ -18,19 +18,21 @@
*/
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/server';
+import { IndexPatternsService } from './index_patterns';
import { ISearchSetup } from './search';
import { SearchService } from './search/search_service';
export interface DataPluginSetup {
search: ISearchSetup;
}
-
export class DataServerPlugin implements Plugin {
private readonly searchService: SearchService;
+ private readonly indexPatterns = new IndexPatternsService();
constructor(initializerContext: PluginInitializerContext) {
this.searchService = new SearchService(initializerContext);
}
public setup(core: CoreSetup) {
+ this.indexPatterns.setup(core);
return {
search: this.searchService.setup(core),
};
diff --git a/src/plugins/embeddable/public/_index.scss b/src/plugins/embeddable/public/_index.scss
new file mode 100644
index 0000000000000..ed80b3f9983e5
--- /dev/null
+++ b/src/plugins/embeddable/public/_index.scss
@@ -0,0 +1,3 @@
+@import './variables';
+@import './lib/panel/index';
+@import './lib/panel/panel_header/index';
diff --git a/src/legacy/core_plugins/embeddable_api/public/_variables.scss b/src/plugins/embeddable/public/_variables.scss
similarity index 100%
rename from src/legacy/core_plugins/embeddable_api/public/_variables.scss
rename to src/plugins/embeddable/public/_variables.scss
diff --git a/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts b/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts
index 99cfb2ea13d07..e2592b70397f3 100644
--- a/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts
+++ b/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts
@@ -18,16 +18,16 @@
*/
import { i18n } from '@kbn/i18n';
-import { Filter } from '@kbn/es-query';
import { IAction, createAction, IncompatibleActionError } from '../ui_actions';
import { IEmbeddable, EmbeddableInput } from '../embeddables';
+import { esFilters } from '../../../../../plugins/data/public';
export const APPLY_FILTER_ACTION = 'APPLY_FILTER_ACTION';
-type RootEmbeddable = IEmbeddable;
+type RootEmbeddable = IEmbeddable;
interface ActionContext {
embeddable: IEmbeddable;
- filters: Filter[];
+ filters: esFilters.Filter[];
}
async function isCompatible(context: ActionContext) {
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 802be5bf1282e..47113ffc59561 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,7 +20,6 @@
import { ViewMode, EmbeddableOutput, isErrorEmbeddable } from '../../../../';
import { AddPanelAction } from './add_panel_action';
import { EmbeddableFactory } from '../../../../embeddables';
-import { Filter, FilterStateStore } from '@kbn/es-query';
import {
FILTERABLE_EMBEDDABLE,
FilterableEmbeddable,
@@ -32,6 +31,7 @@ import { GetEmbeddableFactory } from '../../../../types';
// eslint-disable-next-line
import { coreMock } from '../../../../../../../../core/public/mocks';
import { ContactCardEmbeddable } from '../../../../test_samples';
+import { esFilters } from '../../../../../../../../plugins/data/public';
const embeddableFactories = new Map();
embeddableFactories.set(FILTERABLE_EMBEDDABLE, new FilterableEmbeddableFactory());
@@ -51,8 +51,8 @@ beforeEach(async () => {
() => null
);
- const derivedFilter: Filter = {
- $state: { store: FilterStateStore.APP_STATE },
+ const derivedFilter: esFilters.Filter = {
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
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 550f9706a634b..8d9beec940acc 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
@@ -28,7 +28,6 @@ import {
} from '../../../test_samples';
// eslint-disable-next-line
import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks';
-import { FilterStateStore } from '@kbn/es-query';
import {
EmbeddableFactory,
EmbeddableOutput,
@@ -37,6 +36,7 @@ import {
} from '../../../embeddables';
import { GetEmbeddableFactory } from '../../../types';
import { of } from '../../../../tests/helpers';
+import { esFilters } from '../../../../../../../plugins/data/public';
const setup = async () => {
const embeddableFactories = new Map();
@@ -48,7 +48,7 @@ const setup = async () => {
panels: {},
filters: [
{
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
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 22e3be89f1ae9..684a8c45a4e89 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
@@ -17,7 +17,6 @@
* under the License.
*/
-import { Filter, FilterStateStore } from '@kbn/es-query';
import { EmbeddableOutput, isErrorEmbeddable } from '../../../';
import { RemovePanelAction } from './remove_panel_action';
import { EmbeddableFactory } from '../../../embeddables';
@@ -30,6 +29,7 @@ import { FilterableEmbeddableFactory } from '../../../test_samples/embeddables/f
import { FilterableContainer } from '../../../test_samples/embeddables/filterable_container';
import { GetEmbeddableFactory, ViewMode } from '../../../types';
import { ContactCardEmbeddable } from '../../../test_samples/embeddables/contact_card/contact_card_embeddable';
+import { esFilters } from '../../../../../../../plugins/data/public';
const embeddableFactories = new Map();
embeddableFactories.set(FILTERABLE_EMBEDDABLE, new FilterableEmbeddableFactory());
@@ -39,8 +39,8 @@ let container: FilterableContainer;
let embeddable: FilterableEmbeddable;
beforeEach(async () => {
- const derivedFilter: Filter = {
- $state: { store: FilterStateStore.APP_STATE },
+ const derivedFilter: esFilters.Filter = {
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
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 eaef8048a6fbf..de708b778c3c7 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
@@ -16,14 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+
import { Container, ContainerInput } from '../../containers';
import { GetEmbeddableFactory } from '../../types';
+import { esFilters } from '../../../../../data/public';
export const FILTERABLE_CONTAINER = 'FILTERABLE_CONTAINER';
export interface FilterableContainerInput extends ContainerInput {
- filters: Filter[];
+ filters: esFilters.Filter[];
}
/**
@@ -33,7 +34,7 @@ export interface FilterableContainerInput extends ContainerInput {
*/
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type InheritedChildrenInput = {
- filters: Filter[];
+ filters: esFilters.Filter[];
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 f6885ca25b437..56aa7688f37a6 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
@@ -17,14 +17,14 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { IContainer } from '../../containers';
import { EmbeddableOutput, EmbeddableInput, Embeddable } from '../../embeddables';
+import { esFilters } from '../../../../../data/public';
export const FILTERABLE_EMBEDDABLE = 'FILTERABLE_EMBEDDABLE';
export interface FilterableEmbeddableInput extends EmbeddableInput {
- filters: Filter[];
+ filters: esFilters.Filter[];
}
export class FilterableEmbeddable extends Embeddable {
diff --git a/src/plugins/embeddable/public/tests/apply_filter_action.test.ts b/src/plugins/embeddable/public/tests/apply_filter_action.test.ts
index 52500acc3dc59..0721acb1a1fba 100644
--- a/src/plugins/embeddable/public/tests/apply_filter_action.test.ts
+++ b/src/plugins/embeddable/public/tests/apply_filter_action.test.ts
@@ -32,7 +32,7 @@ import {
} from '../lib/test_samples';
// eslint-disable-next-line
import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks';
-import { FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../plugins/data/public';
test('ApplyFilterAction applies the filter to the root of the container tree', async () => {
const { doStart } = testPlugin();
@@ -76,7 +76,7 @@ test('ApplyFilterAction applies the filter to the root of the container tree', a
}
const filter: any = {
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: {
disabled: false,
negate: false,
diff --git a/src/plugins/embeddable/public/tests/container.test.ts b/src/plugins/embeddable/public/tests/container.test.ts
index 3bdbcbad857d6..f97c26a41b901 100644
--- a/src/plugins/embeddable/public/tests/container.test.ts
+++ b/src/plugins/embeddable/public/tests/container.test.ts
@@ -26,7 +26,6 @@ import {
FILTERABLE_EMBEDDABLE,
} from '../lib/test_samples/embeddables/filterable_embeddable';
import { ERROR_EMBEDDABLE_TYPE } from '../lib/embeddables/error_embeddable';
-import { Filter, FilterStateStore } from '@kbn/es-query';
import { FilterableEmbeddableFactory } from '../lib/test_samples/embeddables/filterable_embeddable_factory';
import { CONTACT_CARD_EMBEDDABLE } from '../lib/test_samples/embeddables/contact_card/contact_card_embeddable_factory';
import { SlowContactCardEmbeddableFactory } from '../lib/test_samples/embeddables/contact_card/slow_contact_card_embeddable_factory';
@@ -46,6 +45,7 @@ import {
import { coreMock } from '../../../../core/public/mocks';
import { testPlugin } from './test_plugin';
import { of } from './helpers';
+import { esFilters } from '../../../../plugins/data/public';
async function creatHelloWorldContainerAndEmbeddable(
containerInput: ContainerInput = { id: 'hello', panels: {} },
@@ -437,8 +437,8 @@ test('Test nested reactions', async done => {
test('Explicit embeddable input mapped to undefined will default to inherited', async () => {
const { start } = await creatHelloWorldContainerAndEmbeddable();
- const derivedFilter: Filter = {
- $state: { store: FilterStateStore.APP_STATE },
+ const derivedFilter: esFilters.Filter = {
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
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 6cde7bdc48ba1..47c4b0944cef2 100644
--- a/src/plugins/embeddable/public/tests/explicit_input.test.ts
+++ b/src/plugins/embeddable/public/tests/explicit_input.test.ts
@@ -18,7 +18,6 @@
*/
import { skip } from 'rxjs/operators';
-import { Filter, FilterStateStore } from '@kbn/es-query';
import { testPlugin } from './test_plugin';
import {
FILTERABLE_EMBEDDABLE,
@@ -34,6 +33,7 @@ import { isErrorEmbeddable } from '../lib';
import { HelloWorldContainer } from '../lib/test_samples/embeddables/hello_world_container';
// eslint-disable-next-line
import { coreMock } from '../../../../core/public/mocks';
+import { esFilters } from '../../../../plugins/data/public';
const { setup, doStart, coreStart, uiActions } = testPlugin(
coreMock.createSetup(),
@@ -50,8 +50,8 @@ setup.registerEmbeddableFactory(CONTACT_CARD_EMBEDDABLE, factory);
setup.registerEmbeddableFactory(HELLO_WORLD_EMBEDDABLE_TYPE, new HelloWorldEmbeddableFactory());
test('Explicit embeddable input mapped to undefined will default to inherited', async () => {
- const derivedFilter: Filter = {
- $state: { store: FilterStateStore.APP_STATE },
+ const derivedFilter: esFilters.Filter = {
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
diff --git a/src/plugins/expressions/kibana.json b/src/plugins/expressions/kibana.json
index ce2b1854cf415..ec87b56f3745e 100644
--- a/src/plugins/expressions/kibana.json
+++ b/src/plugins/expressions/kibana.json
@@ -2,5 +2,8 @@
"id": "expressions",
"version": "kibana",
"server": false,
- "ui": true
+ "ui": true,
+ "requiredPlugins": [
+ "inspector"
+ ]
}
diff --git a/src/plugins/expressions/common/expressions/create_error.ts b/src/plugins/expressions/public/create_error.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/create_error.ts
rename to src/plugins/expressions/public/create_error.ts
diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable_api.ts b/src/plugins/expressions/public/create_handlers.ts
similarity index 90%
rename from src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable_api.ts
rename to src/plugins/expressions/public/create_handlers.ts
index 17911b908d3b3..46e85411c5895 100644
--- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable_api.ts
+++ b/src/plugins/expressions/public/create_handlers.ts
@@ -17,4 +17,8 @@
* under the License.
*/
-export * from '../../../../../embeddable_api/public/np_ready/public';
+export function createHandlers() {
+ return {
+ environment: 'client',
+ };
+}
diff --git a/src/plugins/expressions/common/expressions/expression_types/boolean.ts b/src/plugins/expressions/public/expression_types/boolean.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/boolean.ts
rename to src/plugins/expressions/public/expression_types/boolean.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/datatable.ts b/src/plugins/expressions/public/expression_types/datatable.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/datatable.ts
rename to src/plugins/expressions/public/expression_types/datatable.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/error.ts b/src/plugins/expressions/public/expression_types/error.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/error.ts
rename to src/plugins/expressions/public/expression_types/error.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/filter.ts b/src/plugins/expressions/public/expression_types/filter.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/filter.ts
rename to src/plugins/expressions/public/expression_types/filter.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/image.ts b/src/plugins/expressions/public/expression_types/image.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/image.ts
rename to src/plugins/expressions/public/expression_types/image.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/index.ts b/src/plugins/expressions/public/expression_types/index.ts
similarity index 93%
rename from src/plugins/expressions/common/expressions/expression_types/index.ts
rename to src/plugins/expressions/public/expression_types/index.ts
index bb8a554487f01..a5d182fee75ed 100644
--- a/src/plugins/expressions/common/expressions/expression_types/index.ts
+++ b/src/plugins/expressions/public/expression_types/index.ts
@@ -22,6 +22,8 @@ import { datatable } from './datatable';
import { error } from './error';
import { filter } from './filter';
import { image } from './image';
+import { kibanaContext } from './kibana_context';
+import { kibanaDatatable } from './kibana_datatable';
import { nullType } from './null';
import { number } from './number';
import { pointseries } from './pointseries';
@@ -30,8 +32,6 @@ import { render } from './render';
import { shape } from './shape';
import { string } from './string';
import { style } from './style';
-import { kibanaContext } from './kibana_context';
-import { kibanaDatatable } from './kibana_datatable';
export const typeSpecs = [
boolean,
@@ -39,26 +39,30 @@ export const typeSpecs = [
error,
filter,
image,
- number,
+ kibanaContext,
+ kibanaDatatable,
nullType,
+ number,
pointseries,
range,
render,
shape,
string,
style,
- kibanaContext,
- kibanaDatatable,
];
-// Types
+export * from './boolean';
export * from './datatable';
export * from './error';
export * from './filter';
export * from './image';
export * from './kibana_context';
export * from './kibana_datatable';
+export * from './null';
+export * from './number';
export * from './pointseries';
+export * from './range';
export * from './render';
+export * from './shape';
+export * from './string';
export * from './style';
-export * from './range';
diff --git a/src/plugins/expressions/common/expressions/expression_types/kibana_context.ts b/src/plugins/expressions/public/expression_types/kibana_context.ts
similarity index 90%
rename from src/plugins/expressions/common/expressions/expression_types/kibana_context.ts
rename to src/plugins/expressions/public/expression_types/kibana_context.ts
index 174517abc2c05..bcf8e2853dec8 100644
--- a/src/plugins/expressions/common/expressions/expression_types/kibana_context.ts
+++ b/src/plugins/expressions/public/expression_types/kibana_context.ts
@@ -17,8 +17,7 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
-import { TimeRange, Query } from 'src/plugins/data/public';
+import { TimeRange, Query, esFilters } from 'src/plugins/data/public';
const name = 'kibana_context';
export type KIBANA_CONTEXT_NAME = 'kibana_context';
@@ -26,7 +25,7 @@ export type KIBANA_CONTEXT_NAME = 'kibana_context';
export interface KibanaContext {
type: typeof name;
query?: Query | Query[];
- filters?: Filter[];
+ filters?: esFilters.Filter[];
timeRange?: TimeRange;
}
diff --git a/src/plugins/expressions/common/expressions/expression_types/kibana_datatable.ts b/src/plugins/expressions/public/expression_types/kibana_datatable.ts
similarity index 97%
rename from src/plugins/expressions/common/expressions/expression_types/kibana_datatable.ts
rename to src/plugins/expressions/public/expression_types/kibana_datatable.ts
index 7f77e226ff1d9..c360a2be8c7f7 100644
--- a/src/plugins/expressions/common/expressions/expression_types/kibana_datatable.ts
+++ b/src/plugins/expressions/public/expression_types/kibana_datatable.ts
@@ -19,7 +19,7 @@
import { map } from 'lodash';
import { SerializedFieldFormat } from '../types/common';
-import { Datatable, PointSeries } from '../types';
+import { Datatable, PointSeries } from '.';
const name = 'kibana_datatable';
diff --git a/src/plugins/expressions/common/expressions/expression_types/null.ts b/src/plugins/expressions/public/expression_types/null.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/null.ts
rename to src/plugins/expressions/public/expression_types/null.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/number.ts b/src/plugins/expressions/public/expression_types/number.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/number.ts
rename to src/plugins/expressions/public/expression_types/number.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/pointseries.ts b/src/plugins/expressions/public/expression_types/pointseries.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/pointseries.ts
rename to src/plugins/expressions/public/expression_types/pointseries.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/range.ts b/src/plugins/expressions/public/expression_types/range.ts
similarity index 94%
rename from src/plugins/expressions/common/expressions/expression_types/range.ts
rename to src/plugins/expressions/public/expression_types/range.ts
index c1a0e4d2075fa..082056c909988 100644
--- a/src/plugins/expressions/common/expressions/expression_types/range.ts
+++ b/src/plugins/expressions/public/expression_types/range.ts
@@ -17,7 +17,8 @@
* under the License.
*/
-import { ExpressionType, Render } from '../../../common/expressions/types';
+import { ExpressionType } from '../types';
+import { Render } from '.';
const name = 'range';
diff --git a/src/plugins/expressions/common/expressions/expression_types/render.ts b/src/plugins/expressions/public/expression_types/render.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/render.ts
rename to src/plugins/expressions/public/expression_types/render.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/shape.ts b/src/plugins/expressions/public/expression_types/shape.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/shape.ts
rename to src/plugins/expressions/public/expression_types/shape.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/string.ts b/src/plugins/expressions/public/expression_types/string.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/expression_types/string.ts
rename to src/plugins/expressions/public/expression_types/string.ts
diff --git a/src/plugins/expressions/common/expressions/expression_types/style.ts b/src/plugins/expressions/public/expression_types/style.ts
similarity index 83%
rename from src/plugins/expressions/common/expressions/expression_types/style.ts
rename to src/plugins/expressions/public/expression_types/style.ts
index f6ef0f1fe42e6..d93893d25c11c 100644
--- a/src/plugins/expressions/common/expressions/expression_types/style.ts
+++ b/src/plugins/expressions/public/expression_types/style.ts
@@ -17,17 +17,11 @@
* under the License.
*/
-import { ExpressionType } from '../types';
+import { ExpressionType, ExpressionTypeStyle } from '../types';
const name = 'style';
-export interface Style {
- type: typeof name;
- spec: any;
- css: string;
-}
-
-export const style = (): ExpressionType => ({
+export const style = (): ExpressionType => ({
name,
from: {
null: () => {
diff --git a/src/plugins/expressions/public/expressions/expressions_service.ts b/src/plugins/expressions/public/expressions/expressions_service.ts
deleted file mode 100644
index 4b6820143b794..0000000000000
--- a/src/plugins/expressions/public/expressions/expressions_service.ts
+++ /dev/null
@@ -1,69 +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 { FunctionsRegistry, RenderFunctionsRegistry, TypesRegistry } from './interpreter';
-import { AnyExpressionType, AnyExpressionFunction } from '../../common/expressions/types';
-
-export interface ExpressionsSetupContract {
- registerFunction: (fn: () => AnyExpressionFunction) => void;
- registerRenderer: (renderer: any) => void;
- registerType: (type: () => AnyExpressionType) => void;
- __LEGACY: {
- functions: FunctionsRegistry;
- renderers: RenderFunctionsRegistry;
- types: TypesRegistry;
- };
-}
-
-export type ExpressionsStartContract = ExpressionsSetupContract;
-
-export class ExpressionsService {
- private readonly functions = new FunctionsRegistry();
- private readonly renderers = new RenderFunctionsRegistry();
- private readonly types = new TypesRegistry();
-
- private setupApi!: ExpressionsSetupContract;
-
- public setup() {
- const { functions, renderers, types } = this;
-
- this.setupApi = {
- registerFunction: fn => {
- this.functions.register(fn);
- },
- registerRenderer: (renderer: any) => {
- this.renderers.register(renderer);
- },
- registerType: type => {
- this.types.register(type);
- },
- __LEGACY: {
- functions,
- renderers,
- types,
- },
- };
-
- return this.setupApi;
- }
-
- public start(): ExpressionsStartContract {
- return this.setupApi as ExpressionsStartContract;
- }
-}
diff --git a/src/plugins/expressions/public/expressions/interpreter.ts b/src/plugins/expressions/public/expressions/interpreter.ts
deleted file mode 100644
index f27ef57c7980a..0000000000000
--- a/src/plugins/expressions/public/expressions/interpreter.ts
+++ /dev/null
@@ -1,173 +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.
- */
-
-/**
- * @todo
- * This whole file needs major refactoring. `Registry` class does not do anything
- * useful. "Wrappers" like `RenderFunction` basically just set default props on the objects.
- */
-
-/* eslint-disable max-classes-per-file */
-import { clone, mapValues, includes } from 'lodash';
-import { Type } from '../../common/expressions/interpreter';
-import { ExpressionType, AnyExpressionFunction } from '../../common/expressions/types';
-
-export class Registry {
- _prop: string;
- _indexed: any;
-
- constructor(prop: string = 'name') {
- if (typeof prop !== 'string') throw new Error('Registry property name must be a string');
- this._prop = prop;
- this._indexed = new Object();
- }
-
- wrapper(obj: ItemSpec) {
- return obj;
- }
-
- register(fn: () => ItemSpec) {
- if (typeof fn !== 'function') throw new Error(`Register requires an function`);
-
- const obj = fn() as any;
-
- if (typeof obj !== 'object' || !obj[this._prop]) {
- throw new Error(`Registered functions must return an object with a ${this._prop} property`);
- }
-
- this._indexed[obj[this._prop].toLowerCase()] = this.wrapper(obj);
- }
-
- toJS(): Record {
- return Object.keys(this._indexed).reduce(
- (acc, key) => {
- acc[key] = this.get(key);
- return acc;
- },
- {} as any
- );
- }
-
- toArray(): Item[] {
- return Object.keys(this._indexed).map(key => this.get(key)!);
- }
-
- get(name: string): Item | null {
- if (name === undefined) {
- return null;
- }
- const lowerCaseName = name.toLowerCase();
- return this._indexed[lowerCaseName] ? clone(this._indexed[lowerCaseName]) : null;
- }
-
- getProp(): string {
- return this._prop;
- }
-
- reset() {
- this._indexed = new Object();
- }
-}
-
-function RenderFunction(this: any, config: any) {
- // This must match the name of the function that is used to create the `type: render` object
- this.name = config.name;
-
- // Use this to set a more friendly name
- this.displayName = config.displayName || this.name;
-
- // A sentence or few about what this element does
- this.help = config.help;
-
- // used to validate the data before calling the render function
- this.validate = config.validate || function validate() {};
-
- // tell the renderer if the dom node should be reused, it's recreated each time by default
- this.reuseDomNode = Boolean(config.reuseDomNode);
-
- // the function called to render the data
- this.render =
- config.render ||
- function render(domNode: any, data: any, done: any) {
- done();
- };
-}
-
-export function Arg(this: any, config: any) {
- if (config.name === '_') throw Error('Arg names must not be _. Use it in aliases instead.');
- this.name = config.name;
- this.required = config.required || false;
- this.help = config.help || '';
- this.types = config.types || [];
- this.default = config.default;
- this.aliases = config.aliases || [];
- this.multi = config.multi == null ? false : config.multi;
- this.resolve = config.resolve == null ? true : config.resolve;
- this.options = config.options || [];
- this.accepts = (type: any) => {
- if (!this.types.length) return true;
- return includes(config.types, type);
- };
-}
-
-export function Fn(this: any, config: any) {
- // Required
- this.name = config.name; // Name of function
-
- // Return type of function.
- // This SHOULD be supplied. We use it for UI and autocomplete hinting,
- // We may also use it for optimizations in the future.
- this.type = config.type;
- this.aliases = config.aliases || [];
-
- // Function to run function (context, args)
- this.fn = (...args: any) => Promise.resolve(config.fn(...args));
-
- // Optional
- this.help = config.help || ''; // A short help text
- this.args = mapValues(
- config.args || {},
- (arg: any, name: any) => new (Arg as any)({ name, ...arg })
- );
-
- this.context = config.context || {};
-
- this.accepts = (type: any) => {
- if (!this.context.types) return true; // If you don't tell us about context, we'll assume you don't care what you get
- return includes(this.context.types, type); // Otherwise, check it
- };
-}
-
-export class RenderFunctionsRegistry extends Registry {
- wrapper(obj: any) {
- return new (RenderFunction as any)(obj);
- }
-}
-
-export class FunctionsRegistry extends Registry {
- wrapper(obj: any) {
- return new (Fn as any)(obj);
- }
-}
-
-export class TypesRegistry extends Registry, any> {
- wrapper(obj: any) {
- return new (Type as any)(obj);
- }
-}
diff --git a/src/plugins/expressions/public/fonts.ts b/src/plugins/expressions/public/fonts.ts
new file mode 100644
index 0000000000000..cdf3d4c16f3b5
--- /dev/null
+++ b/src/plugins/expressions/public/fonts.ts
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+/**
+ * This type contains a unions of all supported font labels, or the the name of
+ * the font the user would see in a UI.
+ */
+export type FontLabel = typeof fonts[number]['label'];
+
+/**
+ * This type contains a union of all supported font values, equivalent to the CSS
+ * `font-value` property.
+ */
+export type FontValue = typeof fonts[number]['value'];
+
+/**
+ * An interface representing a font in Canvas, with a textual label and the CSS
+ * `font-value`.
+ */
+export interface Font {
+ label: FontLabel;
+ value: FontValue;
+}
+
+// This function allows one to create a strongly-typed font for inclusion in
+// the font collection. As a result, the values and labels are known to the
+// type system, preventing one from specifying a non-existent font at build
+// time.
+function createFont<
+ RawFont extends { value: RawFontValue; label: RawFontLabel },
+ RawFontValue extends string,
+ RawFontLabel extends string
+>(font: RawFont) {
+ return font;
+}
+
+export const americanTypewriter = createFont({
+ label: 'American Typewriter',
+ value: "'American Typewriter', 'Courier New', Courier, Monaco, mono",
+});
+
+export const arial = createFont({ label: 'Arial', value: 'Arial, sans-serif' });
+
+export const baskerville = createFont({
+ label: 'Baskerville',
+ value: "Baskerville, Georgia, Garamond, 'Times New Roman', Times, serif",
+});
+
+export const bookAntiqua = createFont({
+ label: 'Book Antiqua',
+ value: "'Book Antiqua', Georgia, Garamond, 'Times New Roman', Times, serif",
+});
+
+export const brushScript = createFont({
+ label: 'Brush Script',
+ value: "'Brush Script MT', 'Comic Sans', sans-serif",
+});
+
+export const chalkboard = createFont({
+ label: 'Chalkboard',
+ value: "Chalkboard, 'Comic Sans', sans-serif",
+});
+
+export const didot = createFont({
+ label: 'Didot',
+ value: "Didot, Georgia, Garamond, 'Times New Roman', Times, serif",
+});
+
+export const futura = createFont({
+ label: 'Futura',
+ value: 'Futura, Impact, Helvetica, Arial, sans-serif',
+});
+
+export const gillSans = createFont({
+ label: 'Gill Sans',
+ value:
+ "'Gill Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, Arial, sans-serif",
+});
+
+export const helveticaNeue = createFont({
+ label: 'Helvetica Neue',
+ value: "'Helvetica Neue', Helvetica, Arial, sans-serif",
+});
+
+export const hoeflerText = createFont({
+ label: 'Hoefler Text',
+ value: "'Hoefler Text', Garamond, Georgia, 'Times New Roman', Times, serif",
+});
+
+export const lucidaGrande = createFont({
+ label: 'Lucida Grande',
+ value: "'Lucida Grande', 'Lucida Sans Unicode', Lucida, Verdana, Helvetica, Arial, sans-serif",
+});
+
+export const myriad = createFont({
+ label: 'Myriad',
+ value: 'Myriad, Helvetica, Arial, sans-serif',
+});
+
+export const openSans = createFont({
+ label: 'Open Sans',
+ value: "'Open Sans', Helvetica, Arial, sans-serif",
+});
+
+export const optima = createFont({
+ label: 'Optima',
+ value: "Optima, 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, Arial, sans-serif",
+});
+
+export const palatino = createFont({
+ label: 'Palatino',
+ value: "Palatino, 'Book Antiqua', Georgia, Garamond, 'Times New Roman', Times, serif",
+});
+
+/**
+ * A collection of supported fonts.
+ */
+export const fonts = [
+ americanTypewriter,
+ arial,
+ baskerville,
+ bookAntiqua,
+ brushScript,
+ chalkboard,
+ didot,
+ futura,
+ gillSans,
+ helveticaNeue,
+ hoeflerText,
+ lucidaGrande,
+ myriad,
+ openSans,
+ optima,
+ palatino,
+];
diff --git a/src/plugins/expressions/public/functions/clog.ts b/src/plugins/expressions/public/functions/clog.ts
new file mode 100644
index 0000000000000..929075b882b96
--- /dev/null
+++ b/src/plugins/expressions/public/functions/clog.ts
@@ -0,0 +1,35 @@
+/*
+ * 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 { ExpressionFunction } from '../types';
+
+const name = 'clog';
+
+type Context = any;
+type ClogExpressionFunction = ExpressionFunction;
+
+export const clog = (): ClogExpressionFunction => ({
+ name,
+ args: {},
+ help: 'Outputs the context to the console',
+ fn: context => {
+ console.log(context); // eslint-disable-line no-console
+ return context;
+ },
+});
diff --git a/src/plugins/expressions/public/functions/font.ts b/src/plugins/expressions/public/functions/font.ts
new file mode 100644
index 0000000000000..33e28924f3ee1
--- /dev/null
+++ b/src/plugins/expressions/public/functions/font.ts
@@ -0,0 +1,186 @@
+/*
+ * 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 { openSans, FontLabel as FontFamily } from '../fonts';
+import { ExpressionFunction } from '../types';
+import { CSSStyle, FontStyle, FontWeight, Style, TextAlignment, TextDecoration } from '../types';
+
+const dashify = (str: string) => {
+ return str
+ .trim()
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
+ .replace(/\W/g, m => (/[À-ž]/.test(m) ? m : '-'))
+ .replace(/^-+|-+$/g, '')
+ .toLowerCase();
+};
+
+const inlineStyle = (obj: Record) => {
+ if (!obj) return '';
+ const styles = Object.keys(obj).map(key => {
+ const prop = dashify(key);
+ const line = prop.concat(':').concat(String(obj[key]));
+ return line;
+ });
+ return styles.join(';');
+};
+
+interface Arguments {
+ align?: TextAlignment;
+ color?: string;
+ family?: FontFamily;
+ italic?: boolean;
+ lHeight?: number | null;
+ size?: number;
+ underline?: boolean;
+ weight?: FontWeight;
+}
+
+export function font(): ExpressionFunction<'font', null, Arguments, Style> {
+ return {
+ name: 'font',
+ aliases: [],
+ type: 'style',
+ help: i18n.translate('expressions_np.functions.fontHelpText', {
+ defaultMessage: 'Create a font style.',
+ }),
+ context: {
+ types: ['null'],
+ },
+ args: {
+ align: {
+ default: 'left',
+ help: i18n.translate('expressions_np.functions.font.args.alignHelpText', {
+ defaultMessage: 'The horizontal text alignment.',
+ }),
+ options: Object.values(TextAlignment),
+ types: ['string'],
+ },
+ color: {
+ help: i18n.translate('expressions_np.functions.font.args.colorHelpText', {
+ defaultMessage: 'The text color.',
+ }),
+ types: ['string'],
+ },
+ family: {
+ default: `"${openSans.value}"`,
+ help: i18n.translate('expressions_np.functions.font.args.familyHelpText', {
+ defaultMessage: 'An acceptable {css} web font string',
+ values: {
+ css: 'CSS',
+ },
+ }),
+ types: ['string'],
+ },
+ italic: {
+ default: false,
+ help: i18n.translate('expressions_np.functions.font.args.italicHelpText', {
+ defaultMessage: 'Italicize the text?',
+ }),
+ options: [true, false],
+ types: ['boolean'],
+ },
+ lHeight: {
+ default: null,
+ aliases: ['lineHeight'],
+ help: i18n.translate('expressions_np.functions.font.args.lHeightHelpText', {
+ defaultMessage: 'The line height in pixels',
+ }),
+ types: ['number', 'null'],
+ },
+ size: {
+ default: 14,
+ help: i18n.translate('expressions_np.functions.font.args.sizeHelpText', {
+ defaultMessage: 'The font size in pixels',
+ }),
+ types: ['number'],
+ },
+ underline: {
+ default: false,
+ help: i18n.translate('expressions_np.functions.font.args.underlineHelpText', {
+ defaultMessage: 'Underline the text?',
+ }),
+ options: [true, false],
+ types: ['boolean'],
+ },
+ weight: {
+ default: 'normal',
+ help: i18n.translate('expressions_np.functions.font.args.weightHelpText', {
+ defaultMessage: 'The font weight. For example, {list}, or {end}.',
+ values: {
+ list: Object.values(FontWeight)
+ .slice(0, -1)
+ .map(weight => `\`"${weight}"\``)
+ .join(', '),
+ end: `\`"${Object.values(FontWeight).slice(-1)[0]}"\``,
+ },
+ }),
+ options: Object.values(FontWeight),
+ types: ['string'],
+ },
+ },
+ fn: (_context, args) => {
+ if (!Object.values(FontWeight).includes(args.weight!)) {
+ throw new Error(
+ i18n.translate('expressions_np.functions.font.invalidFontWeightErrorMessage', {
+ defaultMessage: "Invalid font weight: '{weight}'",
+ values: {
+ weight: args.weight,
+ },
+ })
+ );
+ }
+ if (!Object.values(TextAlignment).includes(args.align!)) {
+ throw new Error(
+ i18n.translate('expressions_np.functions.font.invalidTextAlignmentErrorMessage', {
+ defaultMessage: "Invalid text alignment: '{align}'",
+ values: {
+ align: args.align,
+ },
+ })
+ );
+ }
+
+ // the line height shouldn't ever be lower than the size, and apply as a
+ // pixel setting
+ const lineHeight = args.lHeight != null ? `${args.lHeight}px` : '1';
+
+ const spec: CSSStyle = {
+ fontFamily: args.family,
+ fontWeight: args.weight,
+ fontStyle: args.italic ? FontStyle.ITALIC : FontStyle.NORMAL,
+ textDecoration: args.underline ? TextDecoration.UNDERLINE : TextDecoration.NONE,
+ textAlign: args.align,
+ fontSize: `${args.size}px`, // apply font size as a pixel setting
+ lineHeight, // apply line height as a pixel setting
+ };
+
+ // conditionally apply styles based on input
+ if (args.color) {
+ spec.color = args.color;
+ }
+
+ return {
+ type: 'style',
+ spec,
+ css: inlineStyle(spec as Record),
+ };
+ },
+ };
+}
diff --git a/src/plugins/expressions/public/functions/kibana.ts b/src/plugins/expressions/public/functions/kibana.ts
new file mode 100644
index 0000000000000..7ed9619675aea
--- /dev/null
+++ b/src/plugins/expressions/public/functions/kibana.ts
@@ -0,0 +1,64 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { ExpressionFunction } from '../types';
+import { KibanaContext } from '../expression_types';
+
+export type ExpressionFunctionKibana = ExpressionFunction<
+ 'kibana',
+ KibanaContext | null,
+ object,
+ KibanaContext
+>;
+
+export const kibana = (): ExpressionFunctionKibana => ({
+ name: 'kibana',
+ type: 'kibana_context',
+
+ context: {
+ types: ['kibana_context', 'null'],
+ },
+
+ help: i18n.translate('expressions_np.functions.kibana.help', {
+ defaultMessage: 'Gets kibana global context',
+ }),
+ args: {},
+ fn(context, args, handlers) {
+ const initialContext = handlers.getInitialContext ? handlers.getInitialContext() : {};
+
+ if (context && context.query) {
+ initialContext.query = initialContext.query.concat(context.query);
+ }
+
+ if (context && context.filters) {
+ initialContext.filters = initialContext.filters.concat(context.filters);
+ }
+
+ const timeRange = initialContext.timeRange || (context ? context.timeRange : undefined);
+
+ return {
+ ...context,
+ type: 'kibana_context',
+ query: initialContext.query,
+ filters: initialContext.filters,
+ timeRange,
+ };
+ },
+});
diff --git a/src/legacy/core_plugins/interpreter/public/functions/kibana_context.ts b/src/plugins/expressions/public/functions/kibana_context.ts
similarity index 74%
rename from src/legacy/core_plugins/interpreter/public/functions/kibana_context.ts
rename to src/plugins/expressions/public/functions/kibana_context.ts
index 1ba7b450c5409..2a0cd09734b6d 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/kibana_context.ts
+++ b/src/plugins/expressions/public/functions/kibana_context.ts
@@ -17,9 +17,10 @@
* under the License.
*/
-import chrome from 'ui/chrome';
import { i18n } from '@kbn/i18n';
-import { ExpressionFunction, KibanaContext } from '../../types';
+import { ExpressionFunction } from '../types';
+import { KibanaContext } from '../expression_types';
+import { savedObjects } from '../services';
interface Arguments {
q?: string | null;
@@ -41,7 +42,7 @@ export const kibanaContext = (): ExpressionFunctionKibanaContext => ({
context: {
types: ['kibana_context', 'null'],
},
- help: i18n.translate('interpreter.functions.kibana_context.help', {
+ help: i18n.translate('expressions_np.functions.kibana_context.help', {
defaultMessage: 'Updates kibana global context',
}),
args: {
@@ -49,45 +50,43 @@ export const kibanaContext = (): ExpressionFunctionKibanaContext => ({
types: ['string', 'null'],
aliases: ['query', '_'],
default: null,
- help: i18n.translate('interpreter.functions.kibana_context.q.help', {
+ help: i18n.translate('expressions_np.functions.kibana_context.q.help', {
defaultMessage: 'Specify Kibana free form text query',
}),
},
filters: {
types: ['string', 'null'],
default: '"[]"',
- help: i18n.translate('interpreter.functions.kibana_context.filters.help', {
+ help: i18n.translate('expressions_np.functions.kibana_context.filters.help', {
defaultMessage: 'Specify Kibana generic filters',
}),
},
timeRange: {
types: ['string', 'null'],
default: null,
- help: i18n.translate('interpreter.functions.kibana_context.timeRange.help', {
+ help: i18n.translate('expressions_np.functions.kibana_context.timeRange.help', {
defaultMessage: 'Specify Kibana time range filter',
}),
},
savedSearchId: {
types: ['string', 'null'],
default: null,
- help: i18n.translate('interpreter.functions.kibana_context.savedSearchId.help', {
+ help: i18n.translate('expressions_np.functions.kibana_context.savedSearchId.help', {
defaultMessage: 'Specify saved search ID to be used for queries and filters',
}),
},
},
async fn(context, args, handlers) {
- const $injector = await chrome.dangerouslyGetActiveInjector();
- const savedSearches = $injector.get('savedSearches') as any;
const queryArg = args.q ? JSON.parse(args.q) : [];
let queries = Array.isArray(queryArg) ? queryArg : [queryArg];
let filters = args.filters ? JSON.parse(args.filters) : [];
if (args.savedSearchId) {
- const savedSearch = await savedSearches.get(args.savedSearchId);
- const searchQuery = savedSearch.searchSource.getField('query');
- const searchFilters = savedSearch.searchSource.getField('filter');
- queries = queries.concat(searchQuery);
- filters = filters.concat(searchFilters);
+ const obj = await savedObjects.get('search', args.savedSearchId);
+ const search = obj.attributes.kibanaSavedObjectMeta as { searchSourceJSON: string };
+ const data = JSON.parse(search.searchSourceJSON) as { query: string; filter: any[] };
+ queries = queries.concat(data.query);
+ filters = filters.concat(data.filter);
}
if (context && context.query) {
diff --git a/src/legacy/core_plugins/interpreter/public/functions/__snapshots__/kibana.test.ts.snap b/src/plugins/expressions/public/functions/tests/__snapshots__/kibana.test.ts.snap
similarity index 100%
rename from src/legacy/core_plugins/interpreter/public/functions/__snapshots__/kibana.test.ts.snap
rename to src/plugins/expressions/public/functions/tests/__snapshots__/kibana.test.ts.snap
diff --git a/src/legacy/core_plugins/interpreter/public/functions/font.test.ts b/src/plugins/expressions/public/functions/tests/font.test.ts
similarity index 97%
rename from src/legacy/core_plugins/interpreter/public/functions/font.test.ts
rename to src/plugins/expressions/public/functions/tests/font.test.ts
index 7032e042a59ea..a0397b920f905 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/font.test.ts
+++ b/src/plugins/expressions/public/functions/tests/font.test.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { openSans } from '../../common/lib/fonts';
-import { font } from './font';
-import { functionWrapper } from '../../test_helpers';
+import { openSans } from '../../fonts';
+import { font } from '../font';
+import { functionWrapper } from './utils';
describe('font', () => {
const fn = functionWrapper(font);
diff --git a/src/legacy/core_plugins/interpreter/public/functions/kibana.test.ts b/src/plugins/expressions/public/functions/tests/kibana.test.ts
similarity index 93%
rename from src/legacy/core_plugins/interpreter/public/functions/kibana.test.ts
rename to src/plugins/expressions/public/functions/tests/kibana.test.ts
index cd67825b534cd..d9489d724cc70 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/kibana.test.ts
+++ b/src/plugins/expressions/public/functions/tests/kibana.test.ts
@@ -17,9 +17,10 @@
* under the License.
*/
-import { functionWrapper } from '../../test_helpers';
-import { kibana } from './kibana';
-import { KibanaContext, FunctionHandlers } from '../../types';
+import { functionWrapper } from './utils';
+import { kibana } from '../kibana';
+import { FunctionHandlers } from '../../types';
+import { KibanaContext } from '../../expression_types';
describe('interpreter/functions#kibana', () => {
const fn = functionWrapper(kibana);
diff --git a/src/plugins/expressions/public/functions/tests/utils.ts b/src/plugins/expressions/public/functions/tests/utils.ts
new file mode 100644
index 0000000000000..5eb9c1a0d6390
--- /dev/null
+++ b/src/plugins/expressions/public/functions/tests/utils.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 { mapValues } from 'lodash';
+import { AnyExpressionFunction, FunctionHandlers } from '../../types';
+
+// Takes a function spec and passes in default args,
+// overriding with any provided args.
+export const functionWrapper = (fnSpec: () => T) => {
+ const spec = fnSpec();
+ const defaultArgs = mapValues(spec.args, argSpec => argSpec.default);
+ return (
+ context: object | null,
+ args: Record = {},
+ handlers: FunctionHandlers = {}
+ ) => spec.fn(context, { ...defaultArgs, ...args }, handlers);
+};
diff --git a/src/plugins/expressions/public/index.ts b/src/plugins/expressions/public/index.ts
index 21f89db140e5a..84ad2550fda0a 100644
--- a/src/plugins/expressions/public/index.ts
+++ b/src/plugins/expressions/public/index.ts
@@ -26,4 +26,9 @@ export function plugin(initializerContext: PluginInitializerContext) {
export { ExpressionsPublicPlugin as Plugin };
-export * from '../common';
+export * from './plugin';
+export * from './types';
+export { Type, getType } from './interpreter';
+export { interpreterProvider, ExpressionInterpret } from './interpreter_provider';
+export * from './serialize_provider';
+export * from './expression_types';
diff --git a/src/plugins/expressions/common/expressions/serialize_provider.test.ts b/src/plugins/expressions/public/interpreter.test.ts
similarity index 97%
rename from src/plugins/expressions/common/expressions/serialize_provider.test.ts
rename to src/plugins/expressions/public/interpreter.test.ts
index 774fb34938dd2..42443a2c32b82 100644
--- a/src/plugins/expressions/common/expressions/serialize_provider.test.ts
+++ b/src/plugins/expressions/public/interpreter.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { getType } from './serialize_provider';
+import { getType } from './interpreter';
describe('getType()', () => {
test('returns "null" string for null or undefined', () => {
diff --git a/src/plugins/expressions/common/expressions/interpreter.ts b/src/plugins/expressions/public/interpreter.ts
similarity index 50%
rename from src/plugins/expressions/common/expressions/interpreter.ts
rename to src/plugins/expressions/public/interpreter.ts
index 07146b6eb3181..13bf245f233cb 100644
--- a/src/plugins/expressions/common/expressions/interpreter.ts
+++ b/src/plugins/expressions/public/interpreter.ts
@@ -18,8 +18,10 @@
*/
import { get } from 'lodash';
+import { AnyExpressionType } from './types';
+import { ExpressionValue } from './types/types';
-function getType(node: any) {
+export function getType(node: any) {
if (node == null) return 'null';
if (typeof node === 'object') {
if (!node.type) throw new Error('Objects must have a type property');
@@ -28,30 +30,48 @@ function getType(node: any) {
return typeof node;
}
-export function Type(this: any, config: any) {
- // Required
- this.name = config.name;
+export class Type {
+ name: string;
- // Optional
- this.help = config.help || ''; // A short help text
+ /**
+ * A short help text.
+ */
+ help: string;
- // Optional type validation, useful for checking function output
- this.validate = config.validate || function validate() {};
+ /**
+ * Type validation, useful for checking function output.
+ */
+ validate: (type: any) => void | Error;
- // Optional
- this.create = config.create;
+ create: unknown;
- // Optional serialization (used when passing context around client/server)
- this.serialize = config.serialize;
- this.deserialize = config.deserialize;
+ /**
+ * Optional serialization (used when passing context around client/server).
+ */
+ serialize?: (value: ExpressionValue) => any;
+ deserialize?: (serialized: any) => ExpressionValue;
- const getToFn = (type: any) => get(config, ['to', type]) || get(config, ['to', '*']);
- const getFromFn = (type: any) => get(config, ['from', type]) || get(config, ['from', '*']);
+ constructor(private readonly config: AnyExpressionType) {
+ const { name, help, deserialize, serialize, validate } = config;
- this.castsTo = (type: any) => typeof getToFn(type) === 'function';
- this.castsFrom = (type: any) => typeof getFromFn(type) === 'function';
+ this.name = name;
+ this.help = help || '';
+ this.validate = validate || (() => {});
- this.to = (node: any, toTypeName: any, types: any) => {
+ // Optional
+ this.create = (config as any).create;
+
+ this.serialize = serialize;
+ this.deserialize = deserialize;
+ }
+
+ getToFn = (value: any) => get(this.config, ['to', value]) || get(this.config, ['to', '*']);
+ getFromFn = (value: any) => get(this.config, ['from', value]) || get(this.config, ['from', '*']);
+
+ castsTo = (value: any) => typeof this.getToFn(value) === 'function';
+ castsFrom = (value: any) => typeof this.getFromFn(value) === 'function';
+
+ to = (node: any, toTypeName: any, types: any) => {
const typeName = getType(node);
if (typeName !== this.name) {
throw new Error(`Can not cast object of type '${typeName}' using '${this.name}'`);
@@ -59,13 +79,13 @@ export function Type(this: any, config: any) {
throw new Error(`Can not cast '${typeName}' to '${toTypeName}'`);
}
- return (getToFn(toTypeName) as any)(node, types);
+ return (this.getToFn(toTypeName) as any)(node, types);
};
- this.from = (node: any, types: any) => {
+ from = (node: any, types: any) => {
const typeName = getType(node);
if (!this.castsFrom(typeName)) throw new Error(`Can not cast '${this.name}' from ${typeName}`);
- return (getFromFn(typeName) as any)(node, types);
+ return (this.getFromFn(typeName) as any)(node, types);
};
}
diff --git a/src/plugins/expressions/common/expressions/interpreter_provider.ts b/src/plugins/expressions/public/interpreter_provider.ts
similarity index 88%
rename from src/plugins/expressions/common/expressions/interpreter_provider.ts
rename to src/plugins/expressions/public/interpreter_provider.ts
index 59ba1085a9d7d..cb84370ad69c5 100644
--- a/src/plugins/expressions/common/expressions/interpreter_provider.ts
+++ b/src/plugins/expressions/public/interpreter_provider.ts
@@ -21,11 +21,11 @@
import { clone, each, keys, last, mapValues, reduce, zipObject } from 'lodash';
// @ts-ignore
-import { fromExpression, getByAlias, castProvider } from '@kbn/interpreter/common';
+import { fromExpression, getByAlias } from '@kbn/interpreter/common';
import { createError } from './create_error';
import { ExpressionAST, ExpressionFunctionAST, AnyExpressionFunction, ArgumentType } from './types';
-import { getType } from '../../common';
+import { getType } from './interpreter';
export { createError };
@@ -40,7 +40,30 @@ export type ExpressionInterpret = (ast: ExpressionAST, context?: any) => any;
export function interpreterProvider(config: InterpreterConfig): ExpressionInterpret {
const { functions, types } = config;
const handlers = { ...config.handlers, types };
- const cast = castProvider(types);
+
+ function cast(node: any, toTypeNames: any) {
+ // If you don't give us anything to cast to, you'll get your input back
+ if (!toTypeNames || toTypeNames.length === 0) return node;
+
+ // No need to cast if node is already one of the valid types
+ const fromTypeName = getType(node);
+ if (toTypeNames.includes(fromTypeName)) return node;
+
+ const fromTypeDef = types[fromTypeName];
+
+ for (let i = 0; i < toTypeNames.length; i++) {
+ // First check if the current type can cast to this type
+ if (fromTypeDef && fromTypeDef.castsTo(toTypeNames[i])) {
+ return fromTypeDef.to(node, toTypeNames[i], types);
+ }
+
+ // If that isn't possible, check if this type can cast from the current type
+ const toTypeDef = types[toTypeNames[i]];
+ if (toTypeDef && toTypeDef.castsFrom(fromTypeName)) return toTypeDef.from(node, types);
+ }
+
+ throw new Error(`Can not cast '${fromTypeName}' to any of '${toTypeNames.join(', ')}'`);
+ }
async function invokeChain(chainArr: ExpressionFunctionAST[], context: any): Promise {
if (!chainArr.length) return context;
diff --git a/src/plugins/expressions/public/mocks.ts b/src/plugins/expressions/public/mocks.ts
index 56ff343e70ac4..9b47aa2b0cd97 100644
--- a/src/plugins/expressions/public/mocks.ts
+++ b/src/plugins/expressions/public/mocks.ts
@@ -16,10 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Plugin } from '.';
+import { ExpressionsSetup, ExpressionsStart } from '.';
-export type Setup = jest.Mocked>;
-export type Start = jest.Mocked>;
+export type Setup = jest.Mocked;
+export type Start = jest.Mocked;
const createSetupContract = (): Setup => {
const setupContract: Setup = {
@@ -36,28 +36,18 @@ const createSetupContract = (): Setup => {
types: {
register: () => {},
} as any,
+ getExecutor: () => ({
+ interpreter: {
+ interpretAst: () => {},
+ },
+ }),
},
};
return setupContract;
};
const createStartContract = (): Start => {
- const startContract: Start = {
- registerFunction: jest.fn(),
- registerRenderer: jest.fn(),
- registerType: jest.fn(),
- __LEGACY: {
- functions: {
- register: () => {},
- } as any,
- renderers: {
- register: () => {},
- } as any,
- types: {
- register: () => {},
- } as any,
- },
- };
+ const startContract: Start = undefined;
return startContract;
};
diff --git a/src/plugins/expressions/public/plugin.ts b/src/plugins/expressions/public/plugin.ts
index b301981f58801..e67b503f301aa 100644
--- a/src/plugins/expressions/public/plugin.ts
+++ b/src/plugins/expressions/public/plugin.ts
@@ -19,29 +19,133 @@
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
import {
- ExpressionsService,
- ExpressionsSetupContract,
- ExpressionsStartContract,
-} from './expressions/expressions_service';
+ AnyExpressionFunction,
+ AnyExpressionType,
+ ExpressionInterpretWithHandlers,
+ ExpressionExecutor,
+} from './types';
+import { FunctionsRegistry, RenderFunctionsRegistry, TypesRegistry } from './registries';
+import { Setup as InspectorSetup, Start as InspectorStart } from '../../inspector/public';
+import { setCoreStart } from './services';
+import { clog as clogFunction } from './functions/clog';
+import { font as fontFunction } from './functions/font';
+import { kibana as kibanaFunction } from './functions/kibana';
+import { kibanaContext as kibanaContextFunction } from './functions/kibana_context';
+import {
+ boolean as booleanType,
+ datatable as datatableType,
+ error as errorType,
+ filter as filterType,
+ image as imageType,
+ nullType,
+ number as numberType,
+ pointseries,
+ range as rangeType,
+ render as renderType,
+ shape as shapeType,
+ string as stringType,
+ style as styleType,
+ kibanaContext as kibanaContextType,
+ kibanaDatatable as kibanaDatatableType,
+} from './expression_types';
+import { interpreterProvider } from './interpreter_provider';
+import { createHandlers } from './create_handlers';
+
+export interface ExpressionsSetupDeps {
+ inspector: InspectorSetup;
+}
+
+export interface ExpressionsStartDeps {
+ inspector: InspectorStart;
+}
+
+export interface ExpressionsSetup {
+ registerFunction: (fn: AnyExpressionFunction | (() => AnyExpressionFunction)) => void;
+ registerRenderer: (renderer: any) => void;
+ registerType: (type: () => AnyExpressionType) => void;
+ __LEGACY: {
+ functions: FunctionsRegistry;
+ renderers: RenderFunctionsRegistry;
+ types: TypesRegistry;
+ getExecutor: () => ExpressionExecutor;
+ };
+}
+
+export type ExpressionsStart = void;
export class ExpressionsPublicPlugin
- implements Plugin<{}, {}, ExpressionsSetupContract, ExpressionsStartContract> {
- private readonly expressions = new ExpressionsService();
+ implements
+ Plugin {
+ private readonly functions = new FunctionsRegistry();
+ private readonly renderers = new RenderFunctionsRegistry();
+ private readonly types = new TypesRegistry();
constructor(initializerContext: PluginInitializerContext) {}
- public setup(core: CoreSetup): ExpressionsSetupContract {
- const expressions = this.expressions.setup();
- return {
- ...expressions,
+ public setup(core: CoreSetup, { inspector }: ExpressionsSetupDeps): ExpressionsSetup {
+ const { functions, renderers, types } = this;
+
+ const registerFunction: ExpressionsSetup['registerFunction'] = fn => {
+ functions.register(fn);
+ };
+
+ registerFunction(clogFunction);
+ registerFunction(fontFunction);
+ registerFunction(kibanaFunction);
+ registerFunction(kibanaContextFunction);
+
+ types.register(booleanType);
+ types.register(datatableType);
+ types.register(errorType);
+ types.register(filterType);
+ types.register(imageType);
+ types.register(nullType);
+ types.register(numberType);
+ types.register(pointseries);
+ types.register(rangeType);
+ types.register(renderType);
+ types.register(shapeType);
+ types.register(stringType);
+ types.register(styleType);
+ types.register(kibanaContextType);
+ types.register(kibanaDatatableType);
+
+ // TODO: Refactor this function.
+ const getExecutor = () => {
+ const interpretAst: ExpressionInterpretWithHandlers = (ast, context, handlers) => {
+ const interpret = interpreterProvider({
+ types: types.toJS(),
+ handlers: { ...handlers, ...createHandlers() },
+ functions: functions.toJS(),
+ });
+ return interpret(ast, context);
+ };
+ const executor: ExpressionExecutor = { interpreter: { interpretAst } };
+ return executor;
};
- }
- public start(core: CoreStart): ExpressionsStartContract {
- const expressions = this.expressions.start();
- return {
- ...expressions,
+ const setup: ExpressionsSetup = {
+ registerFunction,
+ registerRenderer: (renderer: any) => {
+ renderers.register(renderer);
+ },
+ registerType: type => {
+ types.register(type);
+ },
+ __LEGACY: {
+ functions,
+ renderers,
+ types,
+ getExecutor,
+ },
};
+
+ return setup;
+ }
+
+ public start(core: CoreStart, { inspector }: ExpressionsStartDeps): ExpressionsStart {
+ setCoreStart(core);
}
+
public stop() {}
}
diff --git a/src/plugins/expressions/public/registries/function_registry.ts b/src/plugins/expressions/public/registries/function_registry.ts
new file mode 100644
index 0000000000000..c15b7ceb0d217
--- /dev/null
+++ b/src/plugins/expressions/public/registries/function_registry.ts
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+/* eslint-disable max-classes-per-file */
+
+import { AnyExpressionFunction, FunctionHandlers } from '../types/functions';
+import { ExpressionValue } from '../types/types';
+import { ArgumentType } from '../types';
+import { Registry } from './registry';
+
+export class FunctionParameter {
+ name: string;
+ required: boolean;
+ help: string;
+ types: string[];
+ default: any;
+ aliases: string[];
+ multi: boolean;
+ resolve: boolean;
+ options: any[];
+
+ constructor(name: string, arg: ArgumentType) {
+ const { required, help, types, aliases, multi, resolve, options } = arg;
+
+ if (name === '_') {
+ throw Error('Arg names must not be _. Use it in aliases instead.');
+ }
+
+ this.name = name;
+ this.required = !!required;
+ this.help = help || '';
+ this.types = types || [];
+ this.default = arg.default;
+ this.aliases = aliases || [];
+ this.multi = !!multi;
+ this.resolve = resolve == null ? true : resolve;
+ this.options = options || [];
+ }
+
+ accepts(type: string) {
+ if (!this.types.length) return true;
+ return this.types.indexOf(type) > -1;
+ }
+}
+
+export class Function {
+ /**
+ * Name of function
+ */
+ name: string;
+
+ /**
+ * Aliases that can be used instead of `name`.
+ */
+ aliases: string[];
+
+ /**
+ * Return type of function. This SHOULD be supplied. We use it for UI
+ * and autocomplete hinting. We may also use it for optimizations in
+ * the future.
+ */
+ type: string;
+
+ /**
+ * Function to run function (context, args)
+ */
+ fn: (
+ input: ExpressionValue,
+ params: Record,
+ handlers: FunctionHandlers
+ ) => ExpressionValue;
+
+ /**
+ * A short help text.
+ */
+ help: string;
+
+ args: Record = {};
+
+ context: { types?: string[] };
+
+ constructor(functionDefinition: AnyExpressionFunction) {
+ const { name, type, aliases, fn, help, args, context } = functionDefinition;
+
+ this.name = name;
+ this.type = type;
+ this.aliases = aliases || [];
+ this.fn = (input, params, handlers) => Promise.resolve(fn(input, params, handlers));
+ this.help = help || '';
+ this.context = context || {};
+
+ for (const [key, arg] of Object.entries(args || {})) {
+ this.args[key] = new FunctionParameter(key, arg);
+ }
+ }
+
+ accepts = (type: string): boolean => {
+ // If you don't tell us about context, we'll assume you don't care what you get.
+ if (!this.context.types) return true;
+ return this.context.types.indexOf(type) > -1;
+ };
+}
+
+export class FunctionsRegistry extends Registry {
+ register(functionDefinition: AnyExpressionFunction | (() => AnyExpressionFunction)) {
+ const fn = new Function(
+ typeof functionDefinition === 'object' ? functionDefinition : functionDefinition()
+ );
+ this.set(fn.name, fn);
+ }
+}
diff --git a/src/plugins/expressions/public/registries/index.ts b/src/plugins/expressions/public/registries/index.ts
new file mode 100644
index 0000000000000..16c8d8fc4c93a
--- /dev/null
+++ b/src/plugins/expressions/public/registries/index.ts
@@ -0,0 +1,22 @@
+/*
+ * 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 './type_registry';
+export * from './function_registry';
+export * from './render_registry';
diff --git a/src/plugins/expressions/public/registries/registry.ts b/src/plugins/expressions/public/registries/registry.ts
new file mode 100644
index 0000000000000..fe149116fbf14
--- /dev/null
+++ b/src/plugins/expressions/public/registries/registry.ts
@@ -0,0 +1,42 @@
+/*
+ * 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 class Registry {
+ private data: Record = {};
+
+ set(id: string, item: T) {
+ this.data[id] = item;
+ }
+
+ get(id: string): T | null {
+ return this.data[id] || null;
+ }
+
+ toJS(): Record {
+ return { ...this.data };
+ }
+
+ toArray(): T[] {
+ return Object.values(this.data);
+ }
+
+ reset() {
+ this.data = {};
+ }
+}
diff --git a/src/plugins/expressions/public/registries/render_registry.ts b/src/plugins/expressions/public/registries/render_registry.ts
new file mode 100644
index 0000000000000..6fd48f5f0c6af
--- /dev/null
+++ b/src/plugins/expressions/public/registries/render_registry.ts
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+/* eslint-disable max-classes-per-file */
+
+import { Registry } from './registry';
+
+export interface ExpressionRenderDefinition {
+ name: string;
+ displayName: string;
+ help?: string;
+ validate?: () => void | Error;
+ reuseDomNode: boolean;
+ render: (domNode: HTMLElement, config: Config, handlers: any) => Promise;
+}
+
+class ExpressionRenderFunction {
+ /**
+ * This must match the name of the function that is used to create the `type: render` object.
+ */
+ name: string;
+
+ /**
+ * Use this to set a more friendly name.
+ */
+ displayName: string;
+
+ /**
+ * A sentence or few about what this element does.
+ */
+ help: string;
+
+ /**
+ * Used to validate the data before calling the render function.
+ */
+ validate: () => void | Error;
+
+ /**
+ * Tell the renderer if the dom node should be reused, it's recreated each time by default.
+ */
+ reuseDomNode: boolean;
+
+ /**
+ * The function called to render the data.
+ */
+ render: (domNode: HTMLElement, config: any, handlers: any) => Promise;
+
+ constructor(config: ExpressionRenderDefinition) {
+ const { name, displayName, help, validate, reuseDomNode, render } = config;
+
+ this.name = name;
+ this.displayName = displayName || name;
+ this.help = help || '';
+ this.validate = validate || (() => {});
+ this.reuseDomNode = Boolean(reuseDomNode);
+ this.render = render;
+ }
+}
+
+export class RenderFunctionsRegistry extends Registry {
+ register(definition: ExpressionRenderDefinition | (() => ExpressionRenderDefinition)) {
+ const renderFunction = new ExpressionRenderFunction(
+ typeof definition === 'object' ? definition : definition()
+ );
+ this.set(renderFunction.name, renderFunction);
+ }
+}
diff --git a/src/plugins/expressions/public/registries/type_registry.ts b/src/plugins/expressions/public/registries/type_registry.ts
new file mode 100644
index 0000000000000..bcc801213582e
--- /dev/null
+++ b/src/plugins/expressions/public/registries/type_registry.ts
@@ -0,0 +1,29 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Registry } from './registry';
+import { Type } from '../interpreter';
+import { AnyExpressionType } from '../types';
+
+export class TypesRegistry extends Registry {
+ register(typeDefinition: AnyExpressionType | (() => AnyExpressionType)) {
+ const type = new Type(typeof typeDefinition === 'object' ? typeDefinition : typeDefinition());
+ this.set(type.name, type);
+ }
+}
diff --git a/src/plugins/expressions/common/expressions/serialize_provider.ts b/src/plugins/expressions/public/serialize_provider.ts
similarity index 84%
rename from src/plugins/expressions/common/expressions/serialize_provider.ts
rename to src/plugins/expressions/public/serialize_provider.ts
index 1bd06a38a2560..449d47c183dbb 100644
--- a/src/plugins/expressions/common/expressions/serialize_provider.ts
+++ b/src/plugins/expressions/public/serialize_provider.ts
@@ -18,15 +18,7 @@
*/
import { get, identity } from 'lodash';
-
-export function getType(node: any) {
- if (node == null) return 'null';
- if (typeof node === 'object') {
- if (!node.type) throw new Error('Objects must have a type property');
- return node.type;
- }
- return typeof node;
-}
+import { getType } from './interpreter';
export function serializeProvider(types: any) {
return {
diff --git a/src/legacy/core_plugins/data/public/shim/legacy_dependencies_plugin.ts b/src/plugins/expressions/public/services.ts
similarity index 54%
rename from src/legacy/core_plugins/data/public/shim/legacy_dependencies_plugin.ts
rename to src/plugins/expressions/public/services.ts
index 83d276fe9ba74..a1a42aa85e670 100644
--- a/src/legacy/core_plugins/data/public/shim/legacy_dependencies_plugin.ts
+++ b/src/plugins/expressions/public/services.ts
@@ -17,28 +17,19 @@
* under the License.
*/
-import { Storage } from 'ui/storage';
-import { Plugin } from '../../../../../../src/core/public';
+import { createKibanaUtilsCore, createGetterSetter } from '../../kibana_utils/public';
+import { ExpressionInterpreter } from './types';
+import { Start as IInspector } from '../../inspector/public';
+import { ExpressionsSetup } from './plugin';
-/** @internal */
-export interface LegacyDependenciesPluginSetup {
- storage: Storage;
-}
+export const { getCoreStart, setCoreStart, savedObjects } = createKibanaUtilsCore();
-export interface LegacyDependenciesPluginStart {
- storage: Storage;
-}
+export const [getInspector, setInspector] = createGetterSetter('Inspector');
-export class LegacyDependenciesPlugin implements Plugin {
- public setup() {
- return {
- storage: new Storage(window.localStorage),
- } as LegacyDependenciesPluginSetup;
- }
+export const [getInterpreter, setInterpreter] = createGetterSetter(
+ 'Interpreter'
+);
- public start() {
- return {
- storage: new Storage(window.localStorage),
- } as LegacyDependenciesPluginStart;
- }
-}
+export const [getRenderersRegistry, setRenderersRegistry] = createGetterSetter<
+ ExpressionsSetup['__LEGACY']['renderers']
+>('Renderers registry');
diff --git a/src/plugins/expressions/common/expressions/types/arguments.ts b/src/plugins/expressions/public/types/arguments.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/types/arguments.ts
rename to src/plugins/expressions/public/types/arguments.ts
diff --git a/src/plugins/expressions/common/expressions/types/common.ts b/src/plugins/expressions/public/types/common.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/types/common.ts
rename to src/plugins/expressions/public/types/common.ts
diff --git a/src/plugins/expressions/common/expressions/types/functions.ts b/src/plugins/expressions/public/types/functions.ts
similarity index 100%
rename from src/plugins/expressions/common/expressions/types/functions.ts
rename to src/plugins/expressions/public/types/functions.ts
diff --git a/src/plugins/expressions/public/types/index.ts b/src/plugins/expressions/public/types/index.ts
new file mode 100644
index 0000000000000..2d66216a9770b
--- /dev/null
+++ b/src/plugins/expressions/public/types/index.ts
@@ -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 { ExpressionInterpret } from '../interpreter_provider';
+import { TimeRange } from '../../../data/public';
+import { Adapters } from '../../../inspector/public';
+import { Query } from '../../../data/public';
+import { ExpressionAST } from '../../../expressions/public';
+import { ExpressionArgAST } from '../../../../plugins/expressions/public';
+import { esFilters } from '../../../../plugins/data/public';
+
+export { ArgumentType } from './arguments';
+export {
+ TypeToString,
+ KnownTypeToString,
+ TypeString,
+ UnmappedTypeStrings,
+ UnwrapPromise,
+ SerializedFieldFormat,
+} from './common';
+
+export { ExpressionFunction, AnyExpressionFunction, FunctionHandlers } from './functions';
+export { ExpressionType, AnyExpressionType } from './types';
+
+export * from './style';
+
+export type ExpressionArgAST = string | boolean | number | ExpressionAST;
+
+export interface ExpressionFunctionAST {
+ type: 'function';
+ function: string;
+ arguments: {
+ [key: string]: ExpressionArgAST[];
+ };
+}
+
+export interface ExpressionAST {
+ type: 'expression';
+ chain: ExpressionFunctionAST[];
+}
+
+export type ExpressionInterpretWithHandlers = (
+ ast: Parameters[0],
+ context: Parameters[1],
+ handlers: IInterpreterHandlers
+) => ReturnType;
+
+export interface ExpressionInterpreter {
+ interpretAst: ExpressionInterpretWithHandlers;
+}
+
+export interface ExpressionExecutor {
+ interpreter: ExpressionInterpreter;
+}
+
+export type RenderId = number;
+export type Data = any;
+export type event = any;
+export type Context = object;
+
+export interface SearchContext {
+ type: 'kibana_context';
+ filters?: esFilters.Filter[];
+ query?: Query;
+ timeRange?: TimeRange;
+}
+
+export type IGetInitialContext = () => SearchContext | Context;
+
+export interface IExpressionLoaderParams {
+ searchContext?: SearchContext;
+ context?: Context;
+ variables?: Record;
+ disableCaching?: boolean;
+ customFunctions?: [];
+ customRenderers?: [];
+ extraHandlers?: Record;
+}
+
+export interface IInterpreterHandlers {
+ getInitialContext: IGetInitialContext;
+ inspectorAdapters?: Adapters;
+ abortSignal?: AbortSignal;
+}
+
+export interface IInterpreterRenderHandlers {
+ /**
+ * Done increments the number of rendering successes
+ */
+ done: () => void;
+ onDestroy: (fn: () => void) => void;
+ reload: () => void;
+ update: (params: any) => void;
+ event: (event: event) => void;
+}
+
+export interface IInterpreterRenderFunction {
+ name: string;
+ displayName: string;
+ help: string;
+ validate: () => void;
+ reuseDomNode: boolean;
+ render: (domNode: Element, data: T, handlers: IInterpreterRenderHandlers) => void | Promise;
+}
+
+export interface IInterpreterErrorResult {
+ type: 'error';
+ error: { message: string; name: string; stack: string };
+}
+
+export interface IInterpreterSuccessResult {
+ type: string;
+ as?: string;
+ value?: unknown;
+ error?: unknown;
+}
+
+export type IInterpreterResult = IInterpreterSuccessResult & IInterpreterErrorResult;
+
+export interface IInterpreter {
+ interpretAst(
+ ast: ExpressionAST,
+ context: Context,
+ handlers: IInterpreterHandlers
+ ): Promise;
+}
diff --git a/src/plugins/expressions/public/types/style.ts b/src/plugins/expressions/public/types/style.ts
new file mode 100644
index 0000000000000..9f919223d558c
--- /dev/null
+++ b/src/plugins/expressions/public/types/style.ts
@@ -0,0 +1,137 @@
+/*
+ * 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 { FontLabel } from '../fonts';
+
+/**
+ * Enum of supported CSS `background-repeat` properties.
+ */
+export enum BackgroundRepeat {
+ REPEAT = 'repeat',
+ REPEAT_NO = 'no-repeat',
+ REPEAT_X = 'repeat-x',
+ REPEAT_Y = 'repeat-y',
+ ROUND = 'round',
+ SPACE = 'space',
+}
+
+/**
+ * Enum of supported CSS `background-size` properties.
+ */
+export enum BackgroundSize {
+ AUTO = 'auto',
+ CONTAIN = 'contain',
+ COVER = 'cover',
+}
+
+/**
+ * Enum of supported CSS `font-style` properties.
+ */
+export enum FontStyle {
+ ITALIC = 'italic',
+ NORMAL = 'normal',
+}
+
+/**
+ * Enum of supported CSS `font-weight` properties.
+ */
+export enum FontWeight {
+ NORMAL = 'normal',
+ BOLD = 'bold',
+ BOLDER = 'bolder',
+ LIGHTER = 'lighter',
+ ONE = '100',
+ TWO = '200',
+ THREE = '300',
+ FOUR = '400',
+ FIVE = '500',
+ SIX = '600',
+ SEVEN = '700',
+ EIGHT = '800',
+ NINE = '900',
+}
+
+/**
+ * Enum of supported CSS `overflow` properties.
+ */
+export enum Overflow {
+ AUTO = 'auto',
+ HIDDEN = 'hidden',
+ SCROLL = 'scroll',
+ VISIBLE = 'visible',
+}
+
+/**
+ * Enum of supported CSS `text-align` properties.
+ */
+export enum TextAlignment {
+ CENTER = 'center',
+ JUSTIFY = 'justify',
+ LEFT = 'left',
+ RIGHT = 'right',
+}
+
+/**
+ * Enum of supported CSS `text-decoration` properties.
+ */
+export enum TextDecoration {
+ NONE = 'none',
+ UNDERLINE = 'underline',
+}
+
+/**
+ * Represents the various style properties that can be applied to an element.
+ */
+export interface CSSStyle {
+ color?: string;
+ fill?: string;
+ fontFamily?: FontLabel;
+ fontSize?: string;
+ fontStyle?: FontStyle;
+ fontWeight?: FontWeight;
+ lineHeight?: number | string;
+ textAlign?: TextAlignment;
+ textDecoration?: TextDecoration;
+}
+
+/**
+ * Represents an object containing style information for a Container.
+ */
+export interface ContainerStyle {
+ border: string | null;
+ borderRadius: string | null;
+ padding: string | null;
+ backgroundColor: string | null;
+ backgroundImage: string | null;
+ backgroundSize: BackgroundSize;
+ backgroundRepeat: BackgroundRepeat;
+ opacity: number | null;
+ overflow: Overflow;
+}
+
+/**
+ * An object that represents style information, typically CSS.
+ */
+export interface ExpressionTypeStyle {
+ type: 'style';
+ spec: CSSStyle;
+ css: string;
+}
+
+export type Style = ExpressionTypeStyle;
diff --git a/src/plugins/expressions/common/expressions/types/types.ts b/src/plugins/expressions/public/types/types.ts
similarity index 99%
rename from src/plugins/expressions/common/expressions/types/types.ts
rename to src/plugins/expressions/public/types/types.ts
index 59297e922d313..e7b30d24fa6eb 100644
--- a/src/plugins/expressions/common/expressions/types/types.ts
+++ b/src/plugins/expressions/public/types/types.ts
@@ -51,6 +51,7 @@ export interface ExpressionType<
to?: {
[type: string]: ExpressionValueConverter;
};
+ help?: string;
}
export type AnyExpressionType = ExpressionType;
diff --git a/src/plugins/kibana_react/public/context/context.test.tsx b/src/plugins/kibana_react/public/context/context.test.tsx
index d7dce3f69239d..4008daf69f25d 100644
--- a/src/plugins/kibana_react/public/context/context.test.tsx
+++ b/src/plugins/kibana_react/public/context/context.test.tsx
@@ -21,7 +21,7 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { context, createKibanaReactContext, useKibana, KibanaContextProvider } from './context';
import { coreMock, overlayServiceMock } from '../../../../core/public/mocks';
-import { CoreStart } from './types';
+import { CoreStart } from '../../../../core/public';
let container: HTMLDivElement | null;
diff --git a/src/plugins/kibana_react/public/context/context.tsx b/src/plugins/kibana_react/public/context/context.tsx
index 630348017106a..cbae5c4638ca2 100644
--- a/src/plugins/kibana_react/public/context/context.tsx
+++ b/src/plugins/kibana_react/public/context/context.tsx
@@ -42,11 +42,11 @@ export const useKibana = (): KibanaReactContextValue<
export const withKibana = }>(
type: React.ComponentType
): React.FC> => {
- const enhancedType: React.FC> = (props: Omit) => {
+ const EnhancedType: React.FC> = (props: Omit) => {
const kibana = useKibana();
return React.createElement(type, { ...props, kibana } as Props);
};
- return enhancedType;
+ return EnhancedType;
};
export const UseKibana: React.FC<{
@@ -69,7 +69,7 @@ export const createKibanaReactContext = (
const oldValue = useKibana();
const { value: newValue } = useMemo(
() => createKibanaReactContext({ ...services, ...oldValue.services, ...newServices }),
- Object.keys(services)
+ [services, oldValue, newServices]
);
return createElement(context.Provider as React.ComponentType, {
value: newValue,
diff --git a/src/plugins/kibana_react/public/context/index.ts b/src/plugins/kibana_react/public/context/index.ts
index 444ef343cd7d2..c7c0693a89f2b 100644
--- a/src/plugins/kibana_react/public/context/index.ts
+++ b/src/plugins/kibana_react/public/context/index.ts
@@ -25,4 +25,4 @@ export {
withKibana,
UseKibana,
} from './context';
-export { KibanaReactContext, KibanaReactContextValue } from './types';
+export { KibanaReactContext, KibanaReactContextValue, KibanaServices } from './types';
diff --git a/src/plugins/kibana_react/public/context/types.ts b/src/plugins/kibana_react/public/context/types.ts
index 1906bb808ea87..35e6349bfca87 100644
--- a/src/plugins/kibana_react/public/context/types.ts
+++ b/src/plugins/kibana_react/public/context/types.ts
@@ -22,8 +22,6 @@ import { CoreStart } from '../../../../core/public';
import { KibanaReactOverlays } from '../overlays';
import { KibanaReactNotifications } from '../notifications';
-export { CoreStart };
-
export type KibanaServices = Partial;
export interface KibanaReactContextValue {
diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx b/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx
index 81d514ca4d466..a880d3c6cf87c 100644
--- a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx
+++ b/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx
@@ -24,11 +24,11 @@ import { EuiScreenReaderOnly, keyCodes } from '@elastic/eui';
// @ts-ignore
import { KuiButton } from '@kbn/ui-framework/components';
-interface Props {
+export interface ExitFullScreenButtonProps {
onExitFullScreenMode: () => void;
}
-class ExitFullScreenButtonUi extends PureComponent {
+class ExitFullScreenButtonUi extends PureComponent {
public onKeyDown = (e: KeyboardEvent) => {
if (e.keyCode === keyCodes.ESCAPE) {
this.props.onExitFullScreenMode();
diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/index.tsx b/src/plugins/kibana_react/public/exit_full_screen_button/index.tsx
index a965fd776e0c2..130ac1e980eee 100644
--- a/src/plugins/kibana_react/public/exit_full_screen_button/index.tsx
+++ b/src/plugins/kibana_react/public/exit_full_screen_button/index.tsx
@@ -17,4 +17,4 @@
* under the License.
*/
-export { ExitFullScreenButton } from './exit_full_screen_button';
+export { ExitFullScreenButton, ExitFullScreenButtonProps } from './exit_full_screen_button';
diff --git a/src/plugins/kibana_react/public/overlays/types.ts b/src/plugins/kibana_react/public/overlays/types.ts
index 6a1fb25ca1483..0108d8eaba6cc 100644
--- a/src/plugins/kibana_react/public/overlays/types.ts
+++ b/src/plugins/kibana_react/public/overlays/types.ts
@@ -18,7 +18,7 @@
*/
import * as React from 'react';
-import { CoreStart } from '../context/types';
+import { CoreStart } from '../../../../core/public';
export interface KibanaReactOverlays {
openFlyout: (
diff --git a/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx b/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx
index fbea5d613f60c..c65d428958767 100644
--- a/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx
+++ b/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx
@@ -104,7 +104,7 @@ interface SavedObjectFinderInitialPageSize extends BaseSavedObjectFinder {
initialPageSize?: 5 | 10 | 15 | 25;
fixedPageSize?: undefined;
}
-type SavedObjectFinderProps = {
+export type SavedObjectFinderProps = {
savedObjects: CoreStart['savedObjects'];
uiSettings: CoreStart['uiSettings'];
} & (SavedObjectFinderFixedPage | SavedObjectFinderInitialPageSize);
diff --git a/src/plugins/kibana_react/public/ui_settings/use_ui_setting.test.tsx b/src/plugins/kibana_react/public/ui_settings/use_ui_setting.test.tsx
index cc2a8c3fbe1fc..0879b0cb3f36a 100644
--- a/src/plugins/kibana_react/public/ui_settings/use_ui_setting.test.tsx
+++ b/src/plugins/kibana_react/public/ui_settings/use_ui_setting.test.tsx
@@ -106,7 +106,7 @@ describe('useUiSetting', () => {
});
describe('useUiSetting$', () => {
- const TestConsumer$: React.FC<{
+ const TestConsumerX: React.FC<{
setting: string;
newValue?: string;
}> = ({ setting, newValue = '' }) => {
@@ -126,7 +126,7 @@ describe('useUiSetting$', () => {
ReactDOM.render(
-
+
,
container
);
@@ -143,7 +143,7 @@ describe('useUiSetting$', () => {
ReactDOM.render(
-
+
,
container
);
@@ -159,7 +159,7 @@ describe('useUiSetting$', () => {
ReactDOM.render(
-
+
,
container
);
@@ -174,7 +174,7 @@ describe('useUiSetting$', () => {
ReactDOM.render(
-
+
,
container
);
diff --git a/src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts b/src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts
index ddc8b2a684728..295515bfa51af 100644
--- a/src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts
+++ b/src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts
@@ -65,6 +65,7 @@ export const useUiSetting$ = (key: string, defaultValue?: T): [T, Setter]
const observable$ = useMemo(() => services.uiSettings!.get$(key, defaultValue), [
key,
defaultValue,
+ services.uiSettings,
]);
const value = useObservable(observable$, services.uiSettings!.get(key, defaultValue));
const set = useCallback((newValue: T) => services.uiSettings!.set(key, newValue), [key]);
diff --git a/src/plugins/kibana_utils/public/index.ts b/src/plugins/kibana_utils/public/index.ts
index 7cb4d4a34e971..3aaa6d28a9f64 100644
--- a/src/plugins/kibana_utils/public/index.ts
+++ b/src/plugins/kibana_utils/public/index.ts
@@ -18,8 +18,11 @@
*/
export * from './core';
+export * from './errors';
export * from './store';
export * from './parse';
export * from './render_complete';
+export * from './store';
export * from './errors';
export * from './field_mapping';
+export * from './storage';
diff --git a/src/legacy/ui/public/storage/__tests__/storage.js b/src/plugins/kibana_utils/public/storage/__tests__/storage.js
similarity index 100%
rename from src/legacy/ui/public/storage/__tests__/storage.js
rename to src/plugins/kibana_utils/public/storage/__tests__/storage.js
diff --git a/src/legacy/ui/public/storage/index.ts b/src/plugins/kibana_utils/public/storage/index.ts
similarity index 94%
rename from src/legacy/ui/public/storage/index.ts
rename to src/plugins/kibana_utils/public/storage/index.ts
index 17bbb61b2b8d5..53956bf21cdf3 100644
--- a/src/legacy/ui/public/storage/index.ts
+++ b/src/plugins/kibana_utils/public/storage/index.ts
@@ -17,6 +17,5 @@
* under the License.
*/
-import './directive';
-
export { Storage } from './storage';
+export { IStorage, IStorageWrapper } from './types';
diff --git a/src/legacy/ui/public/storage/storage.ts b/src/plugins/kibana_utils/public/storage/storage.ts
similarity index 73%
rename from src/legacy/ui/public/storage/storage.ts
rename to src/plugins/kibana_utils/public/storage/storage.ts
index 703886c1e034c..a7d3c5ac70074 100644
--- a/src/legacy/ui/public/storage/storage.ts
+++ b/src/plugins/kibana_utils/public/storage/storage.ts
@@ -17,17 +17,12 @@
* under the License.
*/
-import angular from 'angular';
+import { IStorage, IStorageWrapper } from './types';
-// This is really silly, but I wasn't prepared to rename the kibana Storage class everywhere it is used
-// and this is the only way I could figure out how to use the type definition for a built in object
-// in a file that creates a type with the same name as that built in object.
-import { WebStorage } from './web_storage';
+export class Storage implements IStorageWrapper {
+ public store: IStorage;
-export class Storage {
- public store: WebStorage;
-
- constructor(store: WebStorage) {
+ constructor(store: IStorage) {
this.store = store;
}
@@ -50,7 +45,7 @@ export class Storage {
public set = (key: string, value: any) => {
try {
- return this.store.setItem(key, angular.toJson(value));
+ return this.store.setItem(key, JSON.stringify(value));
} catch (e) {
return false;
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_index_pattern.ts b/src/plugins/kibana_utils/public/storage/types.ts
similarity index 71%
rename from src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_index_pattern.ts
rename to src/plugins/kibana_utils/public/storage/types.ts
index d429fc7f70f38..875bb44bcad17 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_index_pattern.ts
+++ b/src/plugins/kibana_utils/public/storage/types.ts
@@ -17,12 +17,16 @@
* under the License.
*/
-export class StubIndexPatterns {
- async get(index: string) {
- return {
- fields: {
- getByName: () => undefined,
- },
- };
- }
+export interface IStorageWrapper {
+ get: (key: string) => any;
+ set: (key: string, value: any) => void;
+ remove: (key: string) => any;
+ clear: () => void;
+}
+
+export interface IStorage {
+ getItem: (key: string) => any;
+ setItem: (key: string, value: any) => void;
+ removeItem: (key: string) => any;
+ clear: () => void;
}
diff --git a/src/plugins/kibana_utils/public/store/react.ts b/src/plugins/kibana_utils/public/store/react.ts
index d561f9bb3cf34..00861b2b0b8fe 100644
--- a/src/plugins/kibana_utils/public/store/react.ts
+++ b/src/plugins/kibana_utils/public/store/react.ts
@@ -86,10 +86,12 @@ export const createContext = <
comparator?: Comparator
): Result => {
const { state$, get } = useStore();
+ /* eslint-disable react-hooks/exhaustive-deps */
const [observable$, unsubscribe] = useMemo(
() => observableSelector(get(), state$, selector, comparator),
[state$]
);
+ /* eslint-enable react-hooks/exhaustive-deps */
useLayoutEffect(() => unsubscribe, [observable$, unsubscribe]);
const value = useObservable(observable$, selector(get()));
return value;
diff --git a/src/plugins/visualizations/kibana.json b/src/plugins/visualizations/kibana.json
new file mode 100644
index 0000000000000..cf79ce17293d6
--- /dev/null
+++ b/src/plugins/visualizations/kibana.json
@@ -0,0 +1,9 @@
+{
+ "id": "visualizations",
+ "version": "kibana",
+ "server": false,
+ "ui": true,
+ "requiredPlugins": [
+ "expressions"
+ ]
+}
diff --git a/src/plugins/visualizations/public/expression_functions/range.ts b/src/plugins/visualizations/public/expression_functions/range.ts
new file mode 100644
index 0000000000000..27c3654e2182a
--- /dev/null
+++ b/src/plugins/visualizations/public/expression_functions/range.ts
@@ -0,0 +1,61 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { ExpressionFunction, KibanaDatatable, Range } from '../../../expressions/public';
+
+const name = 'range';
+
+type Context = KibanaDatatable | null;
+
+interface Arguments {
+ from: number;
+ to: number;
+}
+
+export const range = (): ExpressionFunction => ({
+ name,
+ help: i18n.translate('visualizations.function.range.help', {
+ defaultMessage: 'Generates range object',
+ }),
+ type: 'range',
+ args: {
+ from: {
+ types: ['number'],
+ help: i18n.translate('visualizations.function.range.from.help', {
+ defaultMessage: 'Start of range',
+ }),
+ required: true,
+ },
+ to: {
+ types: ['number'],
+ help: i18n.translate('visualizations.function.range.to.help', {
+ defaultMessage: 'End of range',
+ }),
+ required: true,
+ },
+ },
+ fn: (context, args) => {
+ return {
+ type: 'range',
+ from: args.from,
+ to: args.to,
+ };
+ },
+});
diff --git a/src/plugins/visualizations/public/expression_functions/vis_dimension.ts b/src/plugins/visualizations/public/expression_functions/vis_dimension.ts
new file mode 100644
index 0000000000000..4ad73ef504874
--- /dev/null
+++ b/src/plugins/visualizations/public/expression_functions/vis_dimension.ts
@@ -0,0 +1,89 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { ExpressionFunction, KibanaDatatable } from '../../../expressions/public';
+
+const name = 'visdimension';
+
+type Context = KibanaDatatable | null;
+
+interface Arguments {
+ accessor: string | number;
+ format?: string;
+ formatParams?: string;
+}
+
+type Return = any;
+
+export const visDimension = (): ExpressionFunction => ({
+ name: 'visdimension',
+ help: i18n.translate('visualizations.function.visDimension.help', {
+ defaultMessage: 'Generates visConfig dimension object',
+ }),
+ type: 'vis_dimension',
+ context: {
+ types: ['kibana_datatable'],
+ },
+ args: {
+ accessor: {
+ types: ['string', 'number'],
+ aliases: ['_'],
+ help: i18n.translate('visualizations.function.visDimension.accessor.help', {
+ defaultMessage: 'Column in your dataset to use (either column index or column name)',
+ }),
+ },
+ format: {
+ types: ['string'],
+ default: 'string',
+ help: i18n.translate('visualizations.function.visDimension.format.help', {
+ defaultMessage: 'Format',
+ }),
+ },
+ formatParams: {
+ types: ['string'],
+ default: '"{}"',
+ help: i18n.translate('visualizations.function.visDimension.formatParams.help', {
+ defaultMessage: 'Format params',
+ }),
+ },
+ },
+ fn: (context, args) => {
+ const accessor =
+ typeof args.accessor === 'number'
+ ? args.accessor
+ : context!.columns.find(c => c.id === args.accessor);
+ if (accessor === undefined) {
+ throw new Error(
+ i18n.translate('visualizations.function.visDimension.error.accessor', {
+ defaultMessage: 'Column name provided is invalid',
+ })
+ );
+ }
+
+ return {
+ type: 'vis_dimension',
+ accessor,
+ format: {
+ id: args.format,
+ params: JSON.parse(args.formatParams!),
+ },
+ };
+ },
+});
diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts
index d8f7b5091eb8f..2b4b10c8329a3 100644
--- a/src/plugins/visualizations/public/index.ts
+++ b/src/plugins/visualizations/public/index.ts
@@ -17,4 +17,13 @@
* under the License.
*/
+import { PluginInitializerContext } from '../../../core/public';
+import { VisualizationsPublicPlugin } from './plugin';
+
+export function plugin(initializerContext: PluginInitializerContext) {
+ return new VisualizationsPublicPlugin(initializerContext);
+}
+
+export { VisualizationsPublicPlugin as Plugin };
+export * from './plugin';
export * from './types';
diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts
new file mode 100644
index 0000000000000..af7688d019f65
--- /dev/null
+++ b/src/plugins/visualizations/public/mocks.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 { VisualizationsSetup, VisualizationsStart } from '.';
+
+export type Setup = jest.Mocked;
+export type Start = jest.Mocked;
+
+const createSetupContract = (): Setup => {
+ const setupContract: Setup = undefined;
+ return setupContract;
+};
+
+const createStartContract = (): Start => {
+ const startContract: Start = undefined;
+ return startContract;
+};
+
+export const expressionsPluginMock = {
+ createSetupContract,
+ createStartContract,
+};
diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts
new file mode 100644
index 0000000000000..cceb63122820d
--- /dev/null
+++ b/src/plugins/visualizations/public/plugin.ts
@@ -0,0 +1,59 @@
+/*
+ * 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 { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
+import { ExpressionsSetup, ExpressionsStart } from '../../expressions/public';
+import { range as rangeExpressionFunction } from './expression_functions/range';
+import { visDimension as visDimensionExpressionFunction } from './expression_functions/vis_dimension';
+
+export interface VisualizationsSetupDeps {
+ expressions: ExpressionsSetup;
+}
+
+export interface VisualizationsStartDeps {
+ expressions: ExpressionsStart;
+}
+
+export type VisualizationsSetup = void;
+
+export type VisualizationsStart = void;
+
+export class VisualizationsPublicPlugin
+ implements
+ Plugin<
+ VisualizationsSetup,
+ VisualizationsStart,
+ VisualizationsSetupDeps,
+ VisualizationsStartDeps
+ > {
+ constructor(initializerContext: PluginInitializerContext) {}
+
+ public setup(core: CoreSetup, { expressions }: VisualizationsSetupDeps): VisualizationsSetup {
+ expressions.registerFunction(rangeExpressionFunction);
+ expressions.registerFunction(visDimensionExpressionFunction);
+
+ return undefined;
+ }
+
+ public start(core: CoreStart, { expressions }: VisualizationsStartDeps): VisualizationsStart {
+ return undefined;
+ }
+
+ public stop() {}
+}
diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts
new file mode 100644
index 0000000000000..e3f73ad4bcaf8
--- /dev/null
+++ b/test/accessibility/apps/discover.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 { FtrProviderContext } from '../ftr_provider_context';
+
+const FROM_TIME = '2015-09-19 06:31:44.000';
+const TO_TIME = '2015-09-23 18:31:44.000';
+
+export default function({ getService, getPageObjects }: FtrProviderContext) {
+ const PageObjects = getPageObjects(['common', 'timePicker']);
+ const a11y = getService('a11y');
+ const esArchiver = getService('esArchiver');
+ const kibanaServer = getService('kibanaServer');
+
+ describe('Discover', () => {
+ before(async () => {
+ await esArchiver.load('discover');
+ await esArchiver.loadIfNeeded('logstash_functional');
+ await kibanaServer.uiSettings.update({
+ defaultIndex: 'logstash-*',
+ });
+ await PageObjects.common.navigateToApp('discover');
+ await PageObjects.timePicker.setAbsoluteRange(FROM_TIME, TO_TIME);
+ });
+
+ it('main view', async () => {
+ await a11y.testAppSnapshot();
+ });
+ });
+}
diff --git a/test/accessibility/apps/home.ts b/test/accessibility/apps/home.ts
new file mode 100644
index 0000000000000..4df4d5f42c93d
--- /dev/null
+++ b/test/accessibility/apps/home.ts
@@ -0,0 +1,35 @@
+/*
+ * 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 { FtrProviderContext } from '../ftr_provider_context';
+
+export default function({ getService, getPageObjects }: FtrProviderContext) {
+ const PageObjects = getPageObjects(['common']);
+ const a11y = getService('a11y');
+
+ describe('Kibana Home', () => {
+ before(async () => {
+ await PageObjects.common.navigateToApp('home');
+ });
+
+ it('Kibana Home view', async () => {
+ await a11y.testAppSnapshot();
+ });
+ });
+}
diff --git a/test/accessibility/apps/management.ts b/test/accessibility/apps/management.ts
new file mode 100644
index 0000000000000..842f4ecbafa9e
--- /dev/null
+++ b/test/accessibility/apps/management.ts
@@ -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 { FtrProviderContext } from '../ftr_provider_context';
+
+export default function({ getService, getPageObjects }: FtrProviderContext) {
+ const PageObjects = getPageObjects(['common', 'settings']);
+ const a11y = getService('a11y');
+
+ describe('Management', () => {
+ before(async () => {
+ await PageObjects.common.navigateToApp('settings');
+ });
+
+ it('main view', async () => {
+ await a11y.testAppSnapshot();
+ });
+
+ it('index pattern page', async () => {
+ await PageObjects.settings.clickKibanaIndexPatterns();
+ await a11y.testAppSnapshot();
+ });
+
+ it('Single indexpattern view', async () => {
+ await PageObjects.settings.clickIndexPatternLogstash();
+ await a11y.testAppSnapshot();
+ });
+
+ it('Saved objects view', async () => {
+ await PageObjects.settings.clickKibanaSavedObjects();
+ await a11y.testAppSnapshot();
+ });
+
+ it('Advanced settings', async () => {
+ await PageObjects.settings.clickKibanaSettings();
+ await a11y.testAppSnapshot();
+ });
+ });
+}
diff --git a/test/accessibility/config.ts b/test/accessibility/config.ts
new file mode 100644
index 0000000000000..d73a73820a117
--- /dev/null
+++ b/test/accessibility/config.ts
@@ -0,0 +1,42 @@
+/*
+ * 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 { FtrConfigProviderContext } from '@kbn/test/types/ftr';
+import { services } from './services';
+import { pageObjects } from './page_objects';
+
+export default async function({ readConfigFile }: FtrConfigProviderContext) {
+ const functionalConfig = await readConfigFile(require.resolve('../functional/config'));
+
+ return {
+ ...functionalConfig.getAll(),
+
+ testFiles: [
+ require.resolve('./apps/discover'),
+ require.resolve('./apps/management'),
+ require.resolve('./apps/home'),
+ ],
+ pageObjects,
+ services,
+
+ junit: {
+ reportName: 'Accessibility Tests',
+ },
+ };
+}
diff --git a/test/accessibility/ftr_provider_context.d.ts b/test/accessibility/ftr_provider_context.d.ts
new file mode 100644
index 0000000000000..22df3b16150a4
--- /dev/null
+++ b/test/accessibility/ftr_provider_context.d.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.
+ */
+
+import { GenericFtrProviderContext } from '@kbn/test/types/ftr';
+
+import { pageObjects } from './page_objects';
+import { services } from './services';
+
+export type FtrProviderContext = GenericFtrProviderContext;
diff --git a/test/accessibility/page_objects.ts b/test/accessibility/page_objects.ts
new file mode 100644
index 0000000000000..151b6b34781b8
--- /dev/null
+++ b/test/accessibility/page_objects.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 { pageObjects } from '../functional/page_objects';
diff --git a/test/accessibility/services/a11y/a11y.ts b/test/accessibility/services/a11y/a11y.ts
new file mode 100644
index 0000000000000..7adfe7ebfcc7d
--- /dev/null
+++ b/test/accessibility/services/a11y/a11y.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 chalk from 'chalk';
+import testSubjectToCss from '@kbn/test-subj-selector';
+
+import { FtrProviderContext } from '../../ftr_provider_context';
+import { AxeReport, printResult } from './axe_report';
+// @ts-ignore JS that is run in browser as is
+import { analyzeWithAxe, analyzeWithAxeWithClient } from './analyze_with_axe';
+
+interface AxeContext {
+ include?: string[];
+ exclude?: string[][];
+}
+
+interface TestOptions {
+ excludeTestSubj?: string | string[];
+}
+
+export const normalizeResult = (report: any) => {
+ if (report.error) {
+ throw report.error;
+ }
+
+ return report.result as false | AxeReport;
+};
+
+export function A11yProvider({ getService }: FtrProviderContext) {
+ const browser = getService('browser');
+ const Wd = getService('__webdriver__');
+ const log = getService('log');
+
+ /**
+ * Accessibility testing service using the Axe (https://www.deque.com/axe/)
+ * toolset to validate a11y rules similar to ESLint. In order to test against
+ * the rules we must load up the UI and feed a full HTML snapshot into Axe.
+ */
+ return new (class Accessibility {
+ public async testAppSnapshot(options: TestOptions = {}) {
+ const context = this.getAxeContext(true, options.excludeTestSubj);
+ const report = await this.captureAxeReport(context);
+ await this.testAxeReport(report);
+ }
+
+ public async testGlobalSnapshot(options: TestOptions = {}) {
+ const context = this.getAxeContext(false, options.excludeTestSubj);
+ const report = await this.captureAxeReport(context);
+ await this.testAxeReport(report);
+ }
+
+ private getAxeContext(global: boolean, excludeTestSubj?: string | string[]): AxeContext {
+ return {
+ include: global ? undefined : [testSubjectToCss('appA11yRoot')],
+ exclude: ([] as string[])
+ .concat(excludeTestSubj || [])
+ .map(ts => [testSubjectToCss(ts)])
+ .concat([['.ace_scrollbar']]),
+ };
+ }
+
+ private testAxeReport(report: AxeReport) {
+ const errorMsgs = [];
+
+ for (const result of report.incomplete) {
+ // these items require human review and can't be definitively validated
+ log.warning(printResult(chalk.yellow('UNABLE TO VALIDATE'), result));
+ }
+
+ for (const result of report.violations) {
+ errorMsgs.push(printResult(chalk.red('VIOLATION'), result));
+ }
+
+ if (errorMsgs.length) {
+ throw new Error(`a11y report:\n${errorMsgs.join('\n')}`);
+ }
+ }
+
+ private async captureAxeReport(context: AxeContext): Promise {
+ const axeOptions = {
+ reporter: 'v2',
+ runOnly: ['wcag2a', 'wcag2aa'],
+ rules: {
+ 'color-contrast': {
+ enabled: false,
+ },
+ },
+ };
+
+ await (Wd.driver.manage() as any).setTimeouts({
+ ...(await (Wd.driver.manage() as any).getTimeouts()),
+ script: 600000,
+ });
+
+ const report = normalizeResult(
+ await browser.executeAsync(analyzeWithAxe, context, axeOptions)
+ );
+
+ if (report !== false) {
+ return report;
+ }
+
+ const withClientReport = normalizeResult(
+ await browser.executeAsync(analyzeWithAxeWithClient, context, axeOptions)
+ );
+
+ if (withClientReport === false) {
+ throw new Error('Attempted to analyze with axe but failed to load axe client');
+ }
+
+ return withClientReport;
+ }
+ })();
+}
diff --git a/test/accessibility/services/a11y/analyze_with_axe.js b/test/accessibility/services/a11y/analyze_with_axe.js
new file mode 100644
index 0000000000000..5cba55a29f8a4
--- /dev/null
+++ b/test/accessibility/services/a11y/analyze_with_axe.js
@@ -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 { readFileSync } from 'fs';
+
+export function analyzeWithAxe(context, options, callback) {
+ Promise.resolve()
+ .then(() => {
+ if (window.axe) {
+ return window.axe.run(context, options);
+ }
+
+ // return a false report to trigger analyzeWithAxeWithClient
+ return false;
+ })
+ .then(result => callback({ result }), error => callback({ error }));
+}
+
+export const analyzeWithAxeWithClient = `
+ ${readFileSync(require.resolve('axe-core/axe.js'), 'utf8')}
+
+ return (${analyzeWithAxe.toString()}).apply(null, arguments);
+`;
diff --git a/test/accessibility/services/a11y/axe_report.ts b/test/accessibility/services/a11y/axe_report.ts
new file mode 100644
index 0000000000000..ba1e8c739079d
--- /dev/null
+++ b/test/accessibility/services/a11y/axe_report.ts
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+type AxeImpact = 'minor' | 'moderate' | 'serious' | 'critical';
+
+type AxeRelatedNodes = Array<{
+ data: any;
+ id: string;
+ impact: AxeImpact;
+ message: string;
+ relatedNodes: [];
+}>;
+
+export interface AxeResult {
+ /* Rule description */
+ description: string;
+ /* rule title/error message */
+ help: string;
+ /* documentation url */
+ helpUrl: string;
+ /* rule id */
+ id: string;
+ /* severity level */
+ impact?: AxeImpact;
+ /* tags used to group rules */
+ tags: string[];
+ /* nodes grouped in this result */
+ nodes: Array<{
+ all: AxeRelatedNodes;
+ any: AxeRelatedNodes;
+ none: AxeRelatedNodes;
+
+ html: string;
+ impact: AxeImpact;
+ target: string[];
+ }>;
+}
+
+export type AxeResultGroup = AxeResult[];
+
+export interface AxeReport {
+ inapplicable: AxeResultGroup;
+ passes: AxeResultGroup;
+ incomplete: AxeResultGroup;
+ violations: AxeResultGroup;
+}
+
+export const printResult = (title: string, result: AxeResult) => `
+${title}
+ [${result.id}]: ${result.description}
+ Help: ${result.helpUrl}
+ Elements:
+ - ${result.nodes.map(node => node.target).join('\n - ')}`;
diff --git a/src/plugins/expressions/common/index.ts b/test/accessibility/services/a11y/index.ts
similarity index 95%
rename from src/plugins/expressions/common/index.ts
rename to test/accessibility/services/a11y/index.ts
index af870208f4865..7baa17c1eafa3 100644
--- a/src/plugins/expressions/common/index.ts
+++ b/test/accessibility/services/a11y/index.ts
@@ -17,4 +17,4 @@
* under the License.
*/
-export * from './expressions';
+export { A11yProvider } from './a11y';
diff --git a/test/accessibility/services/index.ts b/test/accessibility/services/index.ts
new file mode 100644
index 0000000000000..98d1628732f5c
--- /dev/null
+++ b/test/accessibility/services/index.ts
@@ -0,0 +1,26 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { services as kibanaFunctionalServices } from '../../functional/services';
+import { A11yProvider } from './a11y';
+
+export const services = {
+ ...kibanaFunctionalServices,
+ a11y: A11yProvider,
+};
diff --git a/test/api_integration/apis/core/index.js b/test/api_integration/apis/core/index.js
index e5da4e4730662..d617b2ad07351 100644
--- a/test/api_integration/apis/core/index.js
+++ b/test/api_integration/apis/core/index.js
@@ -16,45 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
-import expect from '@kbn/expect';
export default function ({ getService }) {
const supertest = getService('supertest');
- describe('core', () => {
- describe('request context', () => {
- it('provides access to elasticsearch', async () => (
- await supertest
- .get('/requestcontext/elasticsearch')
- .expect(200, 'Elasticsearch: true')
- ));
+ describe('core request context', () => {
+ it('provides access to elasticsearch', async () => (
+ await supertest
+ .get('/requestcontext/elasticsearch')
+ .expect(200, 'Elasticsearch: true')
+ ));
- it('provides access to SavedObjects client', async () => (
- await supertest
- .get('/requestcontext/savedobjectsclient')
- .expect(200, 'SavedObjects client: {"page":1,"per_page":20,"total":0,"saved_objects":[]}')
- ));
- });
-
- describe('compression', () => {
- it(`uses compression when there isn't a referer`, async () => {
- await supertest
- .get('/app/kibana')
- .set('accept-encoding', 'gzip')
- .then(response => {
- expect(response.headers).to.have.property('content-encoding', 'gzip');
- });
- });
-
- it(`doesn't use compression when there is a referer`, async () => {
- await supertest
- .get('/app/kibana')
- .set('accept-encoding', 'gzip')
- .set('referer', 'https://www.google.com')
- .then(response => {
- expect(response.headers).not.to.have.property('content-encoding');
- });
- });
- });
+ it('provides access to SavedObjects client', async () => (
+ await supertest
+ .get('/requestcontext/savedobjectsclient')
+ .expect(200, 'SavedObjects client: {"page":1,"per_page":20,"total":0,"saved_objects":[]}')
+ ));
});
}
diff --git a/test/api_integration/apis/index.js b/test/api_integration/apis/index.js
index de36ee678b10e..9f2672959390c 100644
--- a/test/api_integration/apis/index.js
+++ b/test/api_integration/apis/index.js
@@ -34,6 +34,5 @@ export default function ({ loadTestFile }) {
loadTestFile(require.resolve('./status'));
loadTestFile(require.resolve('./stats'));
loadTestFile(require.resolve('./ui_metric'));
- loadTestFile(require.resolve('./core'));
});
}
diff --git a/test/api_integration/apis/index_patterns/es_errors/errors.js b/test/api_integration/apis/index_patterns/es_errors/errors.js
index 7e04e3f7204d7..4e50b965211c2 100644
--- a/test/api_integration/apis/index_patterns/es_errors/errors.js
+++ b/test/api_integration/apis/index_patterns/es_errors/errors.js
@@ -26,7 +26,7 @@ import {
createNoMatchingIndicesError,
isNoMatchingIndicesError,
convertEsError
-} from '../../../../../src/legacy/server/index_patterns/service/lib/errors';
+} from '../../../../../src/plugins/data/server/index_patterns/fetcher/lib/errors';
import {
getIndexNotFoundError,
diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js
index 37916d3bee375..2bd574d669e20 100644
--- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js
+++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js
@@ -20,7 +20,7 @@
export default function ({ getService }) {
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
- const chance = getService('chance');
+ const randomness = getService('randomness');
describe('params', () => {
before(() => esArchiver.load('index_patterns/basic_index'));
@@ -63,8 +63,8 @@ export default function ({ getService }) {
supertest
.get('/api/index_patterns/_fields_for_wildcard')
.query({
- pattern: chance.word(),
- [chance.word()]: chance.word(),
+ pattern: randomness.word(),
+ [randomness.word()]: randomness.word(),
})
.expect(400));
});
diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js
index d909b51e94ac0..bc70339bd1a66 100644
--- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js
+++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js
@@ -61,8 +61,7 @@ export default function ({ getService }) {
aggregatable: true,
name: 'baz.keyword',
readFromDocValues: true,
- parent: 'baz',
- subType: 'multi',
+ subType: { multi: { parent: 'baz' } }
},
{
type: 'number',
@@ -72,6 +71,21 @@ export default function ({ getService }) {
name: 'foo',
readFromDocValues: true,
},
+ {
+ aggregatable: true,
+ esTypes: [
+ 'keyword'
+ ],
+ name: 'nestedField.child',
+ readFromDocValues: true,
+ searchable: true,
+ subType: {
+ nested: {
+ path: 'nestedField'
+ }
+ },
+ type: 'string',
+ },
],
})
.then(ensureFieldsAreSorted));
@@ -124,8 +138,7 @@ export default function ({ getService }) {
aggregatable: true,
name: 'baz.keyword',
readFromDocValues: true,
- parent: 'baz',
- subType: 'multi',
+ subType: { multi: { parent: 'baz' } }
},
{
aggregatable: false,
@@ -142,6 +155,21 @@ export default function ({ getService }) {
name: 'foo',
readFromDocValues: true,
},
+ {
+ aggregatable: true,
+ esTypes: [
+ 'keyword'
+ ],
+ name: 'nestedField.child',
+ readFromDocValues: true,
+ searchable: true,
+ subType: {
+ nested: {
+ path: 'nestedField'
+ }
+ },
+ type: 'string',
+ },
],
})
.then(ensureFieldsAreSorted));
diff --git a/test/api_integration/apis/suggestions/suggestions.js b/test/api_integration/apis/suggestions/suggestions.js
index 80b6febb81d7b..abacf13c7aa06 100644
--- a/test/api_integration/apis/suggestions/suggestions.js
+++ b/test/api_integration/apis/suggestions/suggestions.js
@@ -22,8 +22,14 @@ export default function ({ getService }) {
const supertest = getService('supertest');
describe('Suggestions API', function () {
- before(() => esArchiver.load('index_patterns/basic_index'));
- after(() => esArchiver.unload('index_patterns/basic_index'));
+ before(async () => {
+ await esArchiver.load('index_patterns/basic_index');
+ await esArchiver.load('index_patterns/basic_kibana');
+ });
+ after(async () => {
+ await esArchiver.unload('index_patterns/basic_index');
+ await esArchiver.unload('index_patterns/basic_kibana');
+ });
it('should return 200 with special characters', () => (
supertest
@@ -34,5 +40,15 @@ export default function ({ getService }) {
})
.expect(200)
));
+
+ it('should support nested fields', () => (
+ supertest
+ .post('/api/kibana/suggestions/values/basic_index')
+ .send({
+ field: 'nestedField.child',
+ query: 'nes'
+ })
+ .expect(200, ['nestedValue'])
+ ));
});
}
diff --git a/test/api_integration/fixtures/es_archiver/index_patterns/basic_index/data.json.gz b/test/api_integration/fixtures/es_archiver/index_patterns/basic_index/data.json.gz
index edae3bfdaa2ea..ec085ec813240 100644
Binary files a/test/api_integration/fixtures/es_archiver/index_patterns/basic_index/data.json.gz and b/test/api_integration/fixtures/es_archiver/index_patterns/basic_index/data.json.gz differ
diff --git a/test/api_integration/fixtures/es_archiver/index_patterns/basic_index/mappings.json b/test/api_integration/fixtures/es_archiver/index_patterns/basic_index/mappings.json
index 5d0d426010953..338b31dc681ae 100644
--- a/test/api_integration/fixtures/es_archiver/index_patterns/basic_index/mappings.json
+++ b/test/api_integration/fixtures/es_archiver/index_patterns/basic_index/mappings.json
@@ -24,8 +24,18 @@
},
"foo": {
"type": "long"
+ },
+ "nestedField": {
+ "type": "nested",
+ "properties": {
+ "child": {
+ "type": "keyword"
+ }
+ }
}
}
}
}
-}
\ No newline at end of file
+}
+
+
diff --git a/test/api_integration/fixtures/es_archiver/index_patterns/basic_kibana/data.json b/test/api_integration/fixtures/es_archiver/index_patterns/basic_kibana/data.json
new file mode 100644
index 0000000000000..54276b59dcc23
--- /dev/null
+++ b/test/api_integration/fixtures/es_archiver/index_patterns/basic_kibana/data.json
@@ -0,0 +1,15 @@
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "id": "index-pattern:91200a00-9efd-11e7-acb3-3dab96693fab",
+ "source": {
+ "type": "index-pattern",
+ "updated_at": "2017-09-21T18:49:16.270Z",
+ "index-pattern": {
+ "title": "basic_index",
+ "fields": "[{\"name\":\"bar\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"baz\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"baz.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"foo\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nestedField.child\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"nested\":{\"path\":\"nestedField\"}}}]"
+ }
+ }
+ }
+}
diff --git a/test/api_integration/fixtures/es_archiver/index_patterns/basic_kibana/mappings.json b/test/api_integration/fixtures/es_archiver/index_patterns/basic_kibana/mappings.json
new file mode 100644
index 0000000000000..99264d7ebbff8
--- /dev/null
+++ b/test/api_integration/fixtures/es_archiver/index_patterns/basic_kibana/mappings.json
@@ -0,0 +1,253 @@
+{
+ "type": "index",
+ "value": {
+ "index": ".kibana",
+ "settings": {
+ "index": {
+ "number_of_shards": "1",
+ "number_of_replicas": "1"
+ }
+ },
+ "mappings": {
+ "dynamic": "strict",
+ "properties": {
+ "config": {
+ "dynamic": "true",
+ "properties": {
+ "buildNum": {
+ "type": "keyword"
+ },
+ "defaultIndex": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 256
+ }
+ }
+ }
+ }
+ },
+ "dashboard": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "hits": {
+ "type": "integer"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "optionsJSON": {
+ "type": "text"
+ },
+ "panelsJSON": {
+ "type": "text"
+ },
+ "refreshInterval": {
+ "properties": {
+ "display": {
+ "type": "keyword"
+ },
+ "pause": {
+ "type": "boolean"
+ },
+ "section": {
+ "type": "integer"
+ },
+ "value": {
+ "type": "integer"
+ }
+ }
+ },
+ "timeFrom": {
+ "type": "keyword"
+ },
+ "timeRestore": {
+ "type": "boolean"
+ },
+ "timeTo": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "uiStateJSON": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "index-pattern": {
+ "properties": {
+ "fieldFormatMap": {
+ "type": "text"
+ },
+ "fields": {
+ "type": "text"
+ },
+ "intervalName": {
+ "type": "keyword"
+ },
+ "notExpandable": {
+ "type": "boolean"
+ },
+ "sourceFilters": {
+ "type": "text"
+ },
+ "timeFieldName": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ }
+ }
+ },
+ "search": {
+ "properties": {
+ "columns": {
+ "type": "keyword"
+ },
+ "description": {
+ "type": "text"
+ },
+ "hits": {
+ "type": "integer"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "sort": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "server": {
+ "properties": {
+ "uuid": {
+ "type": "keyword"
+ }
+ }
+ },
+ "timelion-sheet": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "hits": {
+ "type": "integer"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "timelion_chart_height": {
+ "type": "integer"
+ },
+ "timelion_columns": {
+ "type": "integer"
+ },
+ "timelion_interval": {
+ "type": "keyword"
+ },
+ "timelion_other_interval": {
+ "type": "keyword"
+ },
+ "timelion_rows": {
+ "type": "integer"
+ },
+ "timelion_sheet": {
+ "type": "text"
+ },
+ "title": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "namespace": {
+ "type": "keyword"
+ },
+ "type": {
+ "type": "keyword"
+ },
+ "updated_at": {
+ "type": "date"
+ },
+ "url": {
+ "properties": {
+ "accessCount": {
+ "type": "long"
+ },
+ "accessDate": {
+ "type": "date"
+ },
+ "createDate": {
+ "type": "date"
+ },
+ "url": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 2048
+ }
+ }
+ }
+ }
+ },
+ "visualization": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "savedSearchId": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "uiStateJSON": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ },
+ "visState": {
+ "type": "text"
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/api_integration/services/index.ts b/test/api_integration/services/index.ts
index d0fcd94a6a204..573450cae534a 100644
--- a/test/api_integration/services/index.ts
+++ b/test/api_integration/services/index.ts
@@ -22,14 +22,11 @@ import { services as commonServices } from '../../common/services';
// @ts-ignore not TS yet
import { KibanaSupertestProvider, ElasticsearchSupertestProvider } from './supertest';
-// @ts-ignore not TS yet
-import { ChanceProvider } from './chance';
-
export const services = {
es: commonServices.es,
esArchiver: commonServices.esArchiver,
retry: commonServices.retry,
supertest: KibanaSupertestProvider,
esSupertest: ElasticsearchSupertestProvider,
- chance: ChanceProvider,
+ randomness: commonServices.randomness,
};
diff --git a/test/common/services/index.ts b/test/common/services/index.ts
index 47d93d811e3f6..225aacc1c9895 100644
--- a/test/common/services/index.ts
+++ b/test/common/services/index.ts
@@ -21,10 +21,12 @@ import { LegacyEsProvider } from './legacy_es';
import { EsArchiverProvider } from './es_archiver';
import { KibanaServerProvider } from './kibana_server';
import { RetryProvider } from './retry';
+import { RandomnessProvider } from './randomness';
export const services = {
es: LegacyEsProvider,
esArchiver: EsArchiverProvider,
kibanaServer: KibanaServerProvider,
retry: RetryProvider,
+ randomness: RandomnessProvider,
};
diff --git a/test/common/services/randomness.ts b/test/common/services/randomness.ts
new file mode 100644
index 0000000000000..2a49703e92c58
--- /dev/null
+++ b/test/common/services/randomness.ts
@@ -0,0 +1,89 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Chance from 'chance';
+
+import { FtrProviderContext } from '../ftr_provider_context';
+
+interface CharOptions {
+ pool?: string;
+ alpha?: boolean;
+ numeric?: boolean;
+ symbols?: boolean;
+ casing?: 'lower' | 'upper';
+}
+
+interface StringOptions extends CharOptions {
+ length?: number;
+}
+
+interface NumberOptions {
+ min?: number;
+ max?: number;
+}
+
+export function RandomnessProvider({ getService }: FtrProviderContext) {
+ const log = getService('log');
+
+ const seed = Date.now();
+ log.debug('randomness seed: %j', seed);
+
+ const chance = new Chance(seed);
+
+ return new (class RandomnessService {
+ /**
+ * Generate a random natural number
+ *
+ * range: 0 to 9007199254740991
+ *
+ */
+ naturalNumber(options?: NumberOptions) {
+ return chance.natural(options);
+ }
+
+ /**
+ * Generate a random integer
+ */
+ integer(options?: NumberOptions) {
+ return chance.integer(options);
+ }
+
+ /**
+ * Generate a random number, defaults to at least 4 and no more than 8 syllables
+ */
+ word(options: { syllables?: number } = {}) {
+ const { syllables = this.naturalNumber({ min: 4, max: 8 }) } = options;
+
+ return chance.word({
+ syllables,
+ });
+ }
+
+ /**
+ * Generate a random string, defaults to at least 8 and no more than 15 alpha-numeric characters
+ */
+ string(options: StringOptions = {}) {
+ return chance.string({
+ length: this.naturalNumber({ min: 8, max: 15 }),
+ ...(options.pool === 'undefined' ? { alpha: true, numeric: true, symbols: false } : {}),
+ ...options,
+ });
+ }
+ })();
+}
diff --git a/test/functional/apps/dashboard/dashboard_state.js b/test/functional/apps/dashboard/dashboard_state.js
index 6dfef4c54c66b..b9ad47e428e82 100644
--- a/test/functional/apps/dashboard/dashboard_state.js
+++ b/test/functional/apps/dashboard/dashboard_state.js
@@ -24,7 +24,7 @@ import { PIE_CHART_VIS_NAME, AREA_CHART_VIS_NAME } from '../../page_objects/dash
// eslint-disable-next-line
import {
DEFAULT_PANEL_WIDTH
-} from '../../../../src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_constants';
+} from '../../../../src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_constants';
export default function ({ getService, getPageObjects }) {
const PageObjects = getPageObjects(['dashboard', 'visualize', 'header', 'discover']);
diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js
index 6c7170d6b2168..9d3f95e28942a 100644
--- a/test/functional/apps/discover/_discover.js
+++ b/test/functional/apps/discover/_discover.js
@@ -26,6 +26,7 @@ export default function ({ getService, getPageObjects }) {
const browser = getService('browser');
const kibanaServer = getService('kibanaServer');
const filterBar = getService('filterBar');
+ const queryBar = getService('queryBar');
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
const defaultSettings = {
defaultIndex: 'logstash-*',
@@ -154,6 +155,26 @@ export default function ({ getService, getPageObjects }) {
});
});
+ describe('nested query', () => {
+
+ before(async () => {
+ log.debug('setAbsoluteRangeForAnotherQuery');
+ await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
+ await PageObjects.discover.waitUntilSearchingHasFinished();
+ });
+
+ it('should support querying on nested fields', async function () {
+ await queryBar.setQuery('nestedField:{ child: nestedValue }');
+ await queryBar.submitQuery();
+ await retry.try(async function () {
+ expect(await PageObjects.discover.getHitCount()).to.be(
+ '1'
+ );
+ });
+ });
+
+ });
+
describe('filter editor', function () {
it('should add a phrases filter', async function () {
await filterBar.addFilter('extension.raw', 'is one of', 'jpg');
diff --git a/test/functional/fixtures/es_archiver/discover/data.json.gz b/test/functional/fixtures/es_archiver/discover/data.json.gz
index c607f211d37c2..047d890f6d410 100644
Binary files a/test/functional/fixtures/es_archiver/discover/data.json.gz and b/test/functional/fixtures/es_archiver/discover/data.json.gz differ
diff --git a/test/functional/fixtures/es_archiver/logstash_functional/data.json.gz b/test/functional/fixtures/es_archiver/logstash_functional/data.json.gz
index 2cef071738526..a212c34e2ead6 100644
Binary files a/test/functional/fixtures/es_archiver/logstash_functional/data.json.gz and b/test/functional/fixtures/es_archiver/logstash_functional/data.json.gz differ
diff --git a/test/functional/fixtures/es_archiver/logstash_functional/mappings.json b/test/functional/fixtures/es_archiver/logstash_functional/mappings.json
index dcfafa2612c5b..010abff9cf6a9 100644
--- a/test/functional/fixtures/es_archiver/logstash_functional/mappings.json
+++ b/test/functional/fixtures/es_archiver/logstash_functional/mappings.json
@@ -153,6 +153,14 @@
}
}
},
+ "nestedField": {
+ "type": "nested",
+ "properties": {
+ "child": {
+ "type": "keyword"
+ }
+ }
+ },
"phpmemory": {
"type": "long"
},
@@ -518,6 +526,14 @@
}
}
},
+ "nestedField": {
+ "type": "nested",
+ "properties": {
+ "child": {
+ "type": "keyword"
+ }
+ }
+ },
"phpmemory": {
"type": "long"
},
@@ -883,6 +899,14 @@
}
}
},
+ "nestedField": {
+ "type": "nested",
+ "properties": {
+ "child": {
+ "type": "keyword"
+ }
+ }
+ },
"phpmemory": {
"type": "long"
},
@@ -1091,4 +1115,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/test/functional/page_objects/discover_page.js b/test/functional/page_objects/discover_page.js
index 4654b85f9c7c4..8d12b2117a214 100644
--- a/test/functional/page_objects/discover_page.js
+++ b/test/functional/page_objects/discover_page.js
@@ -283,19 +283,13 @@ export function DiscoverPageProvider({ getService, getPageObjects }) {
}
async openSidebarFieldFilter() {
- const fieldFilterFormExists = await testSubjects.exists('discoverFieldFilter');
- if (!fieldFilterFormExists) {
- await testSubjects.click('toggleFieldFilterButton');
- await testSubjects.existOrFail('discoverFieldFilter');
- }
+ await testSubjects.click('toggleFieldFilterButton');
+ await testSubjects.existOrFail('filterSelectionPanel');
}
async closeSidebarFieldFilter() {
- const fieldFilterFormExists = await testSubjects.exists('discoverFieldFilter');
- if (fieldFilterFormExists) {
- await testSubjects.click('toggleFieldFilterButton');
- await testSubjects.missingOrFail('discoverFieldFilter', { allowHidden: true });
- }
+ await testSubjects.click('toggleFieldFilterButton');
+ await testSubjects.missingOrFail('filterSelectionPanel', { allowHidden: true });
}
}
diff --git a/test/functional/services/browser.ts b/test/functional/services/browser.ts
index 4060e3dd7800f..97e02958f3787 100644
--- a/test/functional/services/browser.ts
+++ b/test/functional/services/browser.ts
@@ -461,10 +461,7 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
);
}
- public async executeAsync(
- fn: string | ((...args: A) => R),
- ...args: A
- ): Promise {
+ public async executeAsync(fn: string | ((...args: any[]) => R), ...args: any[]): Promise {
return await driver.executeAsyncScript(
fn,
...cloneDeep(args, arg => {
diff --git a/test/functional/services/remote/webdriver.ts b/test/functional/services/remote/webdriver.ts
index 5ebec6bde6ebb..201354fff48ef 100644
--- a/test/functional/services/remote/webdriver.ts
+++ b/test/functional/services/remote/webdriver.ts
@@ -75,13 +75,23 @@ async function attemptToCreateCommand(
case 'chrome': {
const chromeCapabilities = Capabilities.chrome();
const chromeOptions = [
- 'disable-translate',
- 'new-window',
+ // Disables the sandbox for all process types that are normally sandboxed.
'no-sandbox',
+ // Launches URL in new browser window.
+ 'new-window',
+ // By default, file:// URIs cannot read other file:// URIs. This is an override for developers who need the old behavior for testing.
'allow-file-access-from-files',
+ // Use fake device for Media Stream to replace actual camera and microphone.
'use-fake-device-for-media-stream',
+ // Bypass the media stream infobar by selecting the default device for media streams (e.g. WebRTC). Works with --use-fake-device-for-media-stream.
'use-fake-ui-for-media-stream',
];
+ if (process.platform === 'linux') {
+ // The /dev/shm partition is too small in certain VM environments, causing
+ // Chrome to fail or crash. Use this flag to work-around this issue
+ // (a temporary directory will always be used to create anonymous shared memory files).
+ chromeOptions.push('disable-dev-shm-usage');
+ }
if (headlessBrowser === '1') {
// Use --disable-gpu to avoid an error from a missing Mesa library, as per
// See: https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json
index 21b49a9823f62..766e6168002c2 100644
--- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json
+++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json
@@ -7,7 +7,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "14.7.0",
+ "@elastic/eui": "14.8.0",
"react": "^16.8.0",
"react-dom": "^16.8.0"
}
diff --git a/test/plugin_functional/plugins/core_plugin_a/public/application.tsx b/test/plugin_functional/plugins/core_plugin_a/public/application.tsx
index 5d464cf0405d0..7c1406f5b20c3 100644
--- a/test/plugin_functional/plugins/core_plugin_a/public/application.tsx
+++ b/test/plugin_functional/plugins/core_plugin_a/public/application.tsx
@@ -76,7 +76,7 @@ const PageA = () => (
- Page A's content goes here
+ Page A's content goes here
);
diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json
index 7aacfbc22ceee..7c5b6f6be58af 100644
--- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json
@@ -7,7 +7,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "14.7.0",
+ "@elastic/eui": "14.8.0",
"react": "^16.8.0"
}
}
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json
index 80ec89fb0078a..ef472b4026957 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json
@@ -8,7 +8,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "14.7.0",
+ "@elastic/eui": "14.8.0",
"react": "^16.8.0"
},
"scripts": {
diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json
index 54aba07079eeb..277bb09ac745c 100644
--- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json
@@ -8,7 +8,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "14.7.0",
+ "@elastic/eui": "14.8.0",
"react": "^16.8.0"
},
"scripts": {
diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx b/test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx
index d56ac5f92db88..8678ab705df9c 100644
--- a/test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx
+++ b/test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import React, { Component } from 'react';
+import React from 'react';
import {
setup as navSetup,
start as navStart,
@@ -33,22 +33,21 @@ const customExtension = {
navSetup.registerMenuItem(customExtension);
-export class AppWithTopNav extends Component {
- public render() {
- const { TopNavMenu } = navStart.ui;
- const config = [
- {
- id: 'new',
- label: 'New Button',
- description: 'New Demo',
- run() {},
- testId: 'demoNewButton',
- },
- ];
- return (
-
- Hey
-
- );
- }
-}
+export const AppWithTopNav = () => {
+ const { TopNavMenu } = navStart.ui;
+ const config = [
+ {
+ id: 'new',
+ label: 'New Button',
+ description: 'New Demo',
+ run() {},
+ testId: 'demoNewButton',
+ },
+ ];
+
+ return (
+
+ Hey
+
+ );
+};
diff --git a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json b/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json
index 121f69ada329b..f248a7e4d1f2d 100644
--- a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json
@@ -7,7 +7,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "14.7.0",
+ "@elastic/eui": "14.8.0",
"react": "^16.8.0",
"react-dom": "^16.8.0"
}
diff --git a/test/plugin_functional/plugins/search_explorer/public/demo_strategy.tsx b/test/plugin_functional/plugins/search_explorer/public/demo_strategy.tsx
index 665b3c9f0ae03..8a0dd31e3595f 100644
--- a/test/plugin_functional/plugins/search_explorer/public/demo_strategy.tsx
+++ b/test/plugin_functional/plugins/search_explorer/public/demo_strategy.tsx
@@ -127,7 +127,7 @@ export class DemoStrategy extends React.Component {
},
]}
demo={this.renderDemo()}
- >
+ />
);
}
diff --git a/test/plugin_functional/plugins/search_explorer/public/es_strategy.tsx b/test/plugin_functional/plugins/search_explorer/public/es_strategy.tsx
index 20de631bc5605..d35c67191a1f8 100644
--- a/test/plugin_functional/plugins/search_explorer/public/es_strategy.tsx
+++ b/test/plugin_functional/plugins/search_explorer/public/es_strategy.tsx
@@ -139,7 +139,7 @@ export class EsSearchTest extends React.Component {
},
]}
demo={this.renderDemo()}
- >
+ />
);
}
diff --git a/test/plugin_functional/plugins/search_explorer/public/guide_section.tsx b/test/plugin_functional/plugins/search_explorer/public/guide_section.tsx
index fe67e4097b2a3..1562e33b14c2f 100644
--- a/test/plugin_functional/plugins/search_explorer/public/guide_section.tsx
+++ b/test/plugin_functional/plugins/search_explorer/public/guide_section.tsx
@@ -110,7 +110,7 @@ export class GuideSection extends React.Component {
return code.map((codeBlock, i) => (
-
+
{codeBlock.description}
{this.removeLicenseBlock(codeBlock.snippet)}
diff --git a/test/plugin_functional/plugins/search_explorer/public/search_api.tsx b/test/plugin_functional/plugins/search_explorer/public/search_api.tsx
index 3e4768c870064..8ec6225d1f172 100644
--- a/test/plugin_functional/plugins/search_explorer/public/search_api.tsx
+++ b/test/plugin_functional/plugins/search_explorer/public/search_api.tsx
@@ -83,5 +83,5 @@ export const SearchApiPage = () => (
],
},
]}
- >
+ />
);
diff --git a/test/scripts/jenkins_accessibility.sh b/test/scripts/jenkins_accessibility.sh
new file mode 100755
index 0000000000000..0b3d8dc3f85c2
--- /dev/null
+++ b/test/scripts/jenkins_accessibility.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+set -e
+
+if [[ -n "$IS_PIPELINE_JOB" ]] ; then
+ source src/dev/ci_setup/setup_env.sh
+fi
+
+export TEST_BROWSER_HEADLESS=1
+
+if [[ -z "$IS_PIPELINE_JOB" ]] ; then
+ yarn run grunt functionalTests:ensureAllTestsInCiGroup;
+ node scripts/build --debug --oss;
+else
+ installDir="$(realpath $PARENT_DIR/kibana/build/oss/kibana-*-SNAPSHOT-linux-x86_64)"
+ destDir=${installDir}-${CI_WORKER_NUMBER}
+ cp -R "$installDir" "$destDir"
+
+ export KIBANA_INSTALL_DIR="$destDir"
+fi
+
+checks-reporter-with-killswitch "Kibana accessibility tests" \
+ node scripts/functional_tests \
+ --debug --bail \
+ --kibana-install-dir "$installDir" \
+ --config test/accessibility/config.ts;
diff --git a/test/scripts/jenkins_ci_group.sh b/test/scripts/jenkins_ci_group.sh
index 274cca695b535..c6bddb69aa570 100755
--- a/test/scripts/jenkins_ci_group.sh
+++ b/test/scripts/jenkins_ci_group.sh
@@ -1,12 +1,6 @@
#!/usr/bin/env bash
-set -e
-
-if [[ -n "$IS_PIPELINE_JOB" ]] ; then
- source src/dev/ci_setup/setup_env.sh
-fi
-
-export TEST_BROWSER_HEADLESS=1
+source test/scripts/jenkins_test_setup.sh
if [[ -z "$IS_PIPELINE_JOB" ]] ; then
yarn run grunt functionalTests:ensureAllTestsInCiGroup;
diff --git a/test/scripts/jenkins_firefox_smoke.sh b/test/scripts/jenkins_firefox_smoke.sh
index 69cedc9657340..9a31f5f43d224 100755
--- a/test/scripts/jenkins_firefox_smoke.sh
+++ b/test/scripts/jenkins_firefox_smoke.sh
@@ -1,10 +1,6 @@
#!/usr/bin/env bash
-set -e
-
-if [[ -n "$IS_PIPELINE_JOB" ]] ; then
- source src/dev/ci_setup/setup_env.sh
-fi
+source test/scripts/jenkins_test_setup.sh
if [[ -z "$IS_PIPELINE_JOB" ]] ; then
node scripts/build --debug --oss;
diff --git a/test/scripts/jenkins_test_setup.sh b/test/scripts/jenkins_test_setup.sh
new file mode 100644
index 0000000000000..e2dd0bc276bb6
--- /dev/null
+++ b/test/scripts/jenkins_test_setup.sh
@@ -0,0 +1,20 @@
+set -e
+
+function post_work() {
+ set +e
+ if [[ -z "$IS_PIPELINE_JOB" ]] ; then
+ node "$KIBANA_DIR/scripts/report_failed_tests"
+ fi
+
+ if [[ -z "$REMOVE_KIBANA_INSTALL_DIR" && -z "$KIBANA_INSTALL_DIR" && -d "$KIBANA_INSTALL_DIR" ]]; then
+ rm -rf "$REMOVE_KIBANA_INSTALL_DIR"
+ fi
+}
+
+trap 'post_work' EXIT
+
+export TEST_BROWSER_HEADLESS=1
+
+if [[ -n "$IS_PIPELINE_JOB" ]] ; then
+ source src/dev/ci_setup/setup_env.sh
+fi
diff --git a/test/scripts/jenkins_visual_regression.sh b/test/scripts/jenkins_visual_regression.sh
index fdda24423d977..9ca1c0f08d2c9 100755
--- a/test/scripts/jenkins_visual_regression.sh
+++ b/test/scripts/jenkins_visual_regression.sh
@@ -1,11 +1,6 @@
#!/usr/bin/env bash
-set -e
-
-if [[ -n "$IS_PIPELINE_JOB" ]] ; then
- source src/dev/ci_setup/setup_env.sh
-fi
-
+source test/scripts/jenkins_test_setup.sh
source "$KIBANA_DIR/src/dev/ci_setup/setup_percy.sh"
if [[ -z "$IS_PIPELINE_JOB" ]] ; then
@@ -22,8 +17,6 @@ else
export KIBANA_INSTALL_DIR="$destDir"
fi
-export TEST_BROWSER_HEADLESS=1
-
checks-reporter-with-killswitch "Kibana visual regression tests" \
yarn run percy exec -t 500 \
node scripts/functional_tests \
diff --git a/test/scripts/jenkins_xpack_accessibility.sh b/test/scripts/jenkins_xpack_accessibility.sh
new file mode 100755
index 0000000000000..af813c3c40f84
--- /dev/null
+++ b/test/scripts/jenkins_xpack_accessibility.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+
+set -e
+
+if [[ -n "$IS_PIPELINE_JOB" ]] ; then
+ source src/dev/ci_setup/setup_env.sh
+fi
+
+if [[ -z "$IS_PIPELINE_JOB" ]] ; then
+ echo " -> building and extracting default Kibana distributable for use in functional tests"
+ node scripts/build --debug --no-oss
+
+ linuxBuild="$(find "$KIBANA_DIR/target" -name 'kibana-*-linux-x86_64.tar.gz')"
+ installDir="$PARENT_DIR/install/kibana"
+
+ mkdir -p "$installDir"
+ tar -xzf "$linuxBuild" -C "$installDir" --strip=1
+
+ export KIBANA_INSTALL_DIR="$installDir"
+else
+ installDir="$PARENT_DIR/install/kibana"
+ destDir="${installDir}-${CI_WORKER_NUMBER}"
+ cp -R "$installDir" "$destDir"
+
+ export KIBANA_INSTALL_DIR="$destDir"
+fi
+
+export TEST_BROWSER_HEADLESS=1
+cd "$XPACK_DIR"
+
+checks-reporter-with-killswitch "X-Pack accessibility tests" \
+ node scripts/functional_tests \
+ --debug --bail \
+ --kibana-install-dir "$installDir" \
+ --config test/accessibility/config.ts;
diff --git a/test/scripts/jenkins_xpack_ci_group.sh b/test/scripts/jenkins_xpack_ci_group.sh
index 0b9666b33deca..fba05f8f252d7 100755
--- a/test/scripts/jenkins_xpack_ci_group.sh
+++ b/test/scripts/jenkins_xpack_ci_group.sh
@@ -1,12 +1,6 @@
#!/usr/bin/env bash
-set -e
-
-if [[ -n "$IS_PIPELINE_JOB" ]] ; then
- source src/dev/ci_setup/setup_env.sh
-fi
-
-export TEST_BROWSER_HEADLESS=1
+source test/scripts/jenkins_test_setup.sh
if [[ -z "$IS_PIPELINE_JOB" ]] ; then
echo " -> Ensuring all functional tests are in a ciGroup"
diff --git a/test/scripts/jenkins_xpack_firefox_smoke.sh b/test/scripts/jenkins_xpack_firefox_smoke.sh
index 18ed468de1317..43220459bcb97 100755
--- a/test/scripts/jenkins_xpack_firefox_smoke.sh
+++ b/test/scripts/jenkins_xpack_firefox_smoke.sh
@@ -1,10 +1,6 @@
#!/usr/bin/env bash
-set -e
-
-if [[ -n "$IS_PIPELINE_JOB" ]] ; then
- source src/dev/ci_setup/setup_env.sh
-fi
+source test/scripts/jenkins_test_setup.sh
if [[ -z "$IS_PIPELINE_JOB" ]] ; then
node scripts/build --debug --no-oss;
@@ -21,8 +17,6 @@ else
export KIBANA_INSTALL_DIR="$destDir"
fi
-export TEST_BROWSER_HEADLESS=1
-
cd "$XPACK_DIR"
checks-reporter-with-killswitch "X-Pack firefox smoke test" \
diff --git a/test/scripts/jenkins_xpack_visual_regression.sh b/test/scripts/jenkins_xpack_visual_regression.sh
index 0f3275d45f13b..5699f9e5ee7c1 100755
--- a/test/scripts/jenkins_xpack_visual_regression.sh
+++ b/test/scripts/jenkins_xpack_visual_regression.sh
@@ -1,11 +1,6 @@
#!/usr/bin/env bash
-set -e
-
-if [[ -n "$IS_PIPELINE_JOB" ]] ; then
- source src/dev/ci_setup/setup_env.sh
-fi
-
+source test/scripts/jenkins_test_setup.sh
source "$KIBANA_DIR/src/dev/ci_setup/setup_percy.sh"
if [[ -z "$IS_PIPELINE_JOB" ]] ; then
@@ -23,8 +18,6 @@ else
export KIBANA_INSTALL_DIR="$destDir"
fi
-export TEST_BROWSER_HEADLESS=1
-
cd "$XPACK_DIR"
checks-reporter-with-killswitch "X-Pack visual regression tests" \
diff --git a/test/visual_regression/tests/discover/chart_visualization.js b/test/visual_regression/tests/discover/chart_visualization.js
index 5467f2d3eaa14..4e1d9bf643cf6 100644
--- a/test/visual_regression/tests/discover/chart_visualization.js
+++ b/test/visual_regression/tests/discover/chart_visualization.js
@@ -29,6 +29,7 @@ export default function ({ getService, getPageObjects }) {
const visualTesting = getService('visualTesting');
const defaultSettings = {
defaultIndex: 'logstash-*',
+ 'discover:sampleSize': 1
};
describe('discover', function describeIndexTests() {
diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json
index a678ce90c4cc1..622fbf9a72b68 100644
--- a/x-pack/.i18nrc.json
+++ b/x-pack/.i18nrc.json
@@ -35,6 +35,7 @@
"xpack.server": "legacy/server",
"xpack.snapshotRestore": "legacy/plugins/snapshot_restore",
"xpack.spaces": ["legacy/plugins/spaces", "plugins/spaces"],
+ "xpack.taskManager": "legacy/plugins/task_manager",
"xpack.transform": "legacy/plugins/transform",
"xpack.upgradeAssistant": "legacy/plugins/upgrade_assistant",
"xpack.uptime": "legacy/plugins/uptime",
diff --git a/x-pack/legacy/plugins/actions/index.ts b/x-pack/legacy/plugins/actions/index.ts
index 7c4dd9f73c11f..a58c936c63749 100644
--- a/x-pack/legacy/plugins/actions/index.ts
+++ b/x-pack/legacy/plugins/actions/index.ts
@@ -22,10 +22,10 @@ export function actions(kibana: any) {
return new kibana.Plugin({
id: 'actions',
configPrefix: 'xpack.actions',
- require: ['kibana', 'elasticsearch', 'task_manager', 'encrypted_saved_objects'],
+ require: ['kibana', 'elasticsearch', 'task_manager', 'encryptedSavedObjects'],
isEnabled(config: Legacy.KibanaConfig) {
return (
- config.get('xpack.encrypted_saved_objects.enabled') === true &&
+ config.get('xpack.encryptedSavedObjects.enabled') === true &&
config.get('xpack.actions.enabled') === true &&
config.get('xpack.task_manager.enabled') === true
);
diff --git a/x-pack/legacy/plugins/actions/server/actions_client.test.ts b/x-pack/legacy/plugins/actions/server/actions_client.test.ts
index b4940b23ba61c..933b7b0b239b6 100644
--- a/x-pack/legacy/plugins/actions/server/actions_client.test.ts
+++ b/x-pack/legacy/plugins/actions/server/actions_client.test.ts
@@ -11,9 +11,14 @@ import { ActionsClient } from './actions_client';
import { ExecutorType } from './types';
import { ActionExecutor, TaskRunnerFactory } from './lib';
import { taskManagerMock } from '../../task_manager/task_manager.mock';
-import { savedObjectsClientMock } from '../../../../../src/core/server/mocks';
+import {
+ elasticsearchServiceMock,
+ savedObjectsClientMock,
+} from '../../../../../src/core/server/mocks';
+const defaultKibanaIndex = '.kibana';
const savedObjectsClient = savedObjectsClientMock.create();
+const scopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
const mockTaskManager = taskManagerMock.create();
@@ -22,11 +27,22 @@ const actionTypeRegistryParams = {
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor()),
};
+let actionsClient: ActionsClient;
+let actionTypeRegistry: ActionTypeRegistry;
const executor: ExecutorType = async options => {
return { status: 'ok' };
};
-beforeEach(() => jest.resetAllMocks());
+beforeEach(() => {
+ jest.resetAllMocks();
+ actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
+ actionsClient = new ActionsClient({
+ actionTypeRegistry,
+ savedObjectsClient,
+ scopedClusterClient,
+ defaultKibanaIndex,
+ });
+});
describe('create()', () => {
test('creates an action with all given properties', async () => {
@@ -40,16 +56,11 @@ describe('create()', () => {
},
references: [],
};
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
actionTypeRegistry.register({
id: 'my-action-type',
name: 'My action type',
executor,
});
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
savedObjectsClient.create.mockResolvedValueOnce(savedObjectCreateResult);
const result = await actionsClient.create({
action: {
@@ -80,11 +91,6 @@ describe('create()', () => {
});
test('validates config', async () => {
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
actionTypeRegistry.register({
id: 'my-action-type',
name: 'My action type',
@@ -110,11 +116,6 @@ describe('create()', () => {
});
test(`throws an error when an action type doesn't exist`, async () => {
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
await expect(
actionsClient.create({
action: {
@@ -130,16 +131,11 @@ describe('create()', () => {
});
test('encrypts action type options unless specified not to', async () => {
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
actionTypeRegistry.register({
id: 'my-action-type',
name: 'My action type',
executor,
});
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
savedObjectsClient.create.mockResolvedValueOnce({
id: '1',
type: 'type',
@@ -198,11 +194,6 @@ describe('create()', () => {
describe('get()', () => {
test('calls savedObjectsClient with id', async () => {
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
savedObjectsClient.get.mockResolvedValueOnce({
id: '1',
type: 'type',
@@ -242,12 +233,12 @@ describe('find()', () => {
},
],
};
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
savedObjectsClient.find.mockResolvedValueOnce(expectedResult);
+ scopedClusterClient.callAsInternalUser.mockResolvedValueOnce({
+ aggregations: {
+ '1': { doc_count: 6 },
+ },
+ });
const result = await actionsClient.find({});
expect(result).toEqual({
total: 1,
@@ -259,6 +250,7 @@ describe('find()', () => {
config: {
foo: 'bar',
},
+ referencedByCount: 6,
},
],
});
@@ -276,11 +268,6 @@ describe('find()', () => {
describe('delete()', () => {
test('calls savedObjectsClient with id', async () => {
const expectedResult = Symbol();
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
savedObjectsClient.delete.mockResolvedValueOnce(expectedResult);
const result = await actionsClient.delete({ id: '1' });
expect(result).toEqual(expectedResult);
@@ -296,16 +283,11 @@ describe('delete()', () => {
describe('update()', () => {
test('updates an action with all given properties', async () => {
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
actionTypeRegistry.register({
id: 'my-action-type',
name: 'My action type',
executor,
});
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
savedObjectsClient.get.mockResolvedValueOnce({
id: '1',
type: 'action',
@@ -362,11 +344,6 @@ describe('update()', () => {
});
test('validates config', async () => {
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
actionTypeRegistry.register({
id: 'my-action-type',
name: 'My action type',
@@ -400,16 +377,11 @@ describe('update()', () => {
});
test('encrypts action type options unless specified not to', async () => {
- const actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams);
actionTypeRegistry.register({
id: 'my-action-type',
name: 'My action type',
executor,
});
- const actionsClient = new ActionsClient({
- actionTypeRegistry,
- savedObjectsClient,
- });
savedObjectsClient.get.mockResolvedValueOnce({
id: 'my-action',
type: 'action',
diff --git a/x-pack/legacy/plugins/actions/server/actions_client.ts b/x-pack/legacy/plugins/actions/server/actions_client.ts
index 823cb55abaf5e..1e4135bd0d66f 100644
--- a/x-pack/legacy/plugins/actions/server/actions_client.ts
+++ b/x-pack/legacy/plugins/actions/server/actions_client.ts
@@ -4,10 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { SavedObjectsClientContract, SavedObjectAttributes, SavedObject } from 'src/core/server';
+import {
+ IScopedClusterClient,
+ SavedObjectsClientContract,
+ SavedObjectAttributes,
+ SavedObject,
+} from 'src/core/server';
+
import { ActionTypeRegistry } from './action_type_registry';
import { validateConfig, validateSecrets } from './lib';
-import { ActionResult } from './types';
+import { ActionResult, FindActionResult, RawAction } from './types';
interface ActionUpdate extends SavedObjectAttributes {
description: string;
@@ -44,10 +50,12 @@ interface FindResult {
page: number;
perPage: number;
total: number;
- data: ActionResult[];
+ data: FindActionResult[];
}
interface ConstructorOptions {
+ defaultKibanaIndex: string;
+ scopedClusterClient: IScopedClusterClient;
actionTypeRegistry: ActionTypeRegistry;
savedObjectsClient: SavedObjectsClientContract;
}
@@ -58,12 +66,21 @@ interface UpdateOptions {
}
export class ActionsClient {
+ private readonly defaultKibanaIndex: string;
+ private readonly scopedClusterClient: IScopedClusterClient;
private readonly savedObjectsClient: SavedObjectsClientContract;
private readonly actionTypeRegistry: ActionTypeRegistry;
- constructor({ actionTypeRegistry, savedObjectsClient }: ConstructorOptions) {
+ constructor({
+ actionTypeRegistry,
+ defaultKibanaIndex,
+ scopedClusterClient,
+ savedObjectsClient,
+ }: ConstructorOptions) {
this.actionTypeRegistry = actionTypeRegistry;
this.savedObjectsClient = savedObjectsClient;
+ this.scopedClusterClient = scopedClusterClient;
+ this.defaultKibanaIndex = defaultKibanaIndex;
}
/**
@@ -134,16 +151,22 @@ export class ActionsClient {
* Find actions
*/
public async find({ options = {} }: FindOptions): Promise {
- const findResult = await this.savedObjectsClient.find({
+ const findResult = await this.savedObjectsClient.find({
...options,
type: 'action',
});
+ const data = await injectExtraFindData(
+ this.defaultKibanaIndex,
+ this.scopedClusterClient,
+ findResult.saved_objects.map(actionFromSavedObject)
+ );
+
return {
page: findResult.page,
perPage: findResult.per_page,
total: findResult.total,
- data: findResult.saved_objects.map(actionFromSavedObject),
+ data,
};
}
@@ -155,9 +178,64 @@ export class ActionsClient {
}
}
-function actionFromSavedObject(savedObject: SavedObject) {
+function actionFromSavedObject(savedObject: SavedObject): ActionResult {
return {
id: savedObject.id,
...savedObject.attributes,
};
}
+
+async function injectExtraFindData(
+ defaultKibanaIndex: string,
+ scopedClusterClient: IScopedClusterClient,
+ actionResults: ActionResult[]
+): Promise {
+ const aggs: Record = {};
+ for (const actionResult of actionResults) {
+ aggs[actionResult.id] = {
+ filter: {
+ bool: {
+ must: {
+ nested: {
+ path: 'references',
+ query: {
+ bool: {
+ filter: {
+ bool: {
+ must: [
+ {
+ term: {
+ 'references.id': actionResult.id,
+ },
+ },
+ {
+ term: {
+ 'references.type': 'action',
+ },
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+ }
+ const aggregationResult = await scopedClusterClient.callAsInternalUser('search', {
+ index: defaultKibanaIndex,
+ body: {
+ aggs,
+ size: 0,
+ query: {
+ match_all: {},
+ },
+ },
+ });
+ return actionResults.map(actionResult => ({
+ ...actionResult,
+ referencedByCount: aggregationResult.aggregations[actionResult.id].doc_count,
+ }));
+}
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/result_type.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/result_type.ts
index c891f3bf218e7..256463251315d 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/result_type.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/result_type.ts
@@ -8,16 +8,15 @@
// Which is basically the Haskel equivalent of Rust/ML/Scala's Result
// I'll reach out to other's in Kibana to see if we can merge these into one type
-// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
-export type Ok = {
+export interface Ok {
tag: 'ok';
value: T;
-};
-// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
-export type Err = {
+}
+
+export interface Err {
tag: 'err';
error: E;
-};
+}
export type Result = Ok | Err;
export function asOk(value: T): Ok {
diff --git a/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts b/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts
index c724717bef9eb..5ed67ae82b0ce 100644
--- a/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts
@@ -8,7 +8,7 @@ import Hapi from 'hapi';
import { schema } from '@kbn/config-schema';
import { ActionExecutor } from './action_executor';
import { actionTypeRegistryMock } from '../action_type_registry.mock';
-import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/plugin.mock';
+import { encryptedSavedObjectsMock } from '../../../../../plugins/encrypted_saved_objects/server/mocks';
import {
savedObjectsClientMock,
loggingServiceMock,
@@ -24,7 +24,7 @@ function getServices() {
callCluster: jest.fn(),
};
}
-const encryptedSavedObjectsPlugin = encryptedSavedObjectsMock.create();
+const encryptedSavedObjectsPlugin = encryptedSavedObjectsMock.createStart();
const actionTypeRegistry = actionTypeRegistryMock.create();
const executeParams = {
diff --git a/x-pack/legacy/plugins/actions/server/lib/action_executor.ts b/x-pack/legacy/plugins/actions/server/lib/action_executor.ts
index aef389262f884..b7d4ea96ea0f8 100644
--- a/x-pack/legacy/plugins/actions/server/lib/action_executor.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/action_executor.ts
@@ -5,7 +5,7 @@
*/
import Hapi from 'hapi';
-import { EncryptedSavedObjectsStartContract } from '../shim';
+import { PluginStartContract as EncryptedSavedObjectsStartContract } from '../../../../../plugins/encrypted_saved_objects/server';
import { LegacySpacesPlugin as SpacesPluginStartContract } from '../../../spaces';
import { Logger } from '../../../../../../src/core/server';
import { validateParams, validateConfig, validateSecrets } from './validate_with_schema';
diff --git a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts b/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts
index 6411bc7462c9f..3e71725713070 100644
--- a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts
@@ -11,7 +11,7 @@ import { ConcreteTaskInstance, TaskStatus } from '../../../task_manager';
import { TaskRunnerFactory } from './task_runner_factory';
import { actionTypeRegistryMock } from '../action_type_registry.mock';
import { actionExecutorMock } from './action_executor.mock';
-import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/plugin.mock';
+import { encryptedSavedObjectsMock } from '../../../../../plugins/encrypted_saved_objects/server/mocks';
import {
savedObjectsClientMock,
loggingServiceMock,
@@ -19,7 +19,7 @@ import {
const spaceIdToNamespace = jest.fn();
const actionTypeRegistry = actionTypeRegistryMock.create();
-const mockedEncryptedSavedObjectsPlugin = encryptedSavedObjectsMock.create();
+const mockedEncryptedSavedObjectsPlugin = encryptedSavedObjectsMock.createStart();
const mockedActionExecutor = actionExecutorMock.create();
let fakeTimer: sinon.SinonFakeTimers;
diff --git a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.ts b/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.ts
index efe9ce7fa8be5..c0cca22b2c3eb 100644
--- a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.ts
@@ -7,7 +7,7 @@
import { ActionExecutorContract } from './action_executor';
import { ExecutorError } from './executor_error';
import { RunContext } from '../../../task_manager';
-import { EncryptedSavedObjectsStartContract } from '../shim';
+import { PluginStartContract as EncryptedSavedObjectsStartContract } from '../../../../../plugins/encrypted_saved_objects/server';
import { ActionTaskParams, GetBasePathFunction, SpaceIdToNamespaceFunction } from '../types';
export interface TaskRunnerContext {
diff --git a/x-pack/legacy/plugins/actions/server/plugin.ts b/x-pack/legacy/plugins/actions/server/plugin.ts
index 618c1d120c37a..26b65b1a1689a 100644
--- a/x-pack/legacy/plugins/actions/server/plugin.ts
+++ b/x-pack/legacy/plugins/actions/server/plugin.ts
@@ -22,6 +22,7 @@ import {
ActionsCoreStart,
ActionsPluginsSetup,
ActionsPluginsStart,
+ KibanaConfig,
} from './shim';
import {
createActionRoute,
@@ -44,6 +45,7 @@ export interface PluginStartContract {
}
export class Plugin {
+ private readonly kibana$: Observable;
private readonly config$: Observable;
private readonly logger: Logger;
private serverBasePath?: string;
@@ -51,10 +53,12 @@ export class Plugin {
private taskRunnerFactory?: TaskRunnerFactory;
private actionTypeRegistry?: ActionTypeRegistry;
private actionExecutor?: ActionExecutor;
+ private defaultKibanaIndex?: string;
constructor(initializerContext: ActionsPluginInitializerContext) {
this.logger = initializerContext.logger.get('plugins', 'alerting');
this.config$ = initializerContext.config.create();
+ this.kibana$ = initializerContext.config.kibana$;
}
public async setup(
@@ -63,6 +67,7 @@ export class Plugin {
): Promise {
const config = await this.config$.pipe(first()).toPromise();
this.adminClient = await core.elasticsearch.adminClient$.pipe(first()).toPromise();
+ this.defaultKibanaIndex = (await this.kibana$.pipe(first()).toPromise()).index;
plugins.xpack_main.registerFeature({
id: 'actions',
@@ -92,12 +97,12 @@ export class Plugin {
// - `secrets` properties will be encrypted
// - `config` will be included in AAD
// - everything else excluded from AAD
- plugins.encrypted_saved_objects.registerType({
+ plugins.encryptedSavedObjects.registerType({
type: 'action',
attributesToEncrypt: new Set(['secrets']),
attributesToExcludeFromAAD: new Set(['description']),
});
- plugins.encrypted_saved_objects.registerType({
+ plugins.encryptedSavedObjects.registerType({
type: 'action_task_params',
attributesToEncrypt: new Set(['apiKey']),
});
@@ -141,6 +146,7 @@ export class Plugin {
adminClient,
serverBasePath,
taskRunnerFactory,
+ defaultKibanaIndex,
} = this;
function getServices(request: any): Services {
@@ -163,11 +169,11 @@ export class Plugin {
logger,
spaces: plugins.spaces,
getServices,
- encryptedSavedObjectsPlugin: plugins.encrypted_saved_objects,
+ encryptedSavedObjectsPlugin: plugins.encryptedSavedObjects,
actionTypeRegistry: actionTypeRegistry!,
});
taskRunnerFactory!.initialize({
- encryptedSavedObjectsPlugin: plugins.encrypted_saved_objects,
+ encryptedSavedObjectsPlugin: plugins.encryptedSavedObjects,
getBasePath,
spaceIdToNamespace,
});
@@ -186,6 +192,8 @@ export class Plugin {
return new ActionsClient({
savedObjectsClient,
actionTypeRegistry: actionTypeRegistry!,
+ defaultKibanaIndex: defaultKibanaIndex!,
+ scopedClusterClient: adminClient!.asScoped(request),
});
},
};
diff --git a/x-pack/legacy/plugins/actions/server/routes/_mock_server.ts b/x-pack/legacy/plugins/actions/server/routes/_mock_server.ts
index 7f2341c1aa010..23356cedb3ab8 100644
--- a/x-pack/legacy/plugins/actions/server/routes/_mock_server.ts
+++ b/x-pack/legacy/plugins/actions/server/routes/_mock_server.ts
@@ -8,7 +8,7 @@ import Hapi from 'hapi';
import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks';
import { actionsClientMock } from '../actions_client.mock';
import { actionTypeRegistryMock } from '../action_type_registry.mock';
-import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/plugin.mock';
+import { encryptedSavedObjectsMock } from '../../../../../plugins/encrypted_saved_objects/server/mocks';
const defaultConfig = {
'kibana.index': '.kibana',
@@ -22,7 +22,8 @@ export function createMockServer(config: Record = defaultConfig) {
const actionsClient = actionsClientMock.create();
const actionTypeRegistry = actionTypeRegistryMock.create();
const savedObjectsClient = savedObjectsClientMock.create();
- const encryptedSavedObjects = encryptedSavedObjectsMock.create();
+ const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup();
+ const encryptedSavedObjectsStart = encryptedSavedObjectsMock.createStart();
server.config = () => {
return {
@@ -49,21 +50,16 @@ export function createMockServer(config: Record = defaultConfig) {
},
});
- server.register({
- name: 'encrypted_saved_objects',
- register(pluginServer: Hapi.Server) {
- pluginServer.expose('isEncryptionError', encryptedSavedObjects.isEncryptionError);
- pluginServer.expose('registerType', encryptedSavedObjects.registerType);
- pluginServer.expose(
- 'getDecryptedAsInternalUser',
- encryptedSavedObjects.getDecryptedAsInternalUser
- );
- },
- });
-
server.decorate('request', 'getSavedObjectsClient', () => savedObjectsClient);
server.decorate('request', 'getActionsClient', () => actionsClient);
server.decorate('request', 'getBasePath', () => '/s/my-space');
- return { server, savedObjectsClient, actionsClient, actionTypeRegistry, encryptedSavedObjects };
+ return {
+ server,
+ savedObjectsClient,
+ actionsClient,
+ actionTypeRegistry,
+ encryptedSavedObjectsSetup,
+ encryptedSavedObjectsStart,
+ };
}
diff --git a/x-pack/legacy/plugins/actions/server/shim.ts b/x-pack/legacy/plugins/actions/server/shim.ts
index c457a40a78b67..0da6b84f2cc69 100644
--- a/x-pack/legacy/plugins/actions/server/shim.ts
+++ b/x-pack/legacy/plugins/actions/server/shim.ts
@@ -12,7 +12,10 @@ import { TaskManager } from '../../task_manager';
import { XPackMainPlugin } from '../../xpack_main/xpack_main';
import KbnServer from '../../../../../src/legacy/server/kbn_server';
import { LegacySpacesPlugin as SpacesPluginStartContract } from '../../spaces';
-import { EncryptedSavedObjectsPlugin } from '../../encrypted_saved_objects';
+import {
+ PluginSetupContract as EncryptedSavedObjectsSetupContract,
+ PluginStartContract as EncryptedSavedObjectsStartContract,
+} from '../../../../plugins/encrypted_saved_objects/server';
import { PluginSetupContract as SecurityPlugin } from '../../../../plugins/security/server';
import {
CoreSetup,
@@ -24,13 +27,16 @@ import {
// due to being marked as dependencies
interface Plugins extends Hapi.PluginProperties {
task_manager: TaskManager;
- encrypted_saved_objects: EncryptedSavedObjectsPlugin;
}
export interface Server extends Legacy.Server {
plugins: Plugins;
}
+export interface KibanaConfig {
+ index: string;
+}
+
/**
* Shim what we're thinking setup and start contracts will look like
*/
@@ -38,15 +44,10 @@ export type TaskManagerStartContract = Pick;
export type SecurityPluginSetupContract = Pick;
export type SecurityPluginStartContract = Pick;
-export type EncryptedSavedObjectsSetupContract = Pick;
export type TaskManagerSetupContract = Pick<
TaskManager,
'addMiddleware' | 'registerTaskDefinitions'
>;
-export type EncryptedSavedObjectsStartContract = Pick<
- EncryptedSavedObjectsPlugin,
- 'isEncryptionError' | 'getDecryptedAsInternalUser'
->;
/**
* New platform interfaces
@@ -54,6 +55,7 @@ export type EncryptedSavedObjectsStartContract = Pick<
export interface ActionsPluginInitializerContext {
logger: LoggerFactory;
config: {
+ kibana$: Rx.Observable;
create(): Rx.Observable;
};
}
@@ -73,12 +75,12 @@ export interface ActionsPluginsSetup {
security?: SecurityPluginSetupContract;
task_manager: TaskManagerSetupContract;
xpack_main: XPackMainPluginSetupContract;
- encrypted_saved_objects: EncryptedSavedObjectsSetupContract;
+ encryptedSavedObjects: EncryptedSavedObjectsSetupContract;
}
export interface ActionsPluginsStart {
security?: SecurityPluginStartContract;
spaces: () => SpacesPluginStartContract | undefined;
- encrypted_saved_objects: EncryptedSavedObjectsStartContract;
+ encryptedSavedObjects: EncryptedSavedObjectsStartContract;
task_manager: TaskManagerStartContract;
}
@@ -101,6 +103,9 @@ export function shim(
const initializerContext: ActionsPluginInitializerContext = {
logger: newPlatform.coreContext.logger,
config: {
+ kibana$: Rx.of({
+ index: server.config().get('kibana.index'),
+ }),
create() {
return Rx.of({
enabled: server.config().get('xpack.actions.enabled') as boolean,
@@ -126,7 +131,8 @@ export function shim(
security: newPlatform.setup.plugins.security as SecurityPluginSetupContract | undefined,
task_manager: server.plugins.task_manager,
xpack_main: server.plugins.xpack_main,
- encrypted_saved_objects: server.plugins.encrypted_saved_objects,
+ encryptedSavedObjects: newPlatform.setup.plugins
+ .encryptedSavedObjects as EncryptedSavedObjectsSetupContract,
};
const pluginsStart: ActionsPluginsStart = {
@@ -134,7 +140,8 @@ export function shim(
// TODO: Currently a function because it's an optional dependency that
// initializes after this function is called
spaces: () => server.plugins.spaces,
- encrypted_saved_objects: server.plugins.encrypted_saved_objects,
+ encryptedSavedObjects: newPlatform.start.plugins
+ .encryptedSavedObjects as EncryptedSavedObjectsStartContract,
task_manager: server.plugins.task_manager,
};
diff --git a/x-pack/legacy/plugins/actions/server/types.ts b/x-pack/legacy/plugins/actions/server/types.ts
index 9db89aea1b38d..1ee5022338a46 100644
--- a/x-pack/legacy/plugins/actions/server/types.ts
+++ b/x-pack/legacy/plugins/actions/server/types.ts
@@ -45,6 +45,10 @@ export interface ActionResult {
config: Record;
}
+export interface FindActionResult extends ActionResult {
+ referencedByCount: number;
+}
+
// the result returned from an action type executor function
export interface ActionTypeExecutorResult {
status: 'ok' | 'error';
diff --git a/x-pack/legacy/plugins/alerting/README.md b/x-pack/legacy/plugins/alerting/README.md
index ffe3185328abd..1b90cb78d870c 100644
--- a/x-pack/legacy/plugins/alerting/README.md
+++ b/x-pack/legacy/plugins/alerting/README.md
@@ -198,6 +198,7 @@ Payload:
|Property|Description|Type|
|---|---|---|
|enabled|Indicate if you want the alert to start executing on an interval basis after it has been created.|boolean|
+|name|A name to reference and search in the future.|string|
|alertTypeId|The id value of the alert type you want to call when the alert is scheduled to execute.|string|
|interval|The interval in seconds, minutes, hours or days the alert should execute. Example: `10s`, `5m`, `1h`, `1d`.|string|
|alertTypeParams|The parameters to pass in to the alert type executor `params` value. This will also validate against the alert type params validator if defined.|object|
@@ -242,6 +243,7 @@ Payload:
|Property|Description|Type|
|---|---|---|
|interval|The interval in seconds, minutes, hours or days the alert should execute. Example: `10s`, `5m`, `1h`, `1d`.|string|
+|name|A name to reference and search in the future.|string|
|alertTypeParams|The parameters to pass in to the alert type executor `params` value. This will also validate against the alert type params validator if defined.|object|
|actions|Array of the following: - `group` (string): We support grouping actions in the scenario of escalations or different types of alert instances. If you don't need this, feel free to use `default` as a value. - `id` (string): The id of the action saved object to execute. - `params` (object): There map to the `params` the action type will receive. In order to help apply context to strings, we handle them as mustache templates and pass in a default set of context. (see templating actions).|array|
diff --git a/x-pack/legacy/plugins/alerting/index.ts b/x-pack/legacy/plugins/alerting/index.ts
index 22db92baa8d28..b3e33f782688c 100644
--- a/x-pack/legacy/plugins/alerting/index.ts
+++ b/x-pack/legacy/plugins/alerting/index.ts
@@ -22,12 +22,12 @@ export function alerting(kibana: any) {
return new kibana.Plugin({
id: 'alerting',
configPrefix: 'xpack.alerting',
- require: ['kibana', 'elasticsearch', 'actions', 'task_manager', 'encrypted_saved_objects'],
+ require: ['kibana', 'elasticsearch', 'actions', 'task_manager', 'encryptedSavedObjects'],
isEnabled(config: Legacy.KibanaConfig) {
return (
config.get('xpack.alerting.enabled') === true &&
config.get('xpack.actions.enabled') === true &&
- config.get('xpack.encrypted_saved_objects.enabled') === true &&
+ config.get('xpack.encryptedSavedObjects.enabled') === true &&
config.get('xpack.task_manager.enabled') === true
);
},
diff --git a/x-pack/legacy/plugins/alerting/mappings.json b/x-pack/legacy/plugins/alerting/mappings.json
index bc648e874cfa4..ff60ccc98cbaa 100644
--- a/x-pack/legacy/plugins/alerting/mappings.json
+++ b/x-pack/legacy/plugins/alerting/mappings.json
@@ -4,6 +4,9 @@
"enabled": {
"type": "boolean"
},
+ "name": {
+ "type": "text"
+ },
"alertTypeId": {
"type": "keyword"
},
diff --git a/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts b/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts
index 093f5f7484004..99af7db2ef8d7 100644
--- a/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts
@@ -43,6 +43,7 @@ const mockedDate = new Date('2019-02-12T21:01:22.479Z');
function getMockData(overwrites: Record = {}) {
return {
enabled: true,
+ name: 'abc',
alertTypeId: '123',
interval: '10s',
throttle: null,
@@ -172,6 +173,7 @@ describe('create()', () => {
"interval": "10s",
"muteAll": false,
"mutedInstanceIds": Array [],
+ "name": "abc",
"throttle": null,
"updatedBy": "elastic",
}
@@ -504,6 +506,7 @@ describe('create()', () => {
},
],
alertTypeId: '123',
+ name: 'abc',
alertTypeParams: { bar: true },
apiKey: Buffer.from('123:abc').toString('base64'),
apiKeyOwner: 'elastic',
@@ -1173,6 +1176,7 @@ describe('update()', () => {
id: '1',
data: {
interval: '10s',
+ name: 'abc',
alertTypeParams: {
bar: true,
},
@@ -1230,6 +1234,7 @@ describe('update()', () => {
"apiKeyOwner": null,
"enabled": true,
"interval": "10s",
+ "name": "abc",
"scheduledTaskId": "task-123",
"updatedBy": "elastic",
}
@@ -1304,6 +1309,7 @@ describe('update()', () => {
id: '1',
data: {
interval: '10s',
+ name: 'abc',
alertTypeParams: {
bar: true,
},
@@ -1362,6 +1368,7 @@ describe('update()', () => {
"apiKeyOwner": "elastic",
"enabled": true,
"interval": "10s",
+ "name": "abc",
"scheduledTaskId": "task-123",
"updatedBy": "elastic",
}
@@ -1406,6 +1413,7 @@ describe('update()', () => {
id: '1',
data: {
interval: '10s',
+ name: 'abc',
alertTypeParams: {
bar: true,
},
diff --git a/x-pack/legacy/plugins/alerting/server/alerts_client.ts b/x-pack/legacy/plugins/alerting/server/alerts_client.ts
index 39d0277ff53b3..b92af43a1f1c6 100644
--- a/x-pack/legacy/plugins/alerting/server/alerts_client.ts
+++ b/x-pack/legacy/plugins/alerting/server/alerts_client.ts
@@ -72,6 +72,7 @@ interface CreateOptions {
interface UpdateOptions {
id: string;
data: {
+ name: string;
interval: string;
actions: AlertAction[];
alertTypeParams: Record;
diff --git a/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.test.ts b/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.test.ts
index 23591692bca1f..dcc74ed9488ce 100644
--- a/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.test.ts
@@ -9,7 +9,7 @@ import { schema } from '@kbn/config-schema';
import { AlertExecutorOptions } from '../types';
import { ConcreteTaskInstance } from '../../../task_manager';
import { TaskRunnerContext, TaskRunnerFactory } from './task_runner_factory';
-import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/plugin.mock';
+import { encryptedSavedObjectsMock } from '../../../../../plugins/encrypted_saved_objects/server/mocks';
import {
savedObjectsClientMock,
loggingServiceMock,
@@ -52,7 +52,7 @@ beforeAll(() => {
afterAll(() => fakeTimer.restore());
const savedObjectsClient = savedObjectsClientMock.create();
-const encryptedSavedObjectsPlugin = encryptedSavedObjectsMock.create();
+const encryptedSavedObjectsPlugin = encryptedSavedObjectsMock.createStart();
const services = {
log: jest.fn(),
callCluster: jest.fn(),
diff --git a/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.ts b/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.ts
index ca11dc8533996..0c6bd1b4a777a 100644
--- a/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.ts
+++ b/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.ts
@@ -11,7 +11,7 @@ import { createAlertInstanceFactory } from './create_alert_instance_factory';
import { AlertInstance } from './alert_instance';
import { getNextRunAt } from './get_next_run_at';
import { validateAlertTypeParams } from './validate_alert_type_params';
-import { EncryptedSavedObjectsStartContract } from '../shim';
+import { PluginStartContract as EncryptedSavedObjectsStartContract } from '../../../../../plugins/encrypted_saved_objects/server';
import { PluginStartContract as ActionsPluginStartContract } from '../../../actions';
import {
AlertType,
diff --git a/x-pack/legacy/plugins/alerting/server/plugin.ts b/x-pack/legacy/plugins/alerting/server/plugin.ts
index d6c6d5907e7ac..c50bc795757f3 100644
--- a/x-pack/legacy/plugins/alerting/server/plugin.ts
+++ b/x-pack/legacy/plugins/alerting/server/plugin.ts
@@ -85,7 +85,7 @@ export class Plugin {
});
// Encrypted attributes
- plugins.encrypted_saved_objects.registerType({
+ plugins.encryptedSavedObjects.registerType({
type: 'alert',
attributesToEncrypt: new Set(['apiKey']),
attributesToExcludeFromAAD: new Set([
@@ -147,7 +147,7 @@ export class Plugin {
};
},
executeAction: plugins.actions.execute,
- encryptedSavedObjectsPlugin: plugins.encrypted_saved_objects,
+ encryptedSavedObjectsPlugin: plugins.encryptedSavedObjects,
spaceIdToNamespace(spaceId?: string): string | undefined {
const spacesPlugin = plugins.spaces();
return spacesPlugin && spaceId ? spacesPlugin.spaceIdToNamespace(spaceId) : undefined;
diff --git a/x-pack/legacy/plugins/alerting/server/routes/create.test.ts b/x-pack/legacy/plugins/alerting/server/routes/create.test.ts
index 3751aa968b3de..bd153150849c8 100644
--- a/x-pack/legacy/plugins/alerting/server/routes/create.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/routes/create.test.ts
@@ -12,6 +12,7 @@ server.route(createAlertRoute);
const mockedAlert = {
alertTypeId: '1',
+ name: 'abc',
interval: '10s',
alertTypeParams: {
bar: true,
@@ -44,24 +45,25 @@ test('creates an alert with proper parameters', async () => {
expect(statusCode).toBe(200);
const response = JSON.parse(payload);
expect(response).toMatchInlineSnapshot(`
+ Object {
+ "actions": Array [
Object {
- "actions": Array [
- Object {
- "group": "default",
- "id": "2",
- "params": Object {
- "foo": true,
- },
- },
- ],
- "alertTypeId": "1",
- "alertTypeParams": Object {
- "bar": true,
+ "group": "default",
+ "id": "2",
+ "params": Object {
+ "foo": true,
},
- "id": "123",
- "interval": "10s",
- }
- `);
+ },
+ ],
+ "alertTypeId": "1",
+ "alertTypeParams": Object {
+ "bar": true,
+ },
+ "id": "123",
+ "interval": "10s",
+ "name": "abc",
+ }
+ `);
expect(alertsClient.create).toHaveBeenCalledTimes(1);
expect(alertsClient.create.mock.calls[0]).toMatchInlineSnapshot(`
Array [
@@ -82,6 +84,7 @@ test('creates an alert with proper parameters', async () => {
},
"enabled": true,
"interval": "10s",
+ "name": "abc",
"throttle": null,
},
},
@@ -107,6 +110,7 @@ test('creates an alert with proper parameters', async () => {
},
"enabled": true,
"interval": "10s",
+ "name": "abc",
"throttle": null,
},
},
diff --git a/x-pack/legacy/plugins/alerting/server/routes/create.ts b/x-pack/legacy/plugins/alerting/server/routes/create.ts
index 984153d81e0f8..14f72b0041e76 100644
--- a/x-pack/legacy/plugins/alerting/server/routes/create.ts
+++ b/x-pack/legacy/plugins/alerting/server/routes/create.ts
@@ -12,6 +12,7 @@ import { getDurationSchema } from '../lib';
interface ScheduleRequest extends Hapi.Request {
payload: {
enabled: boolean;
+ name: string;
alertTypeId: string;
interval: string;
actions: AlertAction[];
@@ -32,6 +33,7 @@ export const createAlertRoute = {
payload: Joi.object()
.keys({
enabled: Joi.boolean().default(true),
+ name: Joi.string().required(),
alertTypeId: Joi.string().required(),
throttle: getDurationSchema().default(null),
interval: getDurationSchema().required(),
diff --git a/x-pack/legacy/plugins/alerting/server/routes/update.test.ts b/x-pack/legacy/plugins/alerting/server/routes/update.test.ts
index 9e4f18fa1b40d..2237d8245097c 100644
--- a/x-pack/legacy/plugins/alerting/server/routes/update.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/routes/update.test.ts
@@ -36,6 +36,7 @@ test('calls the update function with proper parameters', async () => {
url: '/api/alert/1',
payload: {
throttle: null,
+ name: 'abc',
interval: '12s',
alertTypeParams: {
otherField: false,
@@ -75,6 +76,7 @@ test('calls the update function with proper parameters', async () => {
"otherField": false,
},
"interval": "12s",
+ "name": "abc",
"throttle": null,
},
"id": "1",
diff --git a/x-pack/legacy/plugins/alerting/server/routes/update.ts b/x-pack/legacy/plugins/alerting/server/routes/update.ts
index 2b95b7bc34054..09362295ae73b 100644
--- a/x-pack/legacy/plugins/alerting/server/routes/update.ts
+++ b/x-pack/legacy/plugins/alerting/server/routes/update.ts
@@ -15,6 +15,7 @@ interface UpdateRequest extends Hapi.Request {
};
payload: {
alertTypeId: string;
+ name: string;
interval: string;
actions: AlertAction[];
alertTypeParams: Record;
@@ -36,6 +37,7 @@ export const updateAlertRoute = {
throttle: getDurationSchema()
.required()
.allow(null),
+ name: Joi.string().required(),
interval: getDurationSchema().required(),
alertTypeParams: Joi.object().required(),
actions: Joi.array()
diff --git a/x-pack/legacy/plugins/alerting/server/shim.ts b/x-pack/legacy/plugins/alerting/server/shim.ts
index c977fda451df1..d86eab2038095 100644
--- a/x-pack/legacy/plugins/alerting/server/shim.ts
+++ b/x-pack/legacy/plugins/alerting/server/shim.ts
@@ -10,7 +10,10 @@ import { LegacySpacesPlugin as SpacesPluginStartContract } from '../../spaces';
import { TaskManager } from '../../task_manager';
import { XPackMainPlugin } from '../../xpack_main/xpack_main';
import KbnServer from '../../../../../src/legacy/server/kbn_server';
-import { EncryptedSavedObjectsPlugin } from '../../encrypted_saved_objects';
+import {
+ PluginSetupContract as EncryptedSavedObjectsSetupContract,
+ PluginStartContract as EncryptedSavedObjectsStartContract,
+} from '../../../../plugins/encrypted_saved_objects/server';
import { PluginSetupContract as SecurityPlugin } from '../../../../plugins/security/server';
import {
CoreSetup,
@@ -28,7 +31,6 @@ import {
interface Plugins extends Hapi.PluginProperties {
actions: ActionsPlugin;
task_manager: TaskManager;
- encrypted_saved_objects: EncryptedSavedObjectsPlugin;
}
export interface Server extends Legacy.Server {
@@ -41,16 +43,11 @@ export interface Server extends Legacy.Server {
export type TaskManagerStartContract = Pick;
export type SecurityPluginSetupContract = Pick;
export type SecurityPluginStartContract = Pick;
-export type EncryptedSavedObjectsSetupContract = Pick;
export type XPackMainPluginSetupContract = Pick;
export type TaskManagerSetupContract = Pick<
TaskManager,
'addMiddleware' | 'registerTaskDefinitions'
>;
-export type EncryptedSavedObjectsStartContract = Pick<
- EncryptedSavedObjectsPlugin,
- 'isEncryptionError' | 'getDecryptedAsInternalUser'
->;
/**
* New platform interfaces
@@ -75,13 +72,13 @@ export interface AlertingPluginsSetup {
task_manager: TaskManagerSetupContract;
actions: ActionsPluginSetupContract;
xpack_main: XPackMainPluginSetupContract;
- encrypted_saved_objects: EncryptedSavedObjectsSetupContract;
+ encryptedSavedObjects: EncryptedSavedObjectsSetupContract;
}
export interface AlertingPluginsStart {
actions: ActionsPluginStartContract;
security?: SecurityPluginStartContract;
spaces: () => SpacesPluginStartContract | undefined;
- encrypted_saved_objects: EncryptedSavedObjectsStartContract;
+ encryptedSavedObjects: EncryptedSavedObjectsStartContract;
task_manager: TaskManagerStartContract;
}
@@ -122,7 +119,8 @@ export function shim(
task_manager: server.plugins.task_manager,
actions: server.plugins.actions.setup,
xpack_main: server.plugins.xpack_main,
- encrypted_saved_objects: server.plugins.encrypted_saved_objects,
+ encryptedSavedObjects: newPlatform.setup.plugins
+ .encryptedSavedObjects as EncryptedSavedObjectsSetupContract,
};
const pluginsStart: AlertingPluginsStart = {
@@ -131,7 +129,8 @@ export function shim(
// TODO: Currently a function because it's an optional dependency that
// initializes after this function is called
spaces: () => server.plugins.spaces,
- encrypted_saved_objects: server.plugins.encrypted_saved_objects,
+ encryptedSavedObjects: newPlatform.start.plugins
+ .encryptedSavedObjects as EncryptedSavedObjectsStartContract,
task_manager: server.plugins.task_manager,
};
diff --git a/x-pack/legacy/plugins/alerting/server/types.ts b/x-pack/legacy/plugins/alerting/server/types.ts
index 3c71412da2c89..94b81c9e1b576 100644
--- a/x-pack/legacy/plugins/alerting/server/types.ts
+++ b/x-pack/legacy/plugins/alerting/server/types.ts
@@ -60,6 +60,7 @@ export interface RawAlertAction extends SavedObjectAttributes {
export interface Alert {
enabled: boolean;
+ name: string;
alertTypeId: string;
interval: string;
actions: AlertAction[];
@@ -76,6 +77,7 @@ export interface Alert {
export interface RawAlert extends SavedObjectAttributes {
enabled: boolean;
+ name: string;
alertTypeId: string;
interval: string;
actions: RawAlertAction[];
diff --git a/x-pack/legacy/plugins/apm/common/projections/errors.ts b/x-pack/legacy/plugins/apm/common/projections/errors.ts
index c3094f5cbb0b6..adbd2eb1d6d27 100644
--- a/x-pack/legacy/plugins/apm/common/projections/errors.ts
+++ b/x-pack/legacy/plugins/apm/common/projections/errors.ts
@@ -19,10 +19,10 @@ export function getErrorGroupsProjection({
setup: Setup;
serviceName: string;
}) {
- const { start, end, uiFiltersES, config } = setup;
+ const { start, end, uiFiltersES, indices } = setup;
return {
- index: config.get('apm_oss.errorIndices'),
+ index: indices['apm_oss.errorIndices'],
body: {
query: {
bool: {
diff --git a/x-pack/legacy/plugins/apm/common/projections/metrics.ts b/x-pack/legacy/plugins/apm/common/projections/metrics.ts
index 5c9eeb54744d7..25d1484624e15 100644
--- a/x-pack/legacy/plugins/apm/common/projections/metrics.ts
+++ b/x-pack/legacy/plugins/apm/common/projections/metrics.ts
@@ -34,7 +34,7 @@ export function getMetricsProjection({
serviceName: string;
serviceNodeName?: string;
}) {
- const { start, end, uiFiltersES, config } = setup;
+ const { start, end, uiFiltersES, indices } = setup;
const filter = [
{ term: { [SERVICE_NAME]: serviceName } },
@@ -45,7 +45,7 @@ export function getMetricsProjection({
];
return {
- index: config.get('apm_oss.metricsIndices'),
+ index: indices['apm_oss.metricsIndices'],
body: {
query: {
bool: {
diff --git a/x-pack/legacy/plugins/apm/common/projections/services.ts b/x-pack/legacy/plugins/apm/common/projections/services.ts
index ab72211f92aa7..e889899e11634 100644
--- a/x-pack/legacy/plugins/apm/common/projections/services.ts
+++ b/x-pack/legacy/plugins/apm/common/projections/services.ts
@@ -9,13 +9,13 @@ import { SERVICE_NAME, PROCESSOR_EVENT } from '../elasticsearch_fieldnames';
import { rangeFilter } from '../../server/lib/helpers/range_filter';
export function getServicesProjection({ setup }: { setup: Setup }) {
- const { start, end, uiFiltersES, config } = setup;
+ const { start, end, uiFiltersES, indices } = setup;
return {
index: [
- config.get('apm_oss.metricsIndices'),
- config.get('apm_oss.errorIndices'),
- config.get('apm_oss.transactionIndices')
+ indices['apm_oss.metricsIndices'],
+ indices['apm_oss.errorIndices'],
+ indices['apm_oss.transactionIndices']
],
body: {
size: 0,
diff --git a/x-pack/legacy/plugins/apm/common/projections/transactions.ts b/x-pack/legacy/plugins/apm/common/projections/transactions.ts
index 63abb0572df87..fb249340c867c 100644
--- a/x-pack/legacy/plugins/apm/common/projections/transactions.ts
+++ b/x-pack/legacy/plugins/apm/common/projections/transactions.ts
@@ -24,7 +24,7 @@ export function getTransactionsProjection({
transactionName?: string;
transactionType?: string;
}) {
- const { start, end, uiFiltersES, config } = setup;
+ const { start, end, uiFiltersES, indices } = setup;
const transactionNameFilter = transactionName
? [{ term: { [TRANSACTION_NAME]: transactionName } }]
@@ -48,7 +48,7 @@ export function getTransactionsProjection({
};
return {
- index: config.get('apm_oss.transactionIndices'),
+ index: indices['apm_oss.transactionIndices'],
body: {
query: {
bool
diff --git a/x-pack/legacy/plugins/apm/index.ts b/x-pack/legacy/plugins/apm/index.ts
index 4d3d2b210bbae..556bce9d37bb5 100644
--- a/x-pack/legacy/plugins/apm/index.ts
+++ b/x-pack/legacy/plugins/apm/index.ts
@@ -43,8 +43,7 @@ export const apm: LegacyPluginInitializer = kibana => {
apmUiEnabled: config.get('xpack.apm.ui.enabled'),
// TODO: rename to apm_oss.indexPatternTitle in 7.0 (breaking change)
apmIndexPatternTitle: config.get('apm_oss.indexPattern'),
- apmServiceMapEnabled: config.get('xpack.apm.serviceMapEnabled'),
- apmTransactionIndices: config.get('apm_oss.transactionIndices')
+ apmServiceMapEnabled: config.get('xpack.apm.serviceMapEnabled')
};
},
hacks: ['plugins/apm/hacks/toggle_app_link_in_nav'],
diff --git a/x-pack/legacy/plugins/apm/mappings.json b/x-pack/legacy/plugins/apm/mappings.json
index 26075d406c993..0b31798242fad 100644
--- a/x-pack/legacy/plugins/apm/mappings.json
+++ b/x-pack/legacy/plugins/apm/mappings.json
@@ -41,5 +41,30 @@
}
}
}
+ },
+ "apm-indices": {
+ "properties": {
+ "apm_oss.sourcemapIndices": {
+ "type": "keyword"
+ },
+ "apm_oss.errorIndices": {
+ "type": "keyword"
+ },
+ "apm_oss.onboardingIndices": {
+ "type": "keyword"
+ },
+ "apm_oss.spanIndices": {
+ "type": "keyword"
+ },
+ "apm_oss.transactionIndices": {
+ "type": "keyword"
+ },
+ "apm_oss.metricsIndices": {
+ "type": "keyword"
+ },
+ "apm_oss.apmAgentConfigurationIndex": {
+ "type": "keyword"
+ }
+ }
}
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ErrorTabs.tsx b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ErrorTabs.tsx
index 253580ce5cecd..33b20b0f0f226 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ErrorTabs.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ErrorTabs.tsx
@@ -17,7 +17,7 @@ export interface ErrorTab {
export const logStacktraceTab: ErrorTab = {
key: 'log_stacktrace',
label: i18n.translate('xpack.apm.propertiesTable.tabs.logStacktraceLabel', {
- defaultMessage: 'Log stacktrace'
+ defaultMessage: 'Log stack trace'
})
};
@@ -26,7 +26,7 @@ export const exceptionStacktraceTab: ErrorTab = {
label: i18n.translate(
'xpack.apm.propertiesTable.tabs.exceptionStacktraceLabel',
{
- defaultMessage: 'Exception stacktrace'
+ defaultMessage: 'Exception stack trace'
}
)
};
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ExceptionStacktrace.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ExceptionStacktrace.test.tsx
new file mode 100644
index 0000000000000..8ec9c604e7038
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ExceptionStacktrace.test.tsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { ExceptionStacktrace } from './ExceptionStacktrace';
+
+describe('ExceptionStacktrace', () => {
+ describe('render', () => {
+ it('renders', () => {
+ const props = { exceptions: [] };
+
+ expect(() =>
+ shallow( )
+ ).not.toThrowError();
+ });
+
+ describe('with a stack trace', () => {
+ it('renders the stack trace', () => {
+ const props = { exceptions: [{}] };
+
+ expect(
+ shallow( ).find('Stacktrace')
+ ).toHaveLength(1);
+ });
+ });
+
+ describe('with more than one stack trace', () => {
+ it('renders a cause stack trace', () => {
+ const props = { exceptions: [{}, {}] };
+
+ expect(
+ shallow( ).find('CauseStacktrace')
+ ).toHaveLength(1);
+ });
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ExceptionStacktrace.tsx b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ExceptionStacktrace.tsx
new file mode 100644
index 0000000000000..13c904a119449
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/ExceptionStacktrace.tsx
@@ -0,0 +1,49 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { EuiTitle } from '@elastic/eui';
+import { idx } from '@kbn/elastic-idx/target';
+import { Exception } from '../../../../../typings/es_schemas/raw/ErrorRaw';
+import { Stacktrace } from '../../../shared/Stacktrace';
+import { CauseStacktrace } from '../../../shared/Stacktrace/CauseStacktrace';
+
+interface ExceptionStacktraceProps {
+ codeLanguage?: string;
+ exceptions: Exception[];
+}
+
+export function ExceptionStacktrace({
+ codeLanguage,
+ exceptions
+}: ExceptionStacktraceProps) {
+ const title = idx(exceptions, _ => _[0].message);
+
+ return (
+ <>
+
+ {title}
+
+ {exceptions.map((ex, index) => {
+ return index === 0 ? (
+
+ ) : (
+
+ );
+ })}
+ >
+ );
+}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/__snapshots__/index.test.tsx.snap
index be9d67f31cb11..39874c11b09bf 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/__snapshots__/index.test.tsx.snap
+++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/__snapshots__/index.test.tsx.snap
@@ -46,7 +46,7 @@ exports[`DetailView should render TabContent 1`] = `
currentTab={
Object {
"key": "exception_stacktrace",
- "label": "Exception stacktrace",
+ "label": "Exception stack trace",
}
}
error={
@@ -71,7 +71,7 @@ exports[`DetailView should render tabs 1`] = `
key="exception_stacktrace"
onClick={[Function]}
>
- Exception stacktrace
+ Exception stack trace
_.service.language.name);
- const excStackframes = idx(error, _ => _.error.exception[0].stacktrace);
+ const exceptions = idx(error, _ => _.error.exception) || [];
const logStackframes = idx(error, _ => _.error.log.stacktrace);
switch (currentTab.key) {
@@ -198,7 +199,10 @@ export function TabContent({
);
case exceptionStacktraceTab.key:
return (
-
+
);
default:
return ;
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Main/ProvideBreadcrumbs.tsx b/x-pack/legacy/plugins/apm/public/components/app/Main/ProvideBreadcrumbs.tsx
index 0c1d20d65b7b9..cfbe8b1edbd71 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Main/ProvideBreadcrumbs.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Main/ProvideBreadcrumbs.tsx
@@ -12,11 +12,10 @@ import {
RouteProps,
withRouter
} from 'react-router-dom';
-import { StringMap } from '../../../../typings/common';
import { RouteName } from './route_config/route_names';
type LocationMatch = Pick<
- RouteComponentProps>,
+ RouteComponentProps>,
'location' | 'match'
>;
@@ -75,7 +74,7 @@ export function getBreadcrumb({
return null;
}
- const match = matchPath>(currentPath, route);
+ const match = matchPath>(currentPath, route);
if (match) {
return parse({
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx
index 6c95095592fe4..4769fe6400ac1 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx
@@ -15,7 +15,9 @@ import { TransactionDetails } from '../../TransactionDetails';
import { Home } from '../../Home';
import { BreadcrumbRoute } from '../ProvideBreadcrumbs';
import { RouteName } from './route_names';
+import { Settings } from '../../Settings';
import { AgentConfigurations } from '../../Settings/AgentConfigurations';
+import { ApmIndices } from '../../Settings/ApmIndices';
import { toQuery } from '../../../shared/Links/url_helpers';
import { ServiceNodeMetrics } from '../../ServiceNodeMetrics';
import { resolveUrlParams } from '../../../../context/UrlParamsContext/resolveUrlParams';
@@ -69,12 +71,41 @@ export const routes: BreadcrumbRoute[] = [
{
exact: true,
path: '/settings',
- component: AgentConfigurations,
+ render: renderAsRedirectTo('/settings/agent-configuration'),
breadcrumb: i18n.translate('xpack.apm.breadcrumb.listSettingsTitle', {
defaultMessage: 'Settings'
}),
name: RouteName.SETTINGS
},
+ {
+ exact: true,
+ path: '/settings/apm-indices',
+ component: () => (
+
+
+
+ ),
+ breadcrumb: i18n.translate('xpack.apm.breadcrumb.settings.indicesTitle', {
+ defaultMessage: 'Indices'
+ }),
+ name: RouteName.INDICES
+ },
+ {
+ exact: true,
+ path: '/settings/agent-configuration',
+ component: () => (
+
+
+
+ ),
+ breadcrumb: i18n.translate(
+ 'xpack.apm.breadcrumb.settings.agentConfigurationTitle',
+ {
+ defaultMessage: 'Agent Configuration'
+ }
+ ),
+ name: RouteName.AGENT_CONFIGURATION
+ },
{
exact: true,
path: '/services/:serviceName',
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/route_names.tsx b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/route_names.tsx
index 3af5b217ca738..ab02e38ee9c9d 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/route_names.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/route_names.tsx
@@ -19,5 +19,7 @@ export enum RouteName {
TRANSACTION_TYPE = 'transaction_type',
TRANSACTION_NAME = 'transaction_name',
SETTINGS = 'settings',
+ AGENT_CONFIGURATION = 'agent_configuration',
+ INDICES = 'indices',
SERVICE_NODES = 'nodes'
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/__test__/createErrorGroupWatch.test.ts b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/__test__/createErrorGroupWatch.test.ts
index 4d6c3f4c116c9..c7860b81a7b1e 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/__test__/createErrorGroupWatch.test.ts
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/__test__/createErrorGroupWatch.test.ts
@@ -7,7 +7,6 @@
import { isArray, isObject, isString } from 'lodash';
import mustache from 'mustache';
import uuid from 'uuid';
-import { StringMap } from '../../../../../../typings/common';
// @ts-ignore
import * as rest from '../../../../../services/rest/watcher';
import { createErrorGroupWatch } from '../createErrorGroupWatch';
@@ -85,8 +84,11 @@ describe('createErrorGroupWatch', () => {
});
// Recursively iterate a nested structure and render strings as mustache templates
-type InputOutput = string | string[] | StringMap;
-function renderMustache(input: InputOutput, ctx: StringMap): InputOutput {
+type InputOutput = string | string[] | Record;
+function renderMustache(
+ input: InputOutput,
+ ctx: Record
+): InputOutput {
if (isString(input)) {
return mustache.render(input, {
ctx,
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/createErrorGroupWatch.ts b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/createErrorGroupWatch.ts
index 2617fef6de1d2..e7d06403b8f8e 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/createErrorGroupWatch.ts
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/createErrorGroupWatch.ts
@@ -17,7 +17,6 @@ import {
PROCESSOR_EVENT,
SERVICE_NAME
} from '../../../../../common/elasticsearch_fieldnames';
-import { StringMap } from '../../../../../typings/common';
// @ts-ignore
import { createWatch } from '../../../../services/rest/watcher';
@@ -50,8 +49,8 @@ interface Arguments {
interface Actions {
log_error: { logging: { text: string } };
- slack_webhook?: StringMap;
- email?: StringMap;
+ slack_webhook?: Record;
+ email?: Record;
}
export async function createErrorGroupWatch({
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceNodeMetrics/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceNodeMetrics/index.tsx
index 2833b0476428c..79874d6648d0f 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceNodeMetrics/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceNodeMetrics/index.tsx
@@ -113,7 +113,7 @@ export function ServiceNodeMetrics() {
)
}}
- >
+ />
) : (
@@ -129,7 +129,7 @@ export function ServiceNodeMetrics() {
{host}
}
- >
+ />
{containerId}
}
- >
+ />
)}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx
index e2630efbcf500..9e95cfd0fad7f 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx
@@ -10,7 +10,6 @@ import {
EuiTitle,
EuiFlexGroup,
EuiFlexItem,
- EuiButtonEmpty,
EuiPanel,
EuiSpacer,
EuiButton
@@ -18,7 +17,6 @@ import {
import { isEmpty } from 'lodash';
import { useFetcher } from '../../../../hooks/useFetcher';
import { AgentConfigurationListAPIResponse } from '../../../../../server/lib/settings/agent_configuration/list_configurations';
-import { HomeLink } from '../../../shared/Links/apm/HomeLink';
import { AgentConfigurationList } from './AgentConfigurationList';
import { useTrackPageview } from '../../../../../../infra/public';
import { AddEditFlyout } from './AddEditFlyout';
@@ -62,30 +60,6 @@ export function AgentConfigurations() {
/>
)}
-
-
-
-
- {i18n.translate('xpack.apm.settings.agentConf.pageTitle', {
- defaultMessage: 'Settings'
- })}
-
-
-
-
-
-
- {i18n.translate(
- 'xpack.apm.settings.agentConf.returnToOverviewLinkLabel',
- { defaultMessage: 'Return to overview' }
- )}
-
-
-
-
-
-
-
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx
new file mode 100644
index 0000000000000..67957ae76b1f1
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx
@@ -0,0 +1,258 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useState, useEffect } from 'react';
+import { i18n } from '@kbn/i18n';
+import {
+ EuiTitle,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiPanel,
+ EuiSpacer,
+ EuiText,
+ EuiForm,
+ EuiFormRow,
+ EuiFieldText,
+ EuiButton,
+ EuiButtonEmpty
+} from '@elastic/eui';
+import { useFetcher } from '../../../../hooks/useFetcher';
+import { useCallApmApi } from '../../../../hooks/useCallApmApi';
+import { APMClient } from '../../../../services/rest/createCallApmApi';
+import { useKibanaCore } from '../../../../../../observability/public';
+
+const APM_INDEX_LABELS = [
+ {
+ configurationName: 'apm_oss.sourcemapIndices',
+ label: i18n.translate(
+ 'xpack.apm.settings.apmIndices.sourcemapIndicesLabel',
+ { defaultMessage: 'Sourcemap Indices' }
+ )
+ },
+ {
+ configurationName: 'apm_oss.errorIndices',
+ label: i18n.translate('xpack.apm.settings.apmIndices.errorIndicesLabel', {
+ defaultMessage: 'Error Indices'
+ })
+ },
+ {
+ configurationName: 'apm_oss.onboardingIndices',
+ label: i18n.translate(
+ 'xpack.apm.settings.apmIndices.onboardingIndicesLabel',
+ { defaultMessage: 'Onboarding Indices' }
+ )
+ },
+ {
+ configurationName: 'apm_oss.spanIndices',
+ label: i18n.translate('xpack.apm.settings.apmIndices.spanIndicesLabel', {
+ defaultMessage: 'Span Indices'
+ })
+ },
+ {
+ configurationName: 'apm_oss.transactionIndices',
+ label: i18n.translate(
+ 'xpack.apm.settings.apmIndices.transactionIndicesLabel',
+ { defaultMessage: 'Transaction Indices' }
+ )
+ },
+ {
+ configurationName: 'apm_oss.metricsIndices',
+ label: i18n.translate('xpack.apm.settings.apmIndices.metricsIndicesLabel', {
+ defaultMessage: 'Metrics Indices'
+ })
+ },
+ {
+ configurationName: 'apm_oss.apmAgentConfigurationIndex',
+ label: i18n.translate(
+ 'xpack.apm.settings.apmIndices.apmAgentConfigurationIndexLabel',
+ { defaultMessage: 'Agent Configuration Index' }
+ )
+ }
+];
+
+async function saveApmIndices({
+ callApmApi,
+ apmIndices
+}: {
+ callApmApi: APMClient;
+ apmIndices: Record;
+}) {
+ await callApmApi({
+ method: 'POST',
+ pathname: '/api/apm/settings/apm-indices/save',
+ params: {
+ body: apmIndices
+ }
+ });
+}
+
+export function ApmIndices() {
+ const {
+ notifications: { toasts }
+ } = useKibanaCore();
+
+ const [apmIndices, setApmIndices] = useState>({});
+ const [isSaving, setIsSaving] = useState(false);
+
+ const callApmApiFromHook = useCallApmApi();
+
+ const { data = [], status, refetch } = useFetcher(
+ callApmApi =>
+ callApmApi({ pathname: `/api/apm/settings/apm-index-settings` }),
+ []
+ );
+
+ useEffect(() => {
+ setApmIndices(
+ data.reduce(
+ (acc, { configurationName, savedValue }) => ({
+ ...acc,
+ [configurationName]: savedValue
+ }),
+ {}
+ )
+ );
+ }, [data]);
+
+ const handleApplyChangesEvent = async (
+ event:
+ | React.FormEvent
+ | React.MouseEvent
+ ) => {
+ event.preventDefault();
+ setIsSaving(true);
+ try {
+ await saveApmIndices({
+ callApmApi: callApmApiFromHook,
+ apmIndices
+ });
+ toasts.addSuccess({
+ title: i18n.translate(
+ 'xpack.apm.settings.apmIndices.applyChanges.succeeded.title',
+ { defaultMessage: 'Indices applied' }
+ ),
+ text: i18n.translate(
+ 'xpack.apm.settings.apmIndices.applyChanges.succeeded.text',
+ {
+ defaultMessage:
+ 'The indices changes were successfully applied. These changes are reflected immediately in the APM UI'
+ }
+ )
+ });
+ } catch (error) {
+ toasts.addDanger({
+ title: i18n.translate(
+ 'xpack.apm.settings.apmIndices.applyChanges.failed.title',
+ { defaultMessage: 'Indices could not be applied.' }
+ ),
+ text: i18n.translate(
+ 'xpack.apm.settings.apmIndices.applyChanges.failed.text',
+ {
+ defaultMessage:
+ 'Something went wrong when applying indices. Error: {errorMessage}',
+ values: { errorMessage: error.message }
+ }
+ )
+ });
+ }
+ setIsSaving(false);
+ };
+
+ const handleChangeIndexConfigurationEvent = async (
+ event: React.ChangeEvent
+ ) => {
+ const { name, value } = event.target;
+ setApmIndices({
+ ...apmIndices,
+ [name]: value
+ });
+ };
+
+ return (
+
+
+
+
+
+ {i18n.translate('xpack.apm.settings.apmIndices.title', {
+ defaultMessage: 'Indices'
+ })}
+
+
+
+
+
+ {i18n.translate('xpack.apm.settings.apmIndices.description', {
+ defaultMessage: `The APM UI uses index patterns to query your APM indices. If you've customized the index names that APM Server writes events to, you may need to update these patterns for the APM UI to work. Settings here take precedence over those set in kibana.yml.`
+ })}
+
+
+ {APM_INDEX_LABELS.map(({ configurationName, label }) => {
+ const matchedConfiguration = data.find(
+ ({ configurationName: configName }) =>
+ configName === configurationName
+ );
+ const defaultValue = matchedConfiguration
+ ? matchedConfiguration.defaultValue
+ : '';
+ const savedUiIndexValue = apmIndices[configurationName] || '';
+ return (
+
+
+
+ );
+ })}
+
+
+
+
+ {i18n.translate(
+ 'xpack.apm.settings.apmIndices.cancelButton',
+ { defaultMessage: 'Cancel' }
+ )}
+
+
+
+
+ {i18n.translate(
+ 'xpack.apm.settings.apmIndices.applyButton',
+ { defaultMessage: 'Apply changes' }
+ )}
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/index.tsx
new file mode 100644
index 0000000000000..f3be5abe4d48b
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/index.tsx
@@ -0,0 +1,66 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import {
+ EuiButtonEmpty,
+ EuiPage,
+ EuiSideNav,
+ EuiPageSideBar,
+ EuiPageBody
+} from '@elastic/eui';
+import { HomeLink } from '../../shared/Links/apm/HomeLink';
+import { useLocation } from '../../../hooks/useLocation';
+import { getAPMHref } from '../../shared/Links/apm/APMLink';
+
+export const Settings: React.FC = props => {
+ const { search, pathname } = useLocation();
+ return (
+ <>
+
+
+ {i18n.translate('xpack.apm.settings.returnToOverviewLinkLabel', {
+ defaultMessage: 'Return to overview'
+ })}
+
+
+
+
+
+
+ {props.children}
+
+ >
+ );
+};
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TraceOverview/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TraceOverview/index.tsx
index 4f14c4ba85932..1ecf72f6fa3fc 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TraceOverview/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TraceOverview/index.tsx
@@ -49,7 +49,7 @@ export function TraceOverview() {
return (
-
+
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/TruncateHeightSection.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/TruncateHeightSection.tsx
index 18e29c92d2e68..b01dc2c5398e2 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/TruncateHeightSection.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/TruncateHeightSection.tsx
@@ -4,12 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiLink } from '@elastic/eui';
+import { EuiIcon, EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { Fragment, useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
import { px, units } from '../../../../../../../style/variables';
-import { Ellipsis } from '../../../../../../shared/Icons';
const ToggleButtonContainer = styled.div`
margin-top: ${px(units.half)};
@@ -55,7 +54,13 @@ export const TruncateHeightSection: React.SFC = ({
setIsOpen(!isOpen);
}}
>
- {' '}
+ {' '}
{isOpen
? i18n.translate('xpack.apm.toggleHeight.showLessButtonLabel', {
defaultMessage: 'Show fewer lines'
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/index.tsx
index 7e9171197251d..0f5893772fec8 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/index.tsx
@@ -224,6 +224,7 @@ export function SpanFlyout({
),
content: (
+
)
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/TransactionFlyout/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/TransactionFlyout/index.tsx
index db3e43574023c..2020b8252035b 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/TransactionFlyout/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/TransactionFlyout/index.tsx
@@ -11,7 +11,8 @@ import {
EuiFlyoutHeader,
EuiPortal,
EuiSpacer,
- EuiTitle
+ EuiTitle,
+ EuiHorizontalRule
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
@@ -40,7 +41,6 @@ function TransactionPropertiesTable({
Metadata
-
);
@@ -87,7 +87,7 @@ export function TransactionFlyout({
totalDuration={traceRootDuration}
errorCount={errorCount}
/>
-
+
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts
index cc7697c1d8964..10f59e237ba7f 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts
@@ -17,7 +17,6 @@ import {
} from 'lodash';
import { idx } from '@kbn/elastic-idx';
import { TraceAPIResponse } from '../../../../../../../../server/lib/traces/get_trace';
-import { StringMap } from '../../../../../../../../typings/common';
import { Span } from '../../../../../../../../typings/es_schemas/ui/Span';
import { Transaction } from '../../../../../../../../typings/es_schemas/ui/Transaction';
@@ -191,7 +190,7 @@ function getServices(items: IWaterfallItem[]) {
return uniq(serviceNames);
}
-export type IServiceColors = StringMap
;
+export type IServiceColors = Record;
function getServiceColors(services: string[]) {
const assignedColors = [
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/DottedKeyValueTable/__test__/DottedKeyValueTable.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/DottedKeyValueTable/__test__/DottedKeyValueTable.test.tsx
deleted file mode 100644
index aebc86352a774..0000000000000
--- a/x-pack/legacy/plugins/apm/public/components/shared/DottedKeyValueTable/__test__/DottedKeyValueTable.test.tsx
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React from 'react';
-import { DottedKeyValueTable } from '..';
-import { cleanup, render } from 'react-testing-library';
-
-function getKeys(output: ReturnType) {
- const keys = output.getAllByTestId('dot-key');
- return Array.isArray(keys) ? keys.map(node => node.textContent) : [];
-}
-
-function getValues(output: ReturnType) {
- const values = output.getAllByTestId('value');
- return Array.isArray(values) ? values.map(node => node.textContent) : [];
-}
-
-describe('DottedKeyValueTable', () => {
- afterEach(cleanup);
-
- it('should display a nested object with alpha-ordered, dot notation keys and values', () => {
- const data = {
- name: {
- first: 'Jo',
- last: 'Smith'
- },
- age: 29,
- active: true,
- useless: false,
- start: null,
- end: undefined,
- nested: {
- b: {
- c: 'ccc'
- },
- a: 'aaa'
- }
- };
- const output = render( );
- const rows = output.container.querySelectorAll('tr');
- expect(rows.length).toEqual(9);
-
- expect(getKeys(output)).toEqual([
- 'active',
- 'age',
- 'end',
- 'name.first',
- 'name.last',
- 'nested.a',
- 'nested.b.c',
- 'start',
- 'useless'
- ]);
-
- expect(getValues(output)).toEqual([
- 'true',
- '29',
- 'N/A',
- 'Jo',
- 'Smith',
- 'aaa',
- 'ccc',
- 'N/A',
- 'false'
- ]);
- });
-
- it('should respect max depth', () => {
- const data = {
- nested: { b: { c: 'ccc' }, a: 'aaa' }
- };
- const output = render( );
- const rows = output.container.querySelectorAll('tr');
- expect(rows.length).toEqual(2);
-
- expect(getKeys(output)).toEqual(['nested.a', 'nested.b']);
-
- expect(getValues(output)).toEqual([
- 'aaa',
- JSON.stringify({ c: 'ccc' }, null, 4)
- ]);
- });
-
- it('should prepend a provided parent key to all of the dot-notation keys', () => {
- const data = {
- name: {
- first: 'Jo',
- last: 'Smith'
- },
- age: 29,
- active: true
- };
- const output = render( );
- const rows = output.container.querySelectorAll('tr');
- expect(rows.length).toEqual(4);
-
- expect(getKeys(output)).toEqual([
- 'top.active',
- 'top.age',
- 'top.name.first',
- 'top.name.last'
- ]);
- });
-
- it('should not add 0 sufix if value is an array with one element', () => {
- const data = {
- a: {
- b: {
- c1: ['foo', 'bar'],
- c2: ['foo']
- }
- },
- b: {
- c: ['foo']
- },
- c: {
- d: ['foo', 'bar']
- }
- };
- const output = render( );
-
- expect(getKeys(output)).toEqual([
- 'a.b.c1.0',
- 'a.b.c1.1',
- 'a.b.c2',
- 'b.c',
- 'c.d.0',
- 'c.d.1'
- ]);
- });
-});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/DottedKeyValueTable/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/DottedKeyValueTable/index.tsx
deleted file mode 100644
index 674df14c62eb0..0000000000000
--- a/x-pack/legacy/plugins/apm/public/components/shared/DottedKeyValueTable/index.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React, { TableHTMLAttributes } from 'react';
-import { compact, isObject } from 'lodash';
-import {
- EuiTable,
- EuiTableProps,
- EuiTableBody,
- EuiTableRow,
- EuiTableRowCell
-} from '@elastic/eui';
-import { StringMap } from '../../../../typings/common';
-import { FormattedValue } from './FormattedValue';
-
-interface PathifyOptions {
- maxDepth?: number;
- parentKey?: string;
- depth?: number;
-}
-
-interface PathifyResult {
- [key: string]: any;
-}
-
-/**
- * Converts a deeply-nested object into a one-level object
- * with dot-notation paths as keys.
- */
-export function pathify(
- item: StringMap,
- { maxDepth, parentKey = '', depth = 0 }: PathifyOptions
-): PathifyResult {
- const isArrayWithSingleValue = Array.isArray(item) && item.length === 1;
- return Object.keys(item)
- .sort()
- .reduce((pathified, key) => {
- const childKey = isArrayWithSingleValue ? '' : key;
- const currentKey = compact([parentKey, childKey]).join('.');
- if ((!maxDepth || depth + 1 <= maxDepth) && isObject(item[key])) {
- return {
- ...pathified,
- ...pathify(item[key], {
- maxDepth,
- parentKey: currentKey,
- depth: depth + 1
- })
- };
- } else {
- return { ...pathified, [currentKey]: item[key] };
- }
- }, {});
-}
-
-export function DottedKeyValueTable({
- data,
- parentKey,
- maxDepth,
- tableProps = {}
-}: {
- data: StringMap;
- parentKey?: string;
- maxDepth?: number;
- tableProps?: EuiTableProps & TableHTMLAttributes;
-}) {
- const pathified = pathify(data, { maxDepth, parentKey });
- const rows = Object.keys(pathified)
- .sort()
- .map(k => [k, pathified[k]]);
- return (
-
-
- {rows.map(([key, value]) => (
-
-
- {key}
-
-
-
-
-
- ))}
-
-
- );
-}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/HeightRetainer/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/HeightRetainer/index.tsx
new file mode 100644
index 0000000000000..e6f4487312429
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/HeightRetainer/index.tsx
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useEffect, useRef } from 'react';
+
+export const HeightRetainer: React.SFC = props => {
+ const containerElement = useRef(null);
+ const minHeight = useRef(0);
+
+ useEffect(() => {
+ if (containerElement.current) {
+ const currentHeight = containerElement.current.clientHeight;
+ if (minHeight.current < currentHeight) {
+ minHeight.current = currentHeight;
+ }
+ }
+ });
+
+ return (
+
+ );
+};
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Icons.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Icons.tsx
deleted file mode 100644
index 79b34b2818aac..0000000000000
--- a/x-pack/legacy/plugins/apm/public/components/shared/Icons.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { EuiIcon } from '@elastic/eui';
-import React from 'react';
-
-export function Ellipsis({ horizontal }: { horizontal: boolean }) {
- return (
-
- );
-}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/ImpactBar/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/ImpactBar/index.tsx
index 7f9d3c9f9f3b3..ed931191cfb96 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/ImpactBar/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/ImpactBar/index.tsx
@@ -6,10 +6,9 @@
import { EuiProgress } from '@elastic/eui';
import React from 'react';
-import { StringMap } from '../../../../typings/common';
// TODO: extend from EUI's EuiProgress prop interface
-export interface ImpactBarProps extends StringMap {
+export interface ImpactBarProps extends Record {
value: number;
max?: number;
}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/DottedKeyValueTable/FormattedValue.tsx b/x-pack/legacy/plugins/apm/public/components/shared/KeyValueTable/FormattedValue.tsx
similarity index 100%
rename from x-pack/legacy/plugins/apm/public/components/shared/DottedKeyValueTable/FormattedValue.tsx
rename to x-pack/legacy/plugins/apm/public/components/shared/KeyValueTable/FormattedValue.tsx
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/KeyValueTable/__test__/KeyValueTable.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/KeyValueTable/__test__/KeyValueTable.test.tsx
new file mode 100644
index 0000000000000..2ce8feb08d4ad
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/KeyValueTable/__test__/KeyValueTable.test.tsx
@@ -0,0 +1,64 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { KeyValueTable } from '..';
+import { cleanup, render } from 'react-testing-library';
+
+function getKeys(output: ReturnType) {
+ const keys = output.getAllByTestId('dot-key');
+ return Array.isArray(keys) ? keys.map(node => node.textContent) : [];
+}
+
+function getValues(output: ReturnType) {
+ const values = output.getAllByTestId('value');
+ return Array.isArray(values) ? values.map(node => node.textContent) : [];
+}
+
+describe('KeyValueTable', () => {
+ afterEach(cleanup);
+
+ it('displays key and value table', () => {
+ const data = [
+ { key: 'name.first', value: 'First Name' },
+ { key: 'name.last', value: 'Last Name' },
+ { key: 'age', value: '29' },
+ { key: 'active', value: true },
+ { key: 'useless', value: false },
+ { key: 'start', value: null },
+ { key: 'end', value: undefined },
+ { key: 'nested.b.c', value: 'ccc' },
+ { key: 'nested.a', value: 'aaa' }
+ ];
+ const output = render( );
+ const rows = output.container.querySelectorAll('tr');
+ expect(rows.length).toEqual(9);
+
+ expect(getKeys(output)).toEqual([
+ 'name.first',
+ 'name.last',
+ 'age',
+ 'active',
+ 'useless',
+ 'start',
+ 'end',
+ 'nested.b.c',
+ 'nested.a'
+ ]);
+
+ expect(getValues(output)).toEqual([
+ 'First Name',
+ 'Last Name',
+ '29',
+ 'true',
+ 'false',
+ 'N/A',
+ 'N/A',
+ 'ccc',
+ 'aaa'
+ ]);
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/KeyValueTable/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/KeyValueTable/index.tsx
new file mode 100644
index 0000000000000..b58f142f1abaa
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/KeyValueTable/index.tsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { TableHTMLAttributes } from 'react';
+import {
+ EuiTable,
+ EuiTableProps,
+ EuiTableBody,
+ EuiTableRow,
+ EuiTableRowCell
+} from '@elastic/eui';
+import { FormattedValue } from './FormattedValue';
+import { KeyValuePair } from '../../../utils/flattenObject';
+
+export function KeyValueTable({
+ keyValuePairs,
+ tableProps = {}
+}: {
+ keyValuePairs: KeyValuePair[];
+ tableProps?: EuiTableProps & TableHTMLAttributes;
+}) {
+ return (
+
+
+ {keyValuePairs.map(({ key, value }) => (
+
+
+ {key}
+
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/Typeahead/index.js b/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/Typeahead/index.js
index fc08dee8b93cb..7a7dfe8b50e3e 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/Typeahead/index.js
+++ b/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/Typeahead/index.js
@@ -9,7 +9,6 @@ import PropTypes from 'prop-types';
import Suggestions from './Suggestions';
import ClickOutside from './ClickOutside';
import { EuiFieldSearch, EuiProgress } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
const KEY_CODES = {
LEFT: 37,
@@ -157,7 +156,7 @@ export class Typeahead extends Component {
};
render() {
- const { queryExample } = this.props;
+ const { placeholder } = this.props;
return (
{
if (node) {
this.inputRef = node;
@@ -227,7 +217,7 @@ Typeahead.propTypes = {
onChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
suggestions: PropTypes.array.isRequired,
- queryExample: PropTypes.string.isRequired
+ placeholder: PropTypes.string.isRequired
};
Typeahead.defaultProps = {
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/get_bool_filter.js b/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/get_bool_filter.ts
similarity index 64%
rename from x-pack/legacy/plugins/apm/public/components/shared/KueryBar/get_bool_filter.js
rename to x-pack/legacy/plugins/apm/public/components/shared/KueryBar/get_bool_filter.ts
index 48a94a96acd3c..f4628524cced5 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/get_bool_filter.js
+++ b/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/get_bool_filter.ts
@@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { ESFilter } from '../../../../typings/elasticsearch';
import {
TRANSACTION_TYPE,
ERROR_GROUP_ID,
@@ -11,27 +12,34 @@ import {
TRANSACTION_NAME,
SERVICE_NAME
} from '../../../../common/elasticsearch_fieldnames';
+import { IUrlParams } from '../../../context/UrlParamsContext/types';
-export function getBoolFilter(urlParams) {
- const boolFilter = [
+export function getBoolFilter(urlParams: IUrlParams) {
+ const { start, end, serviceName, processorEvent } = urlParams;
+
+ if (!start || !end) {
+ throw new Error('Date range was not defined');
+ }
+
+ const boolFilter: ESFilter[] = [
{
range: {
'@timestamp': {
- gte: new Date(urlParams.start).getTime(),
- lte: new Date(urlParams.end).getTime(),
+ gte: new Date(start).getTime(),
+ lte: new Date(end).getTime(),
format: 'epoch_millis'
}
}
}
];
- if (urlParams.serviceName) {
+ if (serviceName) {
boolFilter.push({
- term: { [SERVICE_NAME]: urlParams.serviceName }
+ term: { [SERVICE_NAME]: serviceName }
});
}
- switch (urlParams.processorEvent) {
+ switch (processorEvent) {
case 'transaction':
boolFilter.push({
term: { [PROCESSOR_EVENT]: 'transaction' }
@@ -62,12 +70,19 @@ export function getBoolFilter(urlParams) {
}
break;
+ case 'metric':
+ boolFilter.push({
+ term: { [PROCESSOR_EVENT]: 'metric' }
+ });
+ break;
+
default:
boolFilter.push({
bool: {
should: [
{ term: { [PROCESSOR_EVENT]: 'error' } },
- { term: { [PROCESSOR_EVENT]: 'transaction' } }
+ { term: { [PROCESSOR_EVENT]: 'transaction' } },
+ { term: { [PROCESSOR_EVENT]: 'metric' } }
]
}
});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/index.tsx
index 0e95bb94ea911..7c0b6f24f87a7 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/KueryBar/index.tsx
@@ -6,29 +6,20 @@
import React, { useState } from 'react';
import { uniqueId, startsWith } from 'lodash';
-import { EuiCallOut } from '@elastic/eui';
import styled from 'styled-components';
-import { FormattedMessage } from '@kbn/i18n/react';
-import { i18n } from '@kbn/i18n';
import { npStart } from 'ui/new_platform';
-import { StaticIndexPattern, getFromSavedObject } from 'ui/index_patterns';
+import { StaticIndexPattern } from 'ui/index_patterns';
import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
+import { i18n } from '@kbn/i18n';
import { fromQuery, toQuery } from '../Links/url_helpers';
-import { KibanaLink } from '../Links/KibanaLink';
// @ts-ignore
import { Typeahead } from './Typeahead';
-// @ts-ignore
import { getBoolFilter } from './get_bool_filter';
import { useLocation } from '../../../hooks/useLocation';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { history } from '../../../utils/history';
-import { useMatchedRoutes } from '../../../hooks/useMatchedRoutes';
-import { RouteName } from '../../app/Main/route_config/route_names';
-import { useKibanaCore } from '../../../../../observability/public';
-import { ISavedObject } from '../../../services/rest/savedObjects';
import { AutocompleteSuggestion } from '../../../../../../../../src/plugins/data/public';
-import { FETCH_STATUS } from '../../../hooks/useFetcher';
-import { useAPMIndexPattern } from '../../../hooks/useAPMIndexPattern';
+import { useKueryBarIndexPattern } from '../../../hooks/useKueryBarIndexPattern';
const Container = styled.div`
margin-bottom: 10px;
@@ -50,16 +41,10 @@ function convertKueryToEsQuery(
return toElasticsearchQuery(ast, indexPattern);
}
-function getAPMIndexPatternForKuery(
- apmIndexPattern: ISavedObject
-): StaticIndexPattern | undefined {
- return getFromSavedObject(apmIndexPattern);
-}
-
function getSuggestions(
query: string,
selectionStart: number,
- apmIndexPattern: StaticIndexPattern,
+ indexPattern: StaticIndexPattern,
boolFilter: unknown
) {
const autocompleteProvider = getAutocompleteProvider('kuery');
@@ -72,7 +57,7 @@ function getSuggestions(
const getAutocompleteSuggestions = autocompleteProvider({
config,
- indexPatterns: [apmIndexPattern],
+ indexPatterns: [indexPattern],
boolFilter
});
return getAutocompleteSuggestions({
@@ -83,43 +68,28 @@ function getSuggestions(
}
export function KueryBar() {
- const core = useKibanaCore();
const [state, setState] = useState({
suggestions: [],
isLoadingSuggestions: false
});
const { urlParams } = useUrlParams();
const location = useLocation();
- const matchedRoutes = useMatchedRoutes();
-
- const apmIndexPatternTitle = core.injectedMetadata.getInjectedVar(
- 'apmIndexPatternTitle'
- );
-
- const {
- apmIndexPattern,
- status: apmIndexPatternStatus
- } = useAPMIndexPattern();
-
- const indexPattern =
- apmIndexPatternStatus === FETCH_STATUS.SUCCESS
- ? getAPMIndexPatternForKuery(apmIndexPattern)
- : null;
-
- const indexPatternMissing = status === FETCH_STATUS.SUCCESS && !indexPattern;
let currentRequestCheck;
- const exampleMap: { [key: string]: string } = {
- [RouteName.TRANSACTIONS]: 'transaction.duration.us > 300000',
- [RouteName.ERRORS]: 'http.response.status_code >= 400',
- [RouteName.METRICS]: 'process.pid = "1234"'
+ const { processorEvent } = urlParams;
+
+ const examples = {
+ transaction: 'transaction.duration.us > 300000',
+ error: 'http.response.status_code >= 400',
+ metric: 'process.pid = "1234"',
+ defaults:
+ 'transaction.duration.us > 300000 AND http.response.status_code >= 400'
};
- // sets queryExample to the first matched example query, else default example
- const queryExample =
- matchedRoutes.map(({ name }) => exampleMap[name]).find(Boolean) ||
- 'transaction.duration.us > 300000 AND http.response.status_code >= 400';
+ const example = examples[processorEvent || 'defaults'];
+
+ const { indexPattern } = useKueryBarIndexPattern(processorEvent);
async function onChange(inputValue: string, selectionStart: number) {
if (indexPattern == null) {
@@ -179,42 +149,24 @@ export function KueryBar() {
return (
-
- {indexPatternMissing && (
-
-
- {i18n.translate(
- 'xpack.apm.kueryBar.setupInstructionsLinkLabel',
- { defaultMessage: 'Setup Instructions' }
- )}
-
- )
- }}
- />
-
+ placeholder={i18n.translate('xpack.apm.kueryBar.placeholder', {
+ defaultMessage: `Search {event, select,
+ transaction {transactions}
+ metric {metrics}
+ error {errors}
+ other {transactions, errors and metrics}
+ } (E.g. {queryExample})`,
+ values: {
+ queryExample: example,
+ event: processorEvent
}
- color="warning"
- iconType="alert"
- size="s"
- />
- )}
+ })}
+ />
);
}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/url_helpers.ts b/x-pack/legacy/plugins/apm/public/components/shared/Links/url_helpers.ts
index 763ee93df6415..357ea23d522a0 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Links/url_helpers.ts
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/url_helpers.ts
@@ -6,13 +6,12 @@
import qs from 'querystring';
import { LocalUIFilterName } from '../../../../server/lib/ui_filters/local_ui_filters/config';
-import { StringMap } from '../../../../typings/common';
export function toQuery(search?: string): APMQueryParamsRaw {
return search ? qs.parse(search.slice(1)) : {};
}
-export function fromQuery(query: StringMap
) {
+export function fromQuery(query: Record) {
return qs.stringify(query, undefined, undefined, {
encodeURIComponent: (value: string) => {
return encodeURIComponent(value).replace(/%3A/g, ':');
@@ -39,6 +38,7 @@ export type APMQueryParams = {
rangeTo?: string;
refreshPaused?: string | boolean;
refreshInterval?: string | number;
+ searchTerm?: string;
} & { [key in LocalUIFilterName]?: string };
// forces every value of T[K] to be type: string
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterBadgeList.tsx b/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterBadgeList.tsx
index a1140dcbbb3fc..01d2d56b6d142 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterBadgeList.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterBadgeList.tsx
@@ -32,7 +32,7 @@ const FilterBadgeList = ({ onRemove, value }: Props) => (
>
{val}
-
+
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/index.tsx
index aef8e5747d992..412b92d525aa2 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/index.tsx
@@ -168,7 +168,7 @@ const Filter = ({
}}
value={value}
/>
-
+
>
) : null}
>
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/ManagedTable/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/ManagedTable/index.tsx
index 0f5fcceea3d20..29a8528295dd7 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/ManagedTable/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/ManagedTable/index.tsx
@@ -8,7 +8,6 @@ import { EuiBasicTable } from '@elastic/eui';
import { sortByOrder } from 'lodash';
import React, { useMemo, useCallback, ReactNode } from 'react';
import { idx } from '@kbn/elastic-idx';
-import { StringMap } from '../../../../typings/common';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { history } from '../../../utils/history';
import { fromQuery, toQuery } from '../Links/url_helpers';
@@ -16,7 +15,7 @@ import { fromQuery, toQuery } from '../Links/url_helpers';
// TODO: this should really be imported from EUI
export interface ITableColumn {
name: ReactNode;
- actions?: StringMap[];
+ actions?: Array>;
field?: string;
dataType?: string;
align?: string;
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx
index 652bb25afed8e..04a5b60467730 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx
@@ -4,9 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import React, { useMemo } from 'react';
import { ERROR_METADATA_SECTIONS } from './sections';
import { APMError } from '../../../../../typings/es_schemas/ui/APMError';
+import { getSectionsWithRows } from '../helper';
import { MetadataTable } from '..';
interface Props {
@@ -14,5 +15,9 @@ interface Props {
}
export function ErrorMetadata({ error }: Props) {
- return ;
+ const sectionsWithRows = useMemo(
+ () => getSectionsWithRows(ERROR_METADATA_SECTIONS, error),
+ [error]
+ );
+ return ;
}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/Section.tsx b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/Section.tsx
new file mode 100644
index 0000000000000..6f67b2458ea10
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/Section.tsx
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiText } from '@elastic/eui';
+import { KeyValueTable } from '../KeyValueTable';
+import { KeyValuePair } from '../../../utils/flattenObject';
+
+interface Props {
+ keyValuePairs?: KeyValuePair[];
+}
+
+export function Section({ keyValuePairs }: Props) {
+ if (keyValuePairs) {
+ return ;
+ }
+ return (
+
+ {i18n.translate(
+ 'xpack.apm.propertiesTable.agentFeature.noDataAvailableLabel',
+ { defaultMessage: 'No data available' }
+ )}
+
+ );
+}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/index.tsx
index 713863639d1b7..03182062d324a 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/index.tsx
@@ -4,9 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import React, { useMemo } from 'react';
import { SPAN_METADATA_SECTIONS } from './sections';
import { Span } from '../../../../../typings/es_schemas/ui/Span';
+import { getSectionsWithRows } from '../helper';
import { MetadataTable } from '..';
interface Props {
@@ -14,5 +15,9 @@ interface Props {
}
export function SpanMetadata({ span }: Props) {
- return ;
+ const sectionsWithRows = useMemo(
+ () => getSectionsWithRows(SPAN_METADATA_SECTIONS, span),
+ [span]
+ );
+ return ;
}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx
index fa2b32b403ee7..4216e37e0cb27 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx
@@ -4,9 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import React, { useMemo } from 'react';
import { TRANSACTION_METADATA_SECTIONS } from './sections';
import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction';
+import { getSectionsWithRows } from '../helper';
import { MetadataTable } from '..';
interface Props {
@@ -14,10 +15,9 @@ interface Props {
}
export function TransactionMetadata({ transaction }: Props) {
- return (
-
+ const sectionsWithRows = useMemo(
+ () => getSectionsWithRows(TRANSACTION_METADATA_SECTIONS, transaction),
+ [transaction]
);
+ return ;
}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx
index 331a8bf41642e..bdf895f423913 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx
@@ -8,77 +8,44 @@ import React from 'react';
import 'jest-dom/extend-expect';
import { render, cleanup } from 'react-testing-library';
import { MetadataTable } from '..';
-import {
- expectTextsInDocument,
- expectTextsNotInDocument
-} from '../../../../utils/testHelpers';
-import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction';
+import { expectTextsInDocument } from '../../../../utils/testHelpers';
+import { SectionsWithRows } from '../helper';
describe('MetadataTable', () => {
afterEach(cleanup);
+ it('shows sections', () => {
+ const sectionsWithRows = ([
+ { key: 'foo', label: 'Foo', required: true },
+ {
+ key: 'bar',
+ label: 'Bar',
+ required: false,
+ properties: ['props.A', 'props.B'],
+ rows: [{ key: 'props.A', value: 'A' }, { key: 'props.B', value: 'B' }]
+ }
+ ] as unknown) as SectionsWithRows;
+ const output = render( );
+ expectTextsInDocument(output, [
+ 'Foo',
+ 'No data available',
+ 'Bar',
+ 'props.A',
+ 'A',
+ 'props.B',
+ 'B'
+ ]);
+ });
describe('required sections', () => {
it('shows "empty state message" if no data is available', () => {
- const sections = [
+ const sectionsWithRows = ([
{
key: 'foo',
label: 'Foo',
required: true
}
- ];
- const output = render(
-
- );
+ ] as unknown) as SectionsWithRows;
+ const output = render( );
expectTextsInDocument(output, ['Foo', 'No data available']);
});
- it('shows "empty state message" if property is not available', () => {
- const sections = [
- {
- key: 'foo',
- label: 'Foo',
- required: true,
- properties: ['bar']
- }
- ];
- const item = ({
- foo: {
- foobar: 'bar'
- }
- } as unknown) as Transaction;
-
- const output = render( );
- expectTextsInDocument(output, ['Foo', 'No data available']);
- });
- });
- describe('not required sections', () => {
- it('does not show section when no items are provided', () => {
- const sections = [
- {
- key: 'foo',
- label: 'Foo',
- required: false
- }
- ];
- const output = render(
-
- );
- expectTextsNotInDocument(output, ['Foo']);
- });
- it('does not show section if property is not available', () => {
- const sections = [
- {
- key: 'foo',
- label: 'Foo',
- required: false,
- properties: ['bar']
- }
- ];
- const item = ({
- foo: {
- foobar: 'bar'
- }
- } as unknown) as Transaction;
- const output = render( );
- expectTextsNotInDocument(output, ['Foo']);
- });
});
});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/Section.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/Section.test.tsx
new file mode 100644
index 0000000000000..7e68b2f84eead
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/Section.test.tsx
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React from 'react';
+import 'jest-dom/extend-expect';
+import { render } from 'react-testing-library';
+import { Section } from '../Section';
+import { expectTextsInDocument } from '../../../../utils/testHelpers';
+
+describe('Section', () => {
+ it('shows "empty state message" if no data is available', () => {
+ const output = render();
+ expectTextsInDocument(output, ['No data available']);
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/helper.test.ts b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/helper.test.ts
new file mode 100644
index 0000000000000..aaf73619e481a
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/__test__/helper.test.ts
@@ -0,0 +1,85 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { getSectionsWithRows, filterSectionsByTerm } from '../helper';
+import { LABELS, HTTP, SERVICE } from '../sections';
+import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction';
+
+describe('MetadataTable Helper', () => {
+ const sections = [
+ { ...LABELS, required: true },
+ HTTP,
+ { ...SERVICE, properties: ['environment'] }
+ ];
+ const apmDoc = ({
+ http: {
+ headers: {
+ Connection: 'close',
+ Host: 'opbeans:3000',
+ request: { method: 'get' }
+ }
+ },
+ service: {
+ framework: { name: 'express' },
+ environment: 'production'
+ }
+ } as unknown) as Transaction;
+ const metadataItems = getSectionsWithRows(sections, apmDoc);
+
+ it('returns flattened data and required section', () => {
+ expect(metadataItems).toEqual([
+ { key: 'labels', label: 'Labels', required: true, rows: [] },
+ {
+ key: 'http',
+ label: 'HTTP',
+ rows: [
+ { key: 'http.headers.Connection', value: 'close' },
+ { key: 'http.headers.Host', value: 'opbeans:3000' },
+ { key: 'http.headers.request.method', value: 'get' }
+ ]
+ },
+ {
+ key: 'service',
+ label: 'Service',
+ properties: ['environment'],
+ rows: [{ key: 'service.environment', value: 'production' }]
+ }
+ ]);
+ });
+ describe('filter', () => {
+ it('items by key', () => {
+ const filteredItems = filterSectionsByTerm(metadataItems, 'http');
+ expect(filteredItems).toEqual([
+ {
+ key: 'http',
+ label: 'HTTP',
+ rows: [
+ { key: 'http.headers.Connection', value: 'close' },
+ { key: 'http.headers.Host', value: 'opbeans:3000' },
+ { key: 'http.headers.request.method', value: 'get' }
+ ]
+ }
+ ]);
+ });
+
+ it('items by value', () => {
+ const filteredItems = filterSectionsByTerm(metadataItems, 'product');
+ expect(filteredItems).toEqual([
+ {
+ key: 'service',
+ label: 'Service',
+ properties: ['environment'],
+ rows: [{ key: 'service.environment', value: 'production' }]
+ }
+ ]);
+ });
+
+ it('returns empty when no item matches', () => {
+ const filteredItems = filterSectionsByTerm(metadataItems, 'post');
+ expect(filteredItems).toEqual([]);
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/helper.ts b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/helper.ts
new file mode 100644
index 0000000000000..c272790826d8d
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/helper.ts
@@ -0,0 +1,55 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { get, pick, isEmpty } from 'lodash';
+import { Section } from './sections';
+import { Transaction } from '../../../../typings/es_schemas/ui/Transaction';
+import { APMError } from '../../../../typings/es_schemas/ui/APMError';
+import { Span } from '../../../../typings/es_schemas/ui/Span';
+import { flattenObject, KeyValuePair } from '../../../utils/flattenObject';
+
+export type SectionsWithRows = ReturnType;
+
+export const getSectionsWithRows = (
+ sections: Section[],
+ apmDoc: Transaction | APMError | Span
+) => {
+ return sections
+ .map(section => {
+ const sectionData: Record = get(apmDoc, section.key);
+ const filteredData:
+ | Record
+ | undefined = section.properties
+ ? pick(sectionData, section.properties)
+ : sectionData;
+
+ const rows: KeyValuePair[] = flattenObject(filteredData, section.key);
+ return { ...section, rows };
+ })
+ .filter(({ required, rows }) => required || !isEmpty(rows));
+};
+
+export const filterSectionsByTerm = (
+ sections: SectionsWithRows,
+ searchTerm: string
+) => {
+ if (!searchTerm) {
+ return sections;
+ }
+ return sections
+ .map(section => {
+ const { rows = [] } = section;
+ const filteredRows = rows.filter(({ key, value }) => {
+ const valueAsString = String(value).toLowerCase();
+ return (
+ key.toLowerCase().includes(searchTerm) ||
+ valueAsString.includes(searchTerm)
+ );
+ });
+ return { ...section, rows: filteredRows };
+ })
+ .filter(({ rows }) => !isEmpty(rows));
+};
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/index.tsx
index d7f3bf5504d40..53d54ae5de7ad 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/index.tsx
@@ -9,42 +9,50 @@ import {
EuiFlexItem,
EuiIcon,
EuiSpacer,
- EuiTitle
+ EuiTitle,
+ EuiFieldSearch
} from '@elastic/eui';
-import React from 'react';
-import { get, pick, isEmpty } from 'lodash';
-import { EuiText } from '@elastic/eui';
+import React, { useCallback } from 'react';
import { i18n } from '@kbn/i18n';
-import { DottedKeyValueTable } from '../DottedKeyValueTable';
+import { isEmpty } from 'lodash';
+import { EuiText } from '@elastic/eui';
import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink';
-import { Section as SectionType } from './sections';
-import { Transaction } from '../../../../typings/es_schemas/ui/Transaction';
-import { APMError } from '../../../../typings/es_schemas/ui/APMError';
-import { Span } from '../../../../typings/es_schemas/ui/Span';
-
-type Item = Transaction | APMError | Span;
+import { HeightRetainer } from '../HeightRetainer';
+import { Section } from './Section';
+import { history } from '../../../utils/history';
+import { fromQuery, toQuery } from '../Links/url_helpers';
+import { useLocation } from '../../../hooks/useLocation';
+import { useUrlParams } from '../../../hooks/useUrlParams';
+import { SectionsWithRows, filterSectionsByTerm } from './helper';
interface Props {
- item: Item;
- sections: SectionType[];
+ sections: SectionsWithRows;
}
-const filterSections = (sections: SectionType[], item: Item) =>
- sections
- .map(section => {
- const data: Record = get(item, section.key);
- return {
- ...section,
- data: section.properties ? pick(data, section.properties) : data
- };
- })
- .filter(({ required, data }) => required || !isEmpty(data));
+export function MetadataTable({ sections }: Props) {
+ const location = useLocation();
+ const { urlParams } = useUrlParams();
+ const { searchTerm = '' } = urlParams;
-export function MetadataTable({ item, sections }: Props) {
- const filteredSections = filterSections(sections, item);
+ const filteredSections = filterSectionsByTerm(sections, searchTerm);
+
+ const onSearchChange = useCallback(
+ (e: React.ChangeEvent) => {
+ const value = e.target.value.trim().toLowerCase();
+ history.replace({
+ ...location,
+ search: fromQuery({
+ ...toQuery(location.search),
+ searchTerm: value
+ })
+ });
+ },
+ [location]
+ );
+ const noResultFound = Boolean(searchTerm) && isEmpty(filteredSections);
return (
-
+
@@ -52,40 +60,49 @@ export function MetadataTable({ item, sections }: Props) {
+
+
+
- {filteredSections.map(section => (
-
-
- {section.label}
-
-
-
-
-
- ))}
+
+ {filteredSections.map(section => (
+
+
+ {section.label}
+
+
+
+
+
+ ))}
+ {noResultFound && }
+
);
}
-function Section({
- propData = {},
- propKey
-}: {
- propData?: Record;
- propKey?: string;
-}) {
- if (isEmpty(propData)) {
- return (
+const NoResultFound = ({ value }: { value: string }) => (
+
+
{i18n.translate(
- 'xpack.apm.propertiesTable.agentFeature.noDataAvailableLabel',
- { defaultMessage: 'No data available' }
+ 'xpack.apm.propertiesTable.agentFeature.noResultFound',
+ {
+ defaultMessage: `No results for "{value}".`,
+ values: { value }
+ }
)}
- );
- }
-
- return (
-
- );
-}
+
+
+);
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.test.tsx
new file mode 100644
index 0000000000000..f36b91a522e92
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.test.tsx
@@ -0,0 +1,52 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { mount, shallow } from 'enzyme';
+import { CauseStacktrace } from './CauseStacktrace';
+
+describe('CauseStacktrace', () => {
+ describe('render', () => {
+ describe('with no stack trace', () => {
+ it('renders without the accordion', () => {
+ const props = { id: 'testId', message: 'testMessage' };
+
+ expect(
+ mount( ).find('CausedBy')
+ ).toHaveLength(1);
+ });
+ });
+
+ describe('with no message and a stack trace', () => {
+ it('says "Caused by …', () => {
+ const props = {
+ id: 'testId',
+ stackframes: [{ filename: 'testFilename', line: { number: 1 } }]
+ };
+
+ expect(
+ mount( )
+ .find('EuiTitle span')
+ .text()
+ ).toEqual('…');
+ });
+ });
+
+ describe('with a message and a stack trace', () => {
+ it('renders with the accordion', () => {
+ const props = {
+ id: 'testId',
+ message: 'testMessage',
+ stackframes: [{ filename: 'testFilename', line: { number: 1 } }]
+ };
+
+ expect(
+ shallow( ).find('Styled(EuiAccordion)')
+ ).toHaveLength(1);
+ });
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.tsx
new file mode 100644
index 0000000000000..52f2ba4586718
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.tsx
@@ -0,0 +1,79 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import styled from 'styled-components';
+import theme from '@elastic/eui/dist/eui_theme_light.json';
+import { i18n } from '@kbn/i18n';
+import { EuiAccordion, EuiTitle } from '@elastic/eui';
+import { px, unit } from '../../../style/variables';
+import { Stacktrace } from '.';
+import { IStackframe } from '../../../../typings/es_schemas/raw/fields/Stackframe';
+
+// @ts-ignore Styled Components has trouble inferring the types of the default props here.
+const Accordion = styled(EuiAccordion)`
+ border-top: ${theme.euiBorderThin};
+`;
+
+const CausedByContainer = styled('h5')`
+ padding: ${theme.spacerSizes.s} 0;
+`;
+
+const CausedByHeading = styled('span')`
+ color: ${theme.textColors.subdued};
+ display: block;
+ font-size: ${theme.euiFontSizeXS};
+ font-weight: ${theme.euiFontWeightBold};
+ text-transform: uppercase;
+`;
+
+const FramesContainer = styled('div')`
+ padding-left: ${px(unit)};
+`;
+
+function CausedBy({ message }: { message: string }) {
+ return (
+
+
+ {i18n.translate(
+ 'xpack.apm.stacktraceTab.causedByFramesToogleButtonLabel',
+ {
+ defaultMessage: 'Caused By'
+ }
+ )}
+
+
+ {message}
+
+
+ );
+}
+
+interface CauseStacktraceProps {
+ codeLanguage?: string;
+ id: string;
+ message?: string;
+ stackframes?: IStackframe[];
+}
+
+export function CauseStacktrace({
+ codeLanguage,
+ id,
+ message = '…',
+ stackframes = []
+}: CauseStacktraceProps) {
+ if (stackframes.length === 0) {
+ return ;
+ }
+
+ return (
+ } id={id}>
+
+
+
+
+ );
+}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Context.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Context.tsx
index c5d610d0b8e1b..9685ba920a73c 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Context.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Context.tsx
@@ -32,7 +32,7 @@ registerLanguage('ruby', ruby);
const ContextContainer = styled.div`
position: relative;
- border-radius: 0 0 ${borderRadius} ${borderRadius};
+ border-radius: ${borderRadius};
`;
const LINE_HEIGHT = units.eighth * 9;
@@ -49,7 +49,7 @@ const LineNumberContainer = styled.div<{ isLibraryFrame: boolean }>`
position: absolute;
top: 0;
left: 0;
- border-radius: 0 0 0 ${borderRadius};
+ border-radius: ${borderRadius};
background: ${props =>
props.isLibraryFrame
? theme.euiColorEmptyShade
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/FrameHeading.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/FrameHeading.tsx
index c9f7158f464a4..c9f7057d2fb86 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/FrameHeading.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/FrameHeading.tsx
@@ -12,16 +12,17 @@ import { IStackframe } from '../../../../typings/es_schemas/raw/fields/Stackfram
import { fontFamilyCode, fontSize, px, units } from '../../../style/variables';
const FileDetails = styled.div`
- color: ${theme.euiColorMediumShade};
- padding: ${px(units.half)};
+ color: ${theme.euiColorDarkShade};
+ padding: ${px(units.half)} 0;
font-family: ${fontFamilyCode};
font-size: ${fontSize};
`;
+
const LibraryFrameFileDetail = styled.span`
color: ${theme.euiColorDarkShade};
`;
+
const AppFrameFileDetail = styled.span`
- font-weight: bold;
color: ${theme.euiColorFullShade};
`;
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/LibraryStackFrames.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/LibraryStackFrames.tsx
deleted file mode 100644
index 9f8229e024c37..0000000000000
--- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/LibraryStackFrames.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { EuiLink, EuiSpacer } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import React, { Fragment } from 'react';
-import styled from 'styled-components';
-import { IStackframe } from '../../../../typings/es_schemas/raw/fields/Stackframe';
-import { Ellipsis } from '../../shared/Icons';
-import { Stackframe } from './Stackframe';
-
-const LibraryFrameToggle = styled.div`
- user-select: none;
-`;
-
-interface Props {
- stackframes: IStackframe[];
- codeLanguage?: string;
- initialVisiblity: boolean;
-}
-
-interface State {
- isVisible: boolean;
-}
-
-export class LibraryStackFrames extends React.Component {
- public state = {
- isVisible: this.props.initialVisiblity
- };
-
- public onClick = () => {
- this.setState(({ isVisible }) => ({ isVisible: !isVisible }));
- };
-
- public render() {
- const { stackframes, codeLanguage } = this.props;
- const { isVisible } = this.state;
- if (stackframes.length === 0) {
- return null;
- }
-
- return (
-
-
-
- {' '}
- {i18n.translate(
- 'xpack.apm.stacktraceTab.libraryFramesToogleButtonLabel',
- {
- defaultMessage:
- '{count, plural, one {# library frame} other {# library frames}}',
- values: { count: stackframes.length }
- }
- )}
-
-
-
-
- {isVisible && (
-
-
- {stackframes.map((stackframe, i) => (
-
- ))}
-
- )}
-
-
- );
- }
-}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/LibraryStacktrace.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/LibraryStacktrace.test.tsx
new file mode 100644
index 0000000000000..94751f9d0461d
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/LibraryStacktrace.test.tsx
@@ -0,0 +1,34 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { LibraryStacktrace } from './LibraryStacktrace';
+
+describe('LibraryStacktrace', () => {
+ describe('render', () => {
+ describe('with no stack frames', () => {
+ it('renders null', () => {
+ const props = { id: 'testId', stackframes: [] };
+
+ expect(shallow( ).html()).toBeNull();
+ });
+ });
+
+ describe('with stack frames', () => {
+ it('renders an accordion', () => {
+ const props = {
+ id: 'testId',
+ stackframes: [{ filename: 'testFilename', line: { number: 1 } }]
+ };
+
+ expect(
+ shallow( ).find('EuiAccordion')
+ ).toHaveLength(1);
+ });
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/LibraryStacktrace.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/LibraryStacktrace.tsx
new file mode 100644
index 0000000000000..f62ba95407893
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/LibraryStacktrace.tsx
@@ -0,0 +1,55 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiAccordion } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+import styled from 'styled-components';
+import { IStackframe } from '../../../../typings/es_schemas/raw/fields/Stackframe';
+import { Stackframe } from './Stackframe';
+import { px, unit } from '../../../style/variables';
+
+const FramesContainer = styled('div')`
+ padding-left: ${px(unit)};
+`;
+
+interface Props {
+ codeLanguage?: string;
+ stackframes: IStackframe[];
+ id: string;
+}
+
+export function LibraryStacktrace({ codeLanguage, id, stackframes }: Props) {
+ if (stackframes.length === 0) {
+ return null;
+ }
+
+ return (
+
+
+ {stackframes.map((stackframe, i) => (
+
+ ))}
+
+
+ );
+}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Stackframe.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Stackframe.tsx
index cd6c7ce9224a5..a307cc56cc71a 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Stackframe.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Stackframe.tsx
@@ -7,6 +7,7 @@
import theme from '@elastic/eui/dist/eui_theme_light.json';
import React from 'react';
import styled from 'styled-components';
+import { EuiAccordion } from '@elastic/eui';
import {
IStackframe,
IStackframeWithLineContext
@@ -16,16 +17,11 @@ import {
fontFamilyCode,
fontSize
} from '../../../style/variables';
-import { FrameHeading } from '../Stacktrace/FrameHeading';
+import { FrameHeading } from './FrameHeading';
import { Context } from './Context';
import { Variables } from './Variables';
-const CodeHeader = styled.div`
- border-bottom: 1px solid ${theme.euiColorLightShade};
- border-radius: ${borderRadius} ${borderRadius} 0 0;
-`;
-
-const Container = styled.div<{ isLibraryFrame: boolean }>`
+const ContextContainer = styled.div<{ isLibraryFrame: boolean }>`
position: relative;
font-family: ${fontFamilyCode};
font-size: ${fontSize};
@@ -40,12 +36,16 @@ const Container = styled.div<{ isLibraryFrame: boolean }>`
interface Props {
stackframe: IStackframe;
codeLanguage?: string;
+ id: string;
+ initialIsOpen?: boolean;
isLibraryFrame?: boolean;
}
export function Stackframe({
stackframe,
codeLanguage,
+ id,
+ initialIsOpen = false,
isLibraryFrame = false
}: Props) {
if (!hasLineContext(stackframe)) {
@@ -55,19 +55,22 @@ export function Stackframe({
}
return (
-
-
+
-
-
-
-
+ }
+ id={id}
+ initialIsOpen={initialIsOpen}
+ >
+
+
+
-
+
);
}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Variables.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Variables.tsx
index 34c46f84c76b9..6d1b10c90a999 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Variables.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/Variables.tsx
@@ -11,11 +11,11 @@ import { i18n } from '@kbn/i18n';
import React from 'react';
import { borderRadius, px, unit, units } from '../../../style/variables';
import { IStackframe } from '../../../../typings/es_schemas/raw/fields/Stackframe';
-import { DottedKeyValueTable } from '../DottedKeyValueTable';
+import { KeyValueTable } from '../KeyValueTable';
+import { flattenObject } from '../../../utils/flattenObject';
const VariablesContainer = styled.div`
background: ${theme.euiColorEmptyShade};
- border-top: 1px solid ${theme.euiColorLightShade};
border-radius: 0 0 ${borderRadius} ${borderRadius};
padding: ${px(units.half)} ${px(unit)};
`;
@@ -24,29 +24,27 @@ interface Props {
vars: IStackframe['vars'];
}
-export class Variables extends React.Component {
- public render() {
- if (!this.props.vars) {
- return null;
- }
-
- return (
-
-
-
-
-
-
-
-
-
- );
+export const Variables = ({ vars }: Props) => {
+ if (!vars) {
+ return null;
}
-}
+ const flattenedVariables = flattenObject(vars);
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/Stackframe.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/Stackframe.test.tsx
index b0052e8c17b64..5f6519b7c7b96 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/Stackframe.test.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/Stackframe.test.tsx
@@ -16,7 +16,7 @@ describe('Stackframe', () => {
let wrapper: ReactWrapper;
beforeEach(() => {
const stackframe = stacktracesMock[0];
- wrapper = mount( );
+ wrapper = mount( );
});
it('should render correctly', () => {
@@ -38,7 +38,7 @@ describe('Stackframe', () => {
let wrapper: ReactWrapper;
beforeEach(() => {
const stackframe = { line: {} } as IStackframe;
- wrapper = mount( );
+ wrapper = mount( );
});
it('should render only FrameHeading', () => {
@@ -55,7 +55,7 @@ describe('Stackframe', () => {
it('should respect isLibraryFrame', () => {
const stackframe = { line: {} } as IStackframe;
const wrapper = shallow(
-
+
);
expect(wrapper.find('FrameHeading').prop('isLibraryFrame')).toBe(true);
});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/__snapshots__/Stackframe.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/__snapshots__/Stackframe.test.tsx.snap
index 1b465db1c6263..55cec7389dc5c 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/__snapshots__/Stackframe.test.tsx.snap
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/__snapshots__/Stackframe.test.tsx.snap
@@ -1,24 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Stackframe when stackframe has source lines should render correctly 1`] = `
-.c2 {
- color: #98a2b3;
- padding: 8px;
+.c0 {
+ color: #69707d;
+ padding: 8px 0;
font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;
font-size: 14px;
}
-.c3 {
- font-weight: bold;
+.c1 {
color: #000000;
}
-.c4 {
+.c3 {
position: relative;
- border-radius: 0 0 4px 4px;
+ border-radius: 4px;
}
-.c5 {
+.c4 {
position: absolute;
width: 100%;
height: 18px;
@@ -27,15 +26,15 @@ exports[`Stackframe when stackframe has source lines should render correctly 1`]
background-color: #fef6e5;
}
-.c6 {
+.c5 {
position: absolute;
top: 0;
left: 0;
- border-radius: 0 0 0 4px;
+ border-radius: 4px;
background: #f5f7fa;
}
-.c7 {
+.c6 {
position: relative;
min-width: 42px;
padding-left: 8px;
@@ -46,11 +45,11 @@ exports[`Stackframe when stackframe has source lines should render correctly 1`]
border-right: 1px solid #d3dae6;
}
-.c7:last-of-type {
+.c6:last-of-type {
border-radius: 0 0 0 4px;
}
-.c8 {
+.c7 {
position: relative;
min-width: 42px;
padding-left: 8px;
@@ -62,22 +61,22 @@ exports[`Stackframe when stackframe has source lines should render correctly 1`]
background-color: #fef6e5;
}
-.c8:last-of-type {
+.c7:last-of-type {
border-radius: 0 0 0 4px;
}
-.c9 {
+.c8 {
overflow: auto;
margin: 0 0 0 42px;
padding: 0;
background-color: #ffffff;
}
-.c9:last-of-type {
+.c8:last-of-type {
border-radius: 0 0 4px 0;
}
-.c10 {
+.c9 {
margin: 0;
color: inherit;
background: inherit;
@@ -88,7 +87,7 @@ exports[`Stackframe when stackframe has source lines should render correctly 1`]
line-height: 18px;
}
-.c11 {
+.c10 {
position: relative;
padding: 0;
margin: 0;
@@ -96,12 +95,7 @@ exports[`Stackframe when stackframe has source lines should render correctly 1`]
z-index: 2;
}
-.c1 {
- border-bottom: 1px solid #d3dae6;
- border-radius: 4px 4px 0 0;
-}
-
-.c0 {
+.c2 {
position: relative;
font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;
font-size: 14px;
@@ -111,6 +105,7 @@ exports[`Stackframe when stackframe has source lines should render correctly 1`]
}
-
-
-
-
-
",
- "library_frame": false,
- "line": Object {
- "context": " client.query('SELECT id FROM customers WHERE id=$1', [req.body.customer_id], next())",
- "number": 307,
- },
- }
- }
- >
-
-
-
-
- server/routes.js
-
-
- in
-
-
-
- <anonymous>
-
-
- at
-
-
- line
- 307
-
-
-
-
-
-
-
-
+ }
+ id="test"
+ initialIsOpen={false}
+ paddingSize="none"
+ >
+
+
-
-
+
-
-
-
-
+
+
+
+
+
+ ",
+ "library_frame": false,
+ "line": Object {
+ "context": " client.query('SELECT id FROM customers WHERE id=$1', [req.body.customer_id], next())",
+ "number": 307,
+ },
+ }
+ }
>
-
-
-
- 305
- .
-
-
-
-
- 306
- .
-
-
-
-
- 307
- .
-
-
-
-
- 308
- .
-
-
-
+
-
-
-
-
-
-
+
-
-
- })
-
-
-
-
-
-
-
-
+
+ in
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+ at
+
+
-
-
- client.query(
-
- 'SELECT id FROM customers WHERE id=$1'
-
- , [req.body.customer_id], next())
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
",
+ "library_frame": false,
+ "line": Object {
+ "context": " client.query('SELECT id FROM customers WHERE id=$1', [req.body.customer_id], next())",
+ "number": 307,
+ },
}
}
>
-
-
-
+
+
+
+
+
- req.body.lines.forEach(
-
-
+
+ 305
+ .
+
+
+
+
+ 306
+ .
+
+
+
+
+ 307
+ .
+
+
+
+
+ 308
+ .
+
+
+
+
+ 309
+ .
+
+
+
+
+
+
+
- function
-
- (
-
+
+
+
+ })
+
+
+
+
+
+
- line
-
- )
-
- {
-
-
-
-
-
-
-
-
-
-
- client.query(
-
+
+
+
+
+
+
+
+
+
+
+
- 'SELECT id FROM products WHERE id=$1'
-
- , [line.id], next())
-
-
-
-
-
-
-
+ key=" client.query('SELECT id FROM customers WHERE id=$1', [req.body.customer_id], next())2"
+ language="javascript"
+ style={
+ Object {
+ "hljs": Object {
+ "background": "#fff",
+ "color": "black",
+ "display": "block",
+ "overflowX": "auto",
+ "padding": "0.5em",
+ },
+ "hljs-addition": Object {
+ "backgroundColor": "#baeeba",
+ },
+ "hljs-attr": Object {
+ "color": "#5c2699",
+ },
+ "hljs-attribute": Object {
+ "color": "#000",
+ },
+ "hljs-built_in": Object {
+ "color": "#5c2699",
+ },
+ "hljs-builtin-name": Object {
+ "color": "#5c2699",
+ },
+ "hljs-bullet": Object {
+ "color": "#1c00cf",
+ },
+ "hljs-class .hljs-title": Object {
+ "color": "#5c2699",
+ },
+ "hljs-comment": Object {
+ "color": "#006a00",
+ },
+ "hljs-deletion": Object {
+ "backgroundColor": "#ffc8bd",
+ },
+ "hljs-doctag": Object {
+ "fontWeight": "bold",
+ },
+ "hljs-emphasis": Object {
+ "fontStyle": "italic",
+ },
+ "hljs-formula": Object {
+ "backgroundColor": "#eee",
+ "fontStyle": "italic",
+ },
+ "hljs-keyword": Object {
+ "color": "#aa0d91",
+ },
+ "hljs-link": Object {
+ "color": "#080",
+ },
+ "hljs-literal": Object {
+ "color": "#aa0d91",
+ },
+ "hljs-meta": Object {
+ "color": "#1c00cf",
+ },
+ "hljs-name": Object {
+ "color": "#008",
+ },
+ "hljs-number": Object {
+ "color": "#1c00cf",
+ },
+ "hljs-params": Object {
+ "color": "#5c2699",
+ },
+ "hljs-quote": Object {
+ "color": "#006a00",
+ },
+ "hljs-regexp": Object {
+ "color": "#080",
+ },
+ "hljs-section": Object {
+ "color": "#5c2699",
+ },
+ "hljs-selector-class": Object {
+ "color": "#9b703f",
+ },
+ "hljs-selector-id": Object {
+ "color": "#9b703f",
+ },
+ "hljs-selector-tag": Object {
+ "color": "#aa0d91",
+ },
+ "hljs-string": Object {
+ "color": "#c41a16",
+ },
+ "hljs-strong": Object {
+ "fontWeight": "bold",
+ },
+ "hljs-subst": Object {
+ "color": "#000",
+ },
+ "hljs-symbol": Object {
+ "color": "#1c00cf",
+ },
+ "hljs-tag": Object {
+ "color": "#1c00cf",
+ },
+ "hljs-template-variable": Object {
+ "color": "#660",
+ },
+ "hljs-title": Object {
+ "color": "#1c00cf",
+ },
+ "hljs-type": Object {
+ "color": "#5c2699",
+ },
+ "hljs-variable": Object {
+ "color": "#660",
+ },
+ }
+ }
+ >
+
+
+
+
+ client.query(
+
+ 'SELECT id FROM customers WHERE id=$1'
+
+ , [req.body.customer_id], next())
+
+
+
+
+
+
+
+
+
+
+ req.body.lines.forEach(
+
+
+ function
+
+ (
+
+ line
+
+ )
+
+ {
+
+
+
+
+
+
+
+
+
+
+ client.query(
+
+ 'SELECT id FROM products WHERE id=$1'
+
+ , [line.id], next())
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
+
`;
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/index.tsx
index ffa740792cede..ca14be237d22b 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/index.tsx
@@ -10,7 +10,7 @@ import { isEmpty, last } from 'lodash';
import React, { Fragment } from 'react';
import { IStackframe } from '../../../../typings/es_schemas/raw/fields/Stackframe';
import { EmptyMessage } from '../../shared/EmptyMessage';
-import { LibraryStackFrames } from './LibraryStackFrames';
+import { LibraryStacktrace } from './LibraryStacktrace';
import { Stackframe } from './Stackframe';
interface Props {
@@ -25,7 +25,7 @@ export function Stacktrace({ stackframes = [], codeLanguage }: Props) {
heading={i18n.translate(
'xpack.apm.stacktraceTab.noStacktraceAvailableLabel',
{
- defaultMessage: 'No stacktrace available.'
+ defaultMessage: 'No stack trace available.'
}
)}
hideSubheading
@@ -34,16 +34,17 @@ export function Stacktrace({ stackframes = [], codeLanguage }: Props) {
}
const groups = getGroupedStackframes(stackframes);
+
return (
{groups.map((group, i) => {
// library frame
- if (group.isLibraryFrame) {
+ if (group.isLibraryFrame && groups.length > 1) {
return (
-
@@ -56,7 +57,12 @@ export function Stacktrace({ stackframes = [], codeLanguage }: Props) {
return group.stackframes.map((stackframe, idx) => (
{idx > 0 && }
-
+ 1}
+ stackframe={stackframe}
+ />
));
})}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Summary/TransactionSummary.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Summary/TransactionSummary.tsx
index 8f91b8cc5e2af..b6e783a00b5d6 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Summary/TransactionSummary.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Summary/TransactionSummary.tsx
@@ -61,7 +61,7 @@ const TransactionSummary = ({
) : null
];
- return ;
+ return ;
};
export { TransactionSummary };
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/getTimezoneOffsetInMs.test.ts b/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/getTimezoneOffsetInMs.test.ts
index 0605c7dc8b02a..dc815145db4ad 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/getTimezoneOffsetInMs.test.ts
+++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/getTimezoneOffsetInMs.test.ts
@@ -7,7 +7,8 @@
import { getTimezoneOffsetInMs } from './getTimezoneOffsetInMs';
import moment from 'moment-timezone';
-describe('getTimezoneOffsetInMs', () => {
+// FAILING: https://github.com/elastic/kibana/issues/50005
+describe.skip('getTimezoneOffsetInMs', () => {
describe('when no default timezone is set', () => {
it('guesses the timezone', () => {
const guess = jest.fn(() => 'Etc/UTC');
diff --git a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts
index 29a27f034be8a..75b5e0f2a05c8 100644
--- a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts
+++ b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts
@@ -8,6 +8,13 @@ import { compact, pick } from 'lodash';
import datemath from '@elastic/datemath';
import { IUrlParams } from './types';
+interface PathParams {
+ processorEvent?: 'error' | 'metric' | 'transaction';
+ serviceName?: string;
+ errorGroupId?: string;
+ serviceNodeName?: string;
+}
+
export function getParsedDate(rawDate?: string, opts = {}) {
if (rawDate) {
const parsed = datemath.parse(rawDate, opts);
@@ -56,7 +63,7 @@ export function removeUndefinedProps(obj: T): Partial {
return pick(obj, value => value !== undefined);
}
-export function getPathParams(pathname: string = '') {
+export function getPathParams(pathname: string = ''): PathParams {
const paths = getPathAsArray(pathname);
const pageName = paths[0];
@@ -92,17 +99,15 @@ export function getPathParams(pathname: string = '') {
};
case 'nodes':
return {
+ processorEvent: 'metric',
serviceName
};
case 'service-map':
return {
- processorEvent: 'service-map',
serviceName
};
default:
- return {
- processorEvent: 'transaction'
- };
+ return {};
}
case 'traces':
diff --git a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/resolveUrlParams.ts b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/resolveUrlParams.ts
index febe0691d7c1c..7972bdbcf2ee6 100644
--- a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/resolveUrlParams.ts
+++ b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/resolveUrlParams.ts
@@ -53,7 +53,8 @@ export function resolveUrlParams(location: Location, state: TimeUrlParams) {
refreshInterval = TIMEPICKER_DEFAULTS.refreshInterval,
rangeFrom = TIMEPICKER_DEFAULTS.rangeFrom,
rangeTo = TIMEPICKER_DEFAULTS.rangeTo,
- environment
+ environment,
+ searchTerm
} = query;
const localUIFilters = pickKeys(query, ...localUIFilterNames);
@@ -81,6 +82,7 @@ export function resolveUrlParams(location: Location, state: TimeUrlParams) {
kuery: kuery && decodeURIComponent(kuery),
transactionName,
transactionType,
+ searchTerm: toString(searchTerm),
// path params
processorEvent,
diff --git a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/types.ts b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/types.ts
index ca4e0413aa4bf..fc5f5dfb6e301 100644
--- a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/types.ts
+++ b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/types.ts
@@ -29,4 +29,6 @@ export type IUrlParams = {
page?: number;
pageSize?: number;
serviceNodeName?: string;
+ searchTerm?: string;
+ processorEvent?: 'transaction' | 'error' | 'metric';
} & Partial>;
diff --git a/x-pack/legacy/plugins/apm/public/hooks/useKueryBarIndexPattern.ts b/x-pack/legacy/plugins/apm/public/hooks/useKueryBarIndexPattern.ts
new file mode 100644
index 0000000000000..5fb9405559d56
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/hooks/useKueryBarIndexPattern.ts
@@ -0,0 +1,31 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { useFetcher } from './useFetcher';
+
+export function useKueryBarIndexPattern(
+ processorEvent: 'transaction' | 'metric' | 'error' | undefined
+) {
+ const { data: indexPattern, status } = useFetcher(
+ callApmApi => {
+ return callApmApi({
+ pathname: '/api/apm/kuery_bar_index_pattern',
+ forceCache: true,
+ params: {
+ query: {
+ processorEvent
+ }
+ }
+ });
+ },
+ [processorEvent]
+ );
+
+ return {
+ indexPattern,
+ status
+ };
+}
diff --git a/x-pack/legacy/plugins/apm/public/selectors/chartSelectors.ts b/x-pack/legacy/plugins/apm/public/selectors/chartSelectors.ts
index 4b65190d8ef22..b15231e89365a 100644
--- a/x-pack/legacy/plugins/apm/public/selectors/chartSelectors.ts
+++ b/x-pack/legacy/plugins/apm/public/selectors/chartSelectors.ts
@@ -11,7 +11,6 @@ import mean from 'lodash.mean';
import { rgba } from 'polished';
import { TimeSeriesAPIResponse } from '../../server/lib/transactions/charts';
import { ApmTimeSeriesResponse } from '../../server/lib/transactions/charts/get_timeseries_data/transform';
-import { StringMap } from '../../typings/common';
import {
Coordinate,
RectCoordinate,
@@ -192,7 +191,7 @@ function getColorByKey(keys: string[]) {
const assignedColors = ['HTTP 2xx', 'HTTP 3xx', 'HTTP 4xx', 'HTTP 5xx'];
const unknownKeys = difference(keys, assignedColors);
- const unassignedColors: StringMap = zipObject(unknownKeys, [
+ const unassignedColors: Record = zipObject(unknownKeys, [
theme.euiColorVis1,
theme.euiColorVis3,
theme.euiColorVis4,
diff --git a/x-pack/legacy/plugins/apm/public/services/__test__/SessionStorageMock.ts b/x-pack/legacy/plugins/apm/public/services/__test__/SessionStorageMock.ts
index abe44a0fb3934..83e8f020e2529 100644
--- a/x-pack/legacy/plugins/apm/public/services/__test__/SessionStorageMock.ts
+++ b/x-pack/legacy/plugins/apm/public/services/__test__/SessionStorageMock.ts
@@ -4,10 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { StringMap } from '../../../typings/common';
-
export class SessionStorageMock {
- private store: StringMap = {};
+ private store: Record = {};
public clear() {
this.store = {};
diff --git a/x-pack/legacy/plugins/apm/public/services/rest/ml.ts b/x-pack/legacy/plugins/apm/public/services/rest/ml.ts
index 9150c63127317..28b14fa722bbd 100644
--- a/x-pack/legacy/plugins/apm/public/services/rest/ml.ts
+++ b/x-pack/legacy/plugins/apm/public/services/rest/ml.ts
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { npStart } from 'ui/new_platform';
import { HttpServiceBase } from 'kibana/public';
import {
PROCESSOR_EVENT,
@@ -14,6 +13,7 @@ import {
import { getMlJobId, getMlPrefix } from '../../../common/ml_job_constants';
import { callApi } from './callApi';
import { ESFilter } from '../../../typings/elasticsearch';
+import { createCallApmApi, APMClient } from './createCallApmApi';
interface MlResponseItem {
id: string;
@@ -32,7 +32,14 @@ interface StartedMLJobApiResponse {
jobs: MlResponseItem[];
}
-const { core } = npStart;
+async function getTransactionIndices(http: HttpServiceBase) {
+ const callApmApi: APMClient = createCallApmApi(http);
+ const indices = await callApmApi({
+ method: 'GET',
+ pathname: `/api/apm/settings/apm-indices`
+ });
+ return indices['apm_oss.transactionIndices'];
+}
export async function startMLJob({
serviceName,
@@ -43,9 +50,7 @@ export async function startMLJob({
transactionType: string;
http: HttpServiceBase;
}) {
- const indexPatternName = core.injectedMetadata.getInjectedVar(
- 'apmTransactionIndices'
- );
+ const transactionIndices = await getTransactionIndices(http);
const groups = ['apm', serviceName.toLowerCase()];
const filter: ESFilter[] = [
{ term: { [SERVICE_NAME]: serviceName } },
@@ -59,7 +64,7 @@ export async function startMLJob({
body: JSON.stringify({
prefix: getMlPrefix(serviceName, transactionType),
groups,
- indexPatternName,
+ indexPatternName: transactionIndices,
startDatafeed: true,
query: {
bool: {
diff --git a/x-pack/legacy/plugins/apm/public/services/rest/xpack.ts b/x-pack/legacy/plugins/apm/public/services/rest/xpack.ts
index 146376665a0e6..95e283cd67709 100644
--- a/x-pack/legacy/plugins/apm/public/services/rest/xpack.ts
+++ b/x-pack/legacy/plugins/apm/public/services/rest/xpack.ts
@@ -5,7 +5,6 @@
*/
import { HttpServiceBase } from 'kibana/public';
-import { StringMap } from '../../../typings/common';
import { callApi } from './callApi';
export interface LicenseApiResponse {
@@ -13,11 +12,11 @@ export interface LicenseApiResponse {
is_active: boolean;
};
features: {
- beats_management?: StringMap;
- graph?: StringMap;
- grokdebugger?: StringMap;
- index_management?: StringMap;
- logstash?: StringMap;
+ beats_management?: Record;
+ graph?: Record;
+ grokdebugger?: Record;
+ index_management?: Record;
+ logstash?: Record;
ml?: {
is_available: boolean;
license_type: number;
@@ -25,12 +24,12 @@ export interface LicenseApiResponse {
enable_links: boolean;
show_links: boolean;
};
- reporting?: StringMap;
- rollup?: StringMap;
- searchprofiler?: StringMap;
- security?: StringMap;
- spaces?: StringMap;
- tilemap?: StringMap;
+ reporting?: Record;
+ rollup?: Record;
+ searchprofiler?: Record;
+ security?: Record;
+ spaces?: Record;
+ tilemap?: Record;
watcher?: {
is_available: boolean;
enable_links: boolean;
diff --git a/x-pack/legacy/plugins/apm/public/utils/__test__/flattenObject.test.ts b/x-pack/legacy/plugins/apm/public/utils/__test__/flattenObject.test.ts
new file mode 100644
index 0000000000000..8ec826c7f3d08
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/utils/__test__/flattenObject.test.ts
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { flattenObject } from '../flattenObject';
+
+describe('FlattenObject', () => {
+ it('flattens multi level item', () => {
+ const data = {
+ foo: {
+ item1: 'value 1',
+ item2: { itemA: 'value 2' }
+ },
+ bar: {
+ item3: { itemA: { itemAB: 'value AB' } },
+ item4: 'value 4',
+ item5: [1],
+ item6: [1, 2, 3]
+ }
+ };
+
+ const flatten = flattenObject(data);
+ expect(flatten).toEqual([
+ { key: 'bar.item3.itemA.itemAB', value: 'value AB' },
+ { key: 'bar.item4', value: 'value 4' },
+ { key: 'bar.item5', value: 1 },
+ { key: 'bar.item6.0', value: 1 },
+ { key: 'bar.item6.1', value: 2 },
+ { key: 'bar.item6.2', value: 3 },
+ { key: 'foo.item1', value: 'value 1' },
+ { key: 'foo.item2.itemA', value: 'value 2' }
+ ]);
+ });
+ it('returns an empty array if no valid object is provided', () => {
+ expect(flattenObject({})).toEqual([]);
+ expect(flattenObject(null)).toEqual([]);
+ expect(flattenObject(undefined)).toEqual([]);
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/utils/flattenObject.ts b/x-pack/legacy/plugins/apm/public/utils/flattenObject.ts
new file mode 100644
index 0000000000000..01a58ac03d0c3
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/utils/flattenObject.ts
@@ -0,0 +1,35 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { compact, isObject } from 'lodash';
+
+export interface KeyValuePair {
+ key: string;
+ value: unknown;
+}
+
+export const flattenObject = (
+ item: Record | null | undefined,
+ parentKey?: string
+): KeyValuePair[] => {
+ if (item) {
+ const isArrayWithSingleValue = Array.isArray(item) && item.length === 1;
+ return Object.keys(item)
+ .sort()
+ .reduce((acc: KeyValuePair[], key) => {
+ const childKey = isArrayWithSingleValue ? '' : key;
+ const currentKey = compact([parentKey, childKey]).join('.');
+ // item[key] can be a primitive (string, number, boolean, null, undefined) or Object or Array
+ if (isObject(item[key])) {
+ return acc.concat(flattenObject(item[key], currentKey));
+ } else {
+ acc.push({ key: currentKey, value: item[key] });
+ return acc;
+ }
+ }, []);
+ }
+ return [];
+};
diff --git a/x-pack/legacy/plugins/apm/public/utils/httpStatusCodeToColor.ts b/x-pack/legacy/plugins/apm/public/utils/httpStatusCodeToColor.ts
index db1ed490eb7f2..130a7b52ea33b 100644
--- a/x-pack/legacy/plugins/apm/public/utils/httpStatusCodeToColor.ts
+++ b/x-pack/legacy/plugins/apm/public/utils/httpStatusCodeToColor.ts
@@ -5,8 +5,6 @@
*/
import theme from '@elastic/eui/dist/eui_theme_light.json';
-import { StringMap } from '../../typings/common';
-
const { euiColorDarkShade, euiColorWarning } = theme;
export const errorColor = '#c23c2b';
@@ -14,7 +12,7 @@ export const neutralColor = euiColorDarkShade;
export const successColor = '#327a42';
export const warningColor = euiColorWarning;
-const httpStatusCodeColors: StringMap = {
+const httpStatusCodeColors: Record = {
1: neutralColor,
2: successColor,
3: neutralColor,
diff --git a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx
index 2e3c8940680fe..a18882120fe75 100644
--- a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx
+++ b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx
@@ -102,6 +102,15 @@ interface MockSetup {
has: any;
};
uiFiltersES: ESFilter[];
+ indices: {
+ 'apm_oss.sourcemapIndices': string;
+ 'apm_oss.errorIndices': string;
+ 'apm_oss.onboardingIndices': string;
+ 'apm_oss.spanIndices': string;
+ 'apm_oss.transactionIndices': string;
+ 'apm_oss.metricsIndices': string;
+ 'apm_oss.apmAgentConfigurationIndex': string;
+ };
}
export async function inspectSearchParams(
@@ -127,7 +136,16 @@ export async function inspectSearchParams(
{
term: { 'service.environment': 'prod' }
}
- ]
+ ],
+ indices: {
+ 'apm_oss.sourcemapIndices': 'myIndex',
+ 'apm_oss.errorIndices': 'myIndex',
+ 'apm_oss.onboardingIndices': 'myIndex',
+ 'apm_oss.spanIndices': 'myIndex',
+ 'apm_oss.transactionIndices': 'myIndex',
+ 'apm_oss.metricsIndices': 'myIndex',
+ 'apm_oss.apmAgentConfigurationIndex': 'myIndex'
+ }
};
try {
await fn(mockSetup);
diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/__snapshots__/get_buckets.test.ts.snap b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/__snapshots__/get_buckets.test.ts.snap
index 8d89e22fa9864..d336d71424750 100644
--- a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/__snapshots__/get_buckets.test.ts.snap
+++ b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/__snapshots__/get_buckets.test.ts.snap
@@ -50,7 +50,7 @@ Array [
},
"size": 0,
},
- "index": "myIndex",
+ "index": "apm-*",
},
],
]
diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts
index 0b8cd8ae8703f..b7081c43465bf 100644
--- a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts
@@ -39,7 +39,16 @@ describe('timeseriesFetcher', () => {
{
term: { 'service.environment': 'prod' }
}
- ]
+ ],
+ indices: {
+ 'apm_oss.sourcemapIndices': 'apm-*',
+ 'apm_oss.errorIndices': 'apm-*',
+ 'apm_oss.onboardingIndices': 'apm-*',
+ 'apm_oss.spanIndices': 'apm-*',
+ 'apm_oss.transactionIndices': 'apm-*',
+ 'apm_oss.metricsIndices': 'apm-*',
+ 'apm_oss.apmAgentConfigurationIndex': '.apm-agent-configuration'
+ }
}
});
});
diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts
index 6059f2b0051a7..afb8237178a20 100644
--- a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts
@@ -25,7 +25,7 @@ export async function getBuckets({
bucketSize: number;
setup: Setup;
}) {
- const { start, end, uiFiltersES, client, config } = setup;
+ const { start, end, uiFiltersES, client, indices } = setup;
const filter: ESFilter[] = [
{ term: { [PROCESSOR_EVENT]: 'error' } },
{ term: { [SERVICE_NAME]: serviceName } },
@@ -38,7 +38,7 @@ export async function getBuckets({
}
const params = {
- index: config.get('apm_oss.errorIndices'),
+ index: indices['apm_oss.errorIndices'],
body: {
size: 0,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/get_error_group.ts b/x-pack/legacy/plugins/apm/server/lib/errors/get_error_group.ts
index dee5deb4064e4..caadbfef32698 100644
--- a/x-pack/legacy/plugins/apm/server/lib/errors/get_error_group.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/errors/get_error_group.ts
@@ -29,10 +29,10 @@ export async function getErrorGroup({
groupId: string;
setup: Setup;
}) {
- const { start, end, uiFiltersES, client, config } = setup;
+ const { start, end, uiFiltersES, client, indices } = setup;
const params = {
- index: config.get('apm_oss.errorIndices'),
+ index: indices['apm_oss.errorIndices'],
body: {
size: 1,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts b/x-pack/legacy/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts
index aaac56d16c599..9a6aed02e2a84 100644
--- a/x-pack/legacy/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts
@@ -24,10 +24,10 @@ export async function getTraceErrorsPerTransaction(
traceId: string,
setup: Setup
): Promise {
- const { start, end, client, config } = setup;
+ const { start, end, client, indices } = setup;
const params = {
- index: config.get('apm_oss.errorIndices'),
+ index: indices['apm_oss.errorIndices'],
body: {
size: 0,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts
index 9b2c97fab7aa3..ee41599454dd6 100644
--- a/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts
@@ -12,9 +12,9 @@ import {
IndicesCreateParams
} from 'elasticsearch';
import { Legacy } from 'kibana';
-import { cloneDeep, has, isString, set } from 'lodash';
+import { cloneDeep, has, isString, set, pick } from 'lodash';
import { OBSERVER_VERSION_MAJOR } from '../../../common/elasticsearch_fieldnames';
-import { StringMap } from '../../../typings/common';
+import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
import {
ESSearchResponse,
ESSearchRequest
@@ -23,17 +23,6 @@ import {
// `type` was deprecated in 7.0
export type APMIndexDocumentParams = Omit, 'type'>;
-function getApmIndices(config: Legacy.KibanaConfig) {
- return [
- config.get('apm_oss.errorIndices'),
- config.get('apm_oss.metricsIndices'),
- config.get('apm_oss.onboardingIndices'),
- config.get('apm_oss.sourcemapIndices'),
- config.get('apm_oss.spanIndices'),
- config.get('apm_oss.transactionIndices')
- ];
-}
-
export function isApmIndex(
apmIndices: string[],
indexParam: SearchParams['index']
@@ -76,10 +65,23 @@ async function getParamsForSearchRequest(
params: SearchParams,
apmOptions?: APMOptions
) {
- const config = req.server.config();
const uiSettings = req.getUiSettingsService();
- const apmIndices = getApmIndices(config);
- const includeFrozen = await uiSettings.get('search:includeFrozen');
+ const [indices, includeFrozen] = await Promise.all([
+ getApmIndices(req.server),
+ uiSettings.get('search:includeFrozen')
+ ]);
+
+ // Get indices for legacy data filter (only those which apply)
+ const apmIndices: string[] = Object.values(
+ pick(indices, [
+ 'apm_oss.sourcemapIndices',
+ 'apm_oss.errorIndices',
+ 'apm_oss.onboardingIndices',
+ 'apm_oss.spanIndices',
+ 'apm_oss.transactionIndices',
+ 'apm_oss.metricsIndices'
+ ])
+ );
return {
...addFilterForLegacyData(apmIndices, params, apmOptions), // filter out pre-7.0 data
ignore_throttled: !includeFrozen // whether to query frozen indices or not
@@ -92,7 +94,7 @@ interface APMOptions {
export function getESClient(req: Legacy.Request) {
const cluster = req.server.plugins.elasticsearch.getCluster('data');
- const query = req.query as StringMap;
+ const query = req.query as Record;
return {
search: async <
diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/saved_objects_client.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/saved_objects_client.ts
index 3070d7b00b684..81dd8b34c8847 100644
--- a/x-pack/legacy/plugins/apm/server/lib/helpers/saved_objects_client.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/helpers/saved_objects_client.ts
@@ -6,10 +6,10 @@
import { Server } from 'hapi';
-export function getSavedObjectsClient(server: Server) {
+export function getSavedObjectsClient(server: Server, clusterName = 'admin') {
const { SavedObjectsClient, getSavedObjectsRepository } = server.savedObjects;
const { callWithInternalUser } = server.plugins.elasticsearch.getCluster(
- 'admin'
+ clusterName
);
const internalRepository = getSavedObjectsRepository(callWithInternalUser);
return new SavedObjectsClient(internalRepository);
diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts
index e8cf56fcd0802..57de438be7f2a 100644
--- a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts
@@ -3,11 +3,22 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
import { Legacy } from 'kibana';
import { setupRequest } from './setup_request';
import { uiSettingsServiceMock } from 'src/core/server/mocks';
+jest.mock('../settings/apm_indices/get_apm_indices', () => ({
+ getApmIndices: async () => ({
+ 'apm_oss.sourcemapIndices': 'apm-*',
+ 'apm_oss.errorIndices': 'apm-*',
+ 'apm_oss.onboardingIndices': 'apm-*',
+ 'apm_oss.spanIndices': 'apm-*',
+ 'apm_oss.transactionIndices': 'apm-*',
+ 'apm_oss.metricsIndices': 'apm-*',
+ 'apm_oss.apmAgentConfigurationIndex': 'apm-*'
+ })
+}));
+
function getMockRequest() {
const callWithRequestSpy = jest.fn();
const mockRequest = ({
diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts
index 4054537e04b40..3ec519d5e71b5 100644
--- a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts
@@ -10,6 +10,7 @@ import moment from 'moment';
import { getESClient } from './es_client';
import { getUiFiltersES } from './convert_ui_filters/get_ui_filters_es';
import { PromiseReturnType } from '../../../typings/common';
+import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
function decodeUiFilters(server: Server, uiFiltersEncoded?: string) {
if (!uiFiltersEncoded) {
@@ -31,12 +32,17 @@ export async function setupRequest(req: Legacy.Request) {
const query = (req.query as unknown) as APMRequestQuery;
const { server } = req;
const config = server.config();
+ const [uiFiltersES, indices] = await Promise.all([
+ decodeUiFilters(server, query.uiFilters),
+ getApmIndices(server)
+ ]);
return {
start: moment.utc(query.start).valueOf(),
end: moment.utc(query.end).valueOf(),
- uiFiltersES: await decodeUiFilters(server, query.uiFilters),
+ uiFiltersES,
client: getESClient(req),
- config
+ config,
+ indices
};
}
diff --git a/x-pack/legacy/plugins/apm/server/lib/index_pattern/getKueryBarIndexPattern.ts b/x-pack/legacy/plugins/apm/server/lib/index_pattern/getKueryBarIndexPattern.ts
new file mode 100644
index 0000000000000..a5ba4573cfd58
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/server/lib/index_pattern/getKueryBarIndexPattern.ts
@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { Legacy } from 'kibana';
+import { StaticIndexPattern } from 'ui/index_patterns';
+import { APICaller } from 'src/core/server';
+import { IndexPatternsFetcher } from '../../../../../../../src/plugins/data/server';
+import { Setup } from '../helpers/setup_request';
+
+export const getKueryBarIndexPattern = async ({
+ request,
+ processorEvent,
+ setup
+}: {
+ request: Legacy.Request;
+ processorEvent?: 'transaction' | 'error' | 'metric';
+ setup: Setup;
+}) => {
+ const { indices } = setup;
+
+ const indexPatternsFetcher = new IndexPatternsFetcher(
+ (...rest: Parameters) =>
+ request.server.plugins.elasticsearch
+ .getCluster('data')
+ .callWithRequest(request, ...rest)
+ );
+
+ const indexNames = processorEvent
+ ? [processorEvent]
+ : ['transaction' as const, 'metric' as const, 'error' as const];
+
+ const indicesMap = {
+ transaction: indices['apm_oss.transactionIndices'],
+ metric: indices['apm_oss.metricsIndices'],
+ error: indices['apm_oss.errorIndices']
+ };
+
+ const configuredIndices = indexNames.map(name => indicesMap[name]);
+
+ const fields = await indexPatternsFetcher.getFieldsForWildcard({
+ pattern: configuredIndices
+ });
+
+ const pattern: StaticIndexPattern = {
+ fields,
+ title: configuredIndices.join(',')
+ };
+
+ return pattern;
+};
diff --git a/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap b/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap
index 71217ccc36f7b..acd5dc119b737 100644
--- a/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap
+++ b/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap
@@ -56,9 +56,7 @@ Object {
},
"size": 0,
},
- "index": Array [
- "myIndex",
- ],
+ "index": "myIndex",
"terminateAfter": 1,
}
`;
@@ -228,8 +226,6 @@ Object {
},
"size": 0,
},
- "index": Array [
- "myIndex",
- ],
+ "index": "myIndex",
}
`;
diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts
index b39e35a305b19..bbb18eae7eb09 100644
--- a/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts
@@ -13,14 +13,14 @@ import { rangeFilter } from '../helpers/range_filter';
import { Setup } from '../helpers/setup_request';
export async function getServiceAgentName(serviceName: string, setup: Setup) {
- const { start, end, client, config } = setup;
+ const { start, end, client, indices } = setup;
const params = {
terminateAfter: 1,
index: [
- config.get('apm_oss.errorIndices'),
- config.get('apm_oss.transactionIndices'),
- config.get('apm_oss.metricsIndices')
+ indices['apm_oss.errorIndices'],
+ indices['apm_oss.transactionIndices'],
+ indices['apm_oss.metricsIndices']
],
body: {
size: 0,
diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts
index 9d651247d5cee..00ffa7484bb48 100644
--- a/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts
@@ -16,10 +16,10 @@ export async function getServiceTransactionTypes(
serviceName: string,
setup: Setup
) {
- const { start, end, client, config } = setup;
+ const { start, end, client, indices } = setup;
const params = {
- index: [config.get('apm_oss.transactionIndices')],
+ index: indices['apm_oss.transactionIndices'],
body: {
size: 0,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts
index f9a7671abd994..6c28d19a14711 100644
--- a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts
@@ -9,15 +9,15 @@ import { Setup } from '../../helpers/setup_request';
// Note: this logic is duplicated in tutorials/apm/envs/on_prem
export async function getAgentStatus(setup: Setup) {
- const { client, config } = setup;
+ const { client, indices } = setup;
const params = {
terminateAfter: 1,
index: [
- config.get('apm_oss.errorIndices'),
- config.get('apm_oss.metricsIndices'),
- config.get('apm_oss.sourcemapIndices'),
- config.get('apm_oss.transactionIndices')
+ indices['apm_oss.errorIndices'],
+ indices['apm_oss.metricsIndices'],
+ indices['apm_oss.sourcemapIndices'],
+ indices['apm_oss.transactionIndices']
],
body: {
size: 0,
diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts
index 1379d79326add..5497eaa13d34b 100644
--- a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts
@@ -12,11 +12,11 @@ import { Setup } from '../../helpers/setup_request';
// returns true if 6.x data is found
export async function getLegacyDataStatus(setup: Setup) {
- const { client, config } = setup;
+ const { client, indices } = setup;
const params = {
terminateAfter: 1,
- index: [config.get('apm_oss.transactionIndices')],
+ index: indices['apm_oss.transactionIndices'],
body: {
size: 0,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts
index 4226c073b1de0..861732ee03923 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts
@@ -6,15 +6,15 @@
import { InternalCoreSetup } from 'src/core/server';
import { CallCluster } from '../../../../../../../../src/legacy/core_plugins/elasticsearch';
+import { getApmIndices } from '../apm_indices/get_apm_indices';
export async function createApmAgentConfigurationIndex(
core: InternalCoreSetup
) {
try {
const { server } = core.http;
- const index = server
- .config()
- .get('apm_oss.apmAgentConfigurationIndex');
+ const indices = await getApmIndices(server);
+ const index = indices['apm_oss.apmAgentConfigurationIndex'];
const { callWithInternalUser } = server.plugins.elasticsearch.getCluster(
'admin'
);
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts
index 9f0d8e2f1c718..25a4f5141498f 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts
@@ -21,11 +21,11 @@ export async function createOrUpdateConfiguration({
>;
setup: Setup;
}) {
- const { client, config } = setup;
+ const { client, indices } = setup;
const params: APMIndexDocumentParams = {
refresh: true,
- index: config.get('apm_oss.apmAgentConfigurationIndex'),
+ index: indices['apm_oss.apmAgentConfigurationIndex'],
body: {
agent_name: configuration.agent_name,
service: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts
index 82b192125a5cf..896363c054ba7 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts
@@ -13,11 +13,11 @@ export async function deleteConfiguration({
configurationId: string;
setup: Setup;
}) {
- const { client, config } = setup;
+ const { client, indices } = setup;
const params = {
refresh: 'wait_for',
- index: config.get('apm_oss.apmAgentConfigurationIndex'),
+ index: indices['apm_oss.apmAgentConfigurationIndex'],
id: configurationId
};
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts
index 7742bc938816f..21663b813f01f 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts
@@ -19,14 +19,14 @@ export async function getAgentNameByService({
serviceName: string;
setup: Setup;
}) {
- const { client, config } = setup;
+ const { client, indices } = setup;
const params = {
terminateAfter: 1,
index: [
- config.get('apm_oss.metricsIndices'),
- config.get('apm_oss.errorIndices'),
- config.get('apm_oss.transactionIndices')
+ indices['apm_oss.metricsIndices'],
+ indices['apm_oss.errorIndices'],
+ indices['apm_oss.transactionIndices']
],
body: {
size: 0,
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts
index aad31feef000b..8215e2b9fd668 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts
@@ -20,7 +20,7 @@ export async function getAllEnvironments({
serviceName: string | undefined;
setup: Setup;
}) {
- const { client, config } = setup;
+ const { client, indices } = setup;
// omit filter for service.name if "All" option is selected
const serviceNameFilter = serviceName
@@ -29,9 +29,9 @@ export async function getAllEnvironments({
const params = {
index: [
- config.get('apm_oss.metricsIndices'),
- config.get('apm_oss.errorIndices'),
- config.get('apm_oss.transactionIndices')
+ indices['apm_oss.metricsIndices'],
+ indices['apm_oss.errorIndices'],
+ indices['apm_oss.transactionIndices']
],
body: {
size: 0,
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts
index 6b557f21f3457..d5aa389cea335 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts
@@ -19,14 +19,14 @@ export async function getExistingEnvironmentsForService({
serviceName: string | undefined;
setup: Setup;
}) {
- const { client, config } = setup;
+ const { client, indices } = setup;
const bool = serviceName
? { filter: [{ term: { [SERVICE_NAME]: serviceName } }] }
: { must_not: [{ exists: { field: SERVICE_NAME } }] };
const params = {
- index: config.get('apm_oss.apmAgentConfigurationIndex'),
+ index: indices['apm_oss.apmAgentConfigurationIndex'],
body: {
size: 0,
query: { bool },
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts
index dfc1041c96488..51a4564f53576 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts
@@ -17,13 +17,13 @@ export type AgentConfigurationServicesAPIResponse = PromiseReturnType<
typeof getServiceNames
>;
export async function getServiceNames({ setup }: { setup: Setup }) {
- const { client, config } = setup;
+ const { client, indices } = setup;
const params = {
index: [
- config.get('apm_oss.metricsIndices'),
- config.get('apm_oss.errorIndices'),
- config.get('apm_oss.transactionIndices')
+ indices['apm_oss.metricsIndices'],
+ indices['apm_oss.errorIndices'],
+ indices['apm_oss.transactionIndices']
],
body: {
size: 0,
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts
index 9edceb86dda8d..283f30b51441d 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts
@@ -12,10 +12,10 @@ export type AgentConfigurationListAPIResponse = PromiseReturnType<
typeof listConfigurations
>;
export async function listConfigurations({ setup }: { setup: Setup }) {
- const { client, config } = setup;
+ const { client, indices } = setup;
const params = {
- index: config.get('apm_oss.apmAgentConfigurationIndex')
+ index: indices['apm_oss.apmAgentConfigurationIndex']
};
const resp = await client.search(params);
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts
index 867045142cea0..e5349edb67f30 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts
@@ -16,10 +16,10 @@ export async function markAppliedByAgent({
body: AgentConfiguration;
setup: Setup;
}) {
- const { client, config } = setup;
+ const { client, indices } = setup;
const params = {
- index: config.get('apm_oss.apmAgentConfigurationIndex'),
+ index: indices['apm_oss.apmAgentConfigurationIndex'],
id, // by specifying the `id` elasticsearch will do an "upsert"
body: {
...body,
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts
index e8db37891e7ae..400bd0207771a 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts
@@ -15,7 +15,18 @@ describe('search configurations', () => {
environment: 'production',
setup: ({
config: { get: () => '' },
- client: { search: async () => searchMocks }
+ client: { search: async () => searchMocks },
+ indices: {
+ apm_oss: {
+ sourcemapIndices: 'myIndex',
+ errorIndices: 'myIndex',
+ onboardingIndices: 'myIndex',
+ spanIndices: 'myIndex',
+ transactionIndices: 'myIndex',
+ metricsIndices: 'myIndex',
+ apmAgentConfigurationIndex: 'myIndex'
+ }
+ }
} as unknown) as Setup
});
@@ -29,7 +40,18 @@ describe('search configurations', () => {
environment: 'production',
setup: ({
config: { get: () => '' },
- client: { search: async () => searchMocks }
+ client: { search: async () => searchMocks },
+ indices: {
+ apm_oss: {
+ sourcemapIndices: 'myIndex',
+ errorIndices: 'myIndex',
+ onboardingIndices: 'myIndex',
+ spanIndices: 'myIndex',
+ transactionIndices: 'myIndex',
+ metricsIndices: 'myIndex',
+ apmAgentConfigurationIndex: 'myIndex'
+ }
+ }
} as unknown) as Setup
});
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts
index 6b0dc370dd878..35d76d745cf4f 100644
--- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts
@@ -20,7 +20,7 @@ export async function searchConfigurations({
environment?: string;
setup: Setup;
}) {
- const { client, config } = setup;
+ const { client, indices } = setup;
// sorting order
// 1. exact match: service.name AND service.environment (eg. opbeans-node / production)
@@ -33,7 +33,7 @@ export async function searchConfigurations({
: [];
const params = {
- index: config.get('apm_oss.apmAgentConfigurationIndex'),
+ index: indices['apm_oss.apmAgentConfigurationIndex'],
body: {
query: {
bool: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts
new file mode 100644
index 0000000000000..cd237a5264099
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts
@@ -0,0 +1,101 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { Server } from 'hapi';
+import { merge } from 'lodash';
+import { KibanaConfig } from 'src/legacy/server/kbn_server';
+import { getSavedObjectsClient } from '../../helpers/saved_objects_client';
+import { Setup } from '../../helpers/setup_request';
+import { PromiseReturnType } from '../../../../typings/common';
+
+export interface ApmIndicesConfig {
+ 'apm_oss.sourcemapIndices': string;
+ 'apm_oss.errorIndices': string;
+ 'apm_oss.onboardingIndices': string;
+ 'apm_oss.spanIndices': string;
+ 'apm_oss.transactionIndices': string;
+ 'apm_oss.metricsIndices': string;
+ 'apm_oss.apmAgentConfigurationIndex': string;
+}
+
+export type ApmIndicesName = keyof ApmIndicesConfig;
+
+export const APM_INDICES_SAVED_OBJECT_TYPE = 'apm-indices';
+export const APM_INDICES_SAVED_OBJECT_ID = 'apm-indices';
+
+async function getApmIndicesSavedObject(server: Server) {
+ const savedObjectsClient = getSavedObjectsClient(server, 'data');
+ const apmIndices = await savedObjectsClient.get>(
+ APM_INDICES_SAVED_OBJECT_TYPE,
+ APM_INDICES_SAVED_OBJECT_ID
+ );
+ return apmIndices.attributes;
+}
+
+function getApmIndicesConfig(config: KibanaConfig): ApmIndicesConfig {
+ return {
+ 'apm_oss.sourcemapIndices': config.get('apm_oss.sourcemapIndices'),
+ 'apm_oss.errorIndices': config.get('apm_oss.errorIndices'),
+ 'apm_oss.onboardingIndices': config.get(
+ 'apm_oss.onboardingIndices'
+ ),
+ 'apm_oss.spanIndices': config.get('apm_oss.spanIndices'),
+ 'apm_oss.transactionIndices': config.get(
+ 'apm_oss.transactionIndices'
+ ),
+ 'apm_oss.metricsIndices': config.get('apm_oss.metricsIndices'),
+ 'apm_oss.apmAgentConfigurationIndex': config.get(
+ 'apm_oss.apmAgentConfigurationIndex'
+ )
+ };
+}
+
+export async function getApmIndices(server: Server) {
+ try {
+ const apmIndicesSavedObject = await getApmIndicesSavedObject(server);
+ const apmIndicesConfig = getApmIndicesConfig(server.config());
+ return merge({}, apmIndicesConfig, apmIndicesSavedObject);
+ } catch (error) {
+ return getApmIndicesConfig(server.config());
+ }
+}
+
+const APM_UI_INDICES: ApmIndicesName[] = [
+ 'apm_oss.sourcemapIndices',
+ 'apm_oss.errorIndices',
+ 'apm_oss.onboardingIndices',
+ 'apm_oss.spanIndices',
+ 'apm_oss.transactionIndices',
+ 'apm_oss.metricsIndices',
+ 'apm_oss.apmAgentConfigurationIndex'
+];
+
+export async function getApmIndexSettings({
+ setup,
+ server
+}: {
+ setup: Setup;
+ server: Server;
+}) {
+ const { config } = setup;
+ let apmIndicesSavedObject: PromiseReturnType;
+ try {
+ apmIndicesSavedObject = await getApmIndicesSavedObject(server);
+ } catch (error) {
+ if (error.output && error.output.statusCode === 404) {
+ apmIndicesSavedObject = {};
+ } else {
+ throw error;
+ }
+ }
+ const apmIndicesConfig = getApmIndicesConfig(config);
+
+ return APM_UI_INDICES.map(configurationName => ({
+ configurationName,
+ defaultValue: apmIndicesConfig[configurationName], // value defined in kibana[.dev].yml
+ savedValue: apmIndicesSavedObject[configurationName] // value saved via Saved Objects service
+ }));
+}
diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts
new file mode 100644
index 0000000000000..8de47c5c44144
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { Server } from 'hapi';
+import { getSavedObjectsClient } from '../../helpers/saved_objects_client';
+import {
+ ApmIndicesConfig,
+ APM_INDICES_SAVED_OBJECT_TYPE,
+ APM_INDICES_SAVED_OBJECT_ID
+} from './get_apm_indices';
+
+export async function saveApmIndices(
+ server: Server,
+ apmIndicesSavedObject: Partial
+) {
+ const savedObjectsClient = getSavedObjectsClient(server, 'data');
+ return await savedObjectsClient.create(
+ APM_INDICES_SAVED_OBJECT_TYPE,
+ apmIndicesSavedObject,
+ {
+ id: APM_INDICES_SAVED_OBJECT_ID,
+ overwrite: true
+ }
+ );
+}
diff --git a/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts b/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts
index 71b65982db9f0..0df5cc016431d 100644
--- a/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts
@@ -17,13 +17,13 @@ import { rangeFilter } from '../helpers/range_filter';
import { Setup } from '../helpers/setup_request';
export async function getTraceItems(traceId: string, setup: Setup) {
- const { start, end, client, config } = setup;
+ const { start, end, client, config, indices } = setup;
const maxTraceItems = config.get('xpack.apm.ui.maxTraceItems');
const params = {
index: [
- config.get('apm_oss.spanIndices'),
- config.get('apm_oss.transactionIndices')
+ indices['apm_oss.spanIndices'],
+ indices['apm_oss.transactionIndices']
],
body: {
size: maxTraceItems,
diff --git a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts
index fc7b1b4127892..99553690359cf 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts
@@ -16,15 +16,22 @@ function getSetup() {
config: {
get: jest.fn((key: string) => {
switch (key) {
- case 'apm_oss.transactionIndices':
- return 'myIndex';
case 'xpack.apm.ui.transactionGroupBucketSize':
return 100;
}
}),
has: () => true
},
- uiFiltersES: [{ term: { 'service.environment': 'test' } }]
+ uiFiltersES: [{ term: { 'service.environment': 'test' } }],
+ indices: {
+ 'apm_oss.sourcemapIndices': 'myIndex',
+ 'apm_oss.errorIndices': 'myIndex',
+ 'apm_oss.onboardingIndices': 'myIndex',
+ 'apm_oss.spanIndices': 'myIndex',
+ 'apm_oss.transactionIndices': 'myIndex',
+ 'apm_oss.metricsIndices': 'myIndex',
+ 'apm_oss.apmAgentConfigurationIndex': 'myIndex'
+ }
};
}
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts
index e2989498181ca..e092942a25ba6 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts
@@ -21,9 +21,9 @@ export async function getTransactionAvgDurationByCountry({
setup: Setup;
serviceName: string;
}) {
- const { uiFiltersES, client, config, start, end } = setup;
+ const { uiFiltersES, client, start, end, indices } = setup;
const params = {
- index: config.get('apm_oss.transactionIndices'),
+ index: indices['apm_oss.transactionIndices'],
body: {
size: 0,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts
index e707ce3eafe18..67816d67a29a2 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts
@@ -9,6 +9,16 @@ import * as constants from './constants';
import noDataResponse from './mock-responses/noData.json';
import dataResponse from './mock-responses/data.json';
+const mockIndices = {
+ 'apm_oss.sourcemapIndices': 'myIndex',
+ 'apm_oss.errorIndices': 'myIndex',
+ 'apm_oss.onboardingIndices': 'myIndex',
+ 'apm_oss.spanIndices': 'myIndex',
+ 'apm_oss.transactionIndices': 'myIndex',
+ 'apm_oss.metricsIndices': 'myIndex',
+ 'apm_oss.apmAgentConfigurationIndex': 'myIndex'
+};
+
describe('getTransactionBreakdown', () => {
it('returns an empty array if no data is available', async () => {
const clientSpy = jest.fn().mockReturnValueOnce(noDataResponse);
@@ -24,7 +34,8 @@ describe('getTransactionBreakdown', () => {
get: () => 'myIndex' as any,
has: () => true
},
- uiFiltersES: []
+ uiFiltersES: [],
+ indices: mockIndices
}
});
@@ -47,7 +58,8 @@ describe('getTransactionBreakdown', () => {
get: () => 'myIndex' as any,
has: () => true
},
- uiFiltersES: []
+ uiFiltersES: [],
+ indices: mockIndices
}
});
@@ -87,7 +99,8 @@ describe('getTransactionBreakdown', () => {
get: () => 'myIndex' as any,
has: () => true
},
- uiFiltersES: []
+ uiFiltersES: [],
+ indices: mockIndices
}
});
@@ -126,7 +139,8 @@ describe('getTransactionBreakdown', () => {
get: () => 'myIndex' as any,
has: () => true
},
- uiFiltersES: []
+ uiFiltersES: [],
+ indices: mockIndices
}
});
@@ -149,7 +163,8 @@ describe('getTransactionBreakdown', () => {
get: () => 'myIndex' as any,
has: () => true
},
- uiFiltersES: []
+ uiFiltersES: [],
+ indices: mockIndices
}
});
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts
index ecf963fec3fe9..a21c4f38ac30c 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts
@@ -32,7 +32,7 @@ export async function getTransactionBreakdown({
transactionName?: string;
transactionType: string;
}) {
- const { uiFiltersES, client, config, start, end } = setup;
+ const { uiFiltersES, client, start, end, indices } = setup;
const subAggs = {
sum_all_self_times: {
@@ -88,7 +88,7 @@ export async function getTransactionBreakdown({
}
const params = {
- index: config.get('apm_oss.metricsIndices'),
+ index: indices['apm_oss.metricsIndices'],
body: {
size: 0,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts
index 07f1d96618198..cddc66e52cf70 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts
@@ -30,7 +30,16 @@ describe('getAnomalySeries', () => {
get: () => 'myIndex' as any,
has: () => true
},
- uiFiltersES: []
+ uiFiltersES: [],
+ indices: {
+ 'apm_oss.sourcemapIndices': 'myIndex',
+ 'apm_oss.errorIndices': 'myIndex',
+ 'apm_oss.onboardingIndices': 'myIndex',
+ 'apm_oss.spanIndices': 'myIndex',
+ 'apm_oss.transactionIndices': 'myIndex',
+ 'apm_oss.metricsIndices': 'myIndex',
+ 'apm_oss.apmAgentConfigurationIndex': 'myIndex'
+ }
}
});
});
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts
index dc568d653a5ee..5056a100de3ce 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts
@@ -29,7 +29,16 @@ describe('timeseriesFetcher', () => {
{
term: { 'service.environment': 'test' }
}
- ]
+ ],
+ indices: {
+ 'apm_oss.sourcemapIndices': 'myIndex',
+ 'apm_oss.errorIndices': 'myIndex',
+ 'apm_oss.onboardingIndices': 'myIndex',
+ 'apm_oss.spanIndices': 'myIndex',
+ 'apm_oss.transactionIndices': 'myIndex',
+ 'apm_oss.metricsIndices': 'myIndex',
+ 'apm_oss.apmAgentConfigurationIndex': 'myIndex'
+ }
}
});
});
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts
index 97368b7d92efc..0d9cccb3b56d3 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts
@@ -30,7 +30,7 @@ export function timeseriesFetcher({
transactionName: string | undefined;
setup: Setup;
}) {
- const { start, end, uiFiltersES, client, config } = setup;
+ const { start, end, uiFiltersES, client, indices } = setup;
const { intervalString } = getBucketSize(start, end, 'auto');
const filter: ESFilter[] = [
@@ -50,7 +50,7 @@ export function timeseriesFetcher({
}
const params = {
- index: config.get('apm_oss.transactionIndices'),
+ index: indices['apm_oss.transactionIndices'],
body: {
size: 0,
query: { bool: { filter } },
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts
index 42b35402aab9d..90d9a925a1f36 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts
@@ -28,10 +28,10 @@ export async function bucketFetcher(
bucketSize: number,
setup: Setup
) {
- const { start, end, uiFiltersES, client, config } = setup;
+ const { start, end, uiFiltersES, client, indices } = setup;
const params = {
- index: config.get('apm_oss.transactionIndices'),
+ index: indices['apm_oss.transactionIndices'],
body: {
size: 0,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts
index f49cf2b8c8541..a54fa9c10de13 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts
@@ -19,10 +19,10 @@ export async function getDistributionMax(
transactionType: string,
setup: Setup
) {
- const { start, end, uiFiltersES, client, config } = setup;
+ const { start, end, uiFiltersES, client, indices } = setup;
const params = {
- index: config.get('apm_oss.transactionIndices'),
+ index: indices['apm_oss.transactionIndices'],
body: {
size: 0,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/get_transaction/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/get_transaction/index.ts
index cdaddc3af3e95..20152ecf06480 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/get_transaction/index.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/get_transaction/index.ts
@@ -19,10 +19,10 @@ export async function getTransaction(
traceId: string,
setup: Setup
) {
- const { start, end, uiFiltersES, client, config } = setup;
+ const { start, end, uiFiltersES, client, indices } = setup;
const params = {
- index: config.get('apm_oss.transactionIndices'),
+ index: indices['apm_oss.transactionIndices'],
body: {
size: 1,
query: {
diff --git a/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts b/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts
index 80795ce468c88..ade491be32fc7 100644
--- a/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts
@@ -16,7 +16,7 @@ import { ENVIRONMENT_NOT_DEFINED } from '../../../common/environment_filter_valu
import { ESFilter } from '../../../typings/elasticsearch';
export async function getEnvironments(setup: Setup, serviceName?: string) {
- const { start, end, client, config } = setup;
+ const { start, end, client, indices } = setup;
const filter: ESFilter[] = [
{ terms: { [PROCESSOR_EVENT]: ['transaction', 'error', 'metric'] } },
@@ -31,9 +31,9 @@ export async function getEnvironments(setup: Setup, serviceName?: string) {
const params = {
index: [
- config.get('apm_oss.metricsIndices'),
- config.get('apm_oss.errorIndices'),
- config.get('apm_oss.transactionIndices')
+ indices['apm_oss.metricsIndices'],
+ indices['apm_oss.errorIndices'],
+ indices['apm_oss.transactionIndices']
],
body: {
size: 0,
diff --git a/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts b/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts
index 682ebf27207c4..7d22d9488718f 100644
--- a/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts
+++ b/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { indexPatternRoute } from './index_pattern';
+import { indexPatternRoute, kueryBarIndexPatternRoute } from './index_pattern';
import {
errorDistributionRoute,
errorGroupsRoute,
@@ -25,7 +25,12 @@ import {
listAgentConfigurationServicesRoute,
updateAgentConfigurationRoute,
agentConfigurationAgentNameRoute
-} from './settings';
+} from './settings/agent_configuration';
+import {
+ apmIndexSettingsRoute,
+ apmIndicesRoute,
+ saveApmIndicesRoute
+} from './settings/apm_indices';
import { metricsChartsRoute } from './metrics';
import { serviceNodesRoute } from './service_nodes';
import { tracesRoute, tracesByIdRoute } from './traces';
@@ -53,6 +58,7 @@ const createApmApi = () => {
const api = createApi()
// index pattern
.add(indexPatternRoute)
+ .add(kueryBarIndexPatternRoute)
// Errors
.add(errorDistributionRoute)
@@ -75,6 +81,11 @@ const createApmApi = () => {
.add(listAgentConfigurationServicesRoute)
.add(updateAgentConfigurationRoute)
+ // APM indices
+ .add(apmIndexSettingsRoute)
+ .add(apmIndicesRoute)
+ .add(saveApmIndicesRoute)
+
// Metrics
.add(metricsChartsRoute)
.add(serviceNodesRoute)
diff --git a/x-pack/legacy/plugins/apm/server/routes/index_pattern.ts b/x-pack/legacy/plugins/apm/server/routes/index_pattern.ts
index e838fb1a4b526..100df4dc238fe 100644
--- a/x-pack/legacy/plugins/apm/server/routes/index_pattern.ts
+++ b/x-pack/legacy/plugins/apm/server/routes/index_pattern.ts
@@ -3,8 +3,11 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
+import * as t from 'io-ts';
import { getAPMIndexPattern } from '../lib/index_pattern';
import { createRoute } from './create_route';
+import { getKueryBarIndexPattern } from '../lib/index_pattern/getKueryBarIndexPattern';
+import { setupRequest } from '../lib/helpers/setup_request';
export const indexPatternRoute = createRoute(core => ({
path: '/api/apm/index_pattern',
@@ -13,3 +16,23 @@ export const indexPatternRoute = createRoute(core => ({
return await getAPMIndexPattern(server);
}
}));
+
+export const kueryBarIndexPatternRoute = createRoute(core => ({
+ path: '/api/apm/kuery_bar_index_pattern',
+ params: {
+ query: t.partial({
+ processorEvent: t.union([
+ t.literal('transaction'),
+ t.literal('metric'),
+ t.literal('error')
+ ])
+ })
+ },
+ handler: async (request, { query }) => {
+ const { processorEvent } = query;
+
+ const setup = await setupRequest(request);
+
+ return getKueryBarIndexPattern({ request, processorEvent, setup });
+ }
+}));
diff --git a/x-pack/legacy/plugins/apm/server/routes/settings.ts b/x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts
similarity index 80%
rename from x-pack/legacy/plugins/apm/server/routes/settings.ts
rename to x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts
index 65ef5df78f3e1..d25ad949d6dde 100644
--- a/x-pack/legacy/plugins/apm/server/routes/settings.ts
+++ b/x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts
@@ -5,18 +5,18 @@
*/
import * as t from 'io-ts';
-import { setupRequest } from '../lib/helpers/setup_request';
-import { getServiceNames } from '../lib/settings/agent_configuration/get_service_names';
-import { createOrUpdateConfiguration } from '../lib/settings/agent_configuration/create_or_update_configuration';
-import { searchConfigurations } from '../lib/settings/agent_configuration/search';
-import { listConfigurations } from '../lib/settings/agent_configuration/list_configurations';
-import { getEnvironments } from '../lib/settings/agent_configuration/get_environments';
-import { deleteConfiguration } from '../lib/settings/agent_configuration/delete_configuration';
-import { createRoute } from './create_route';
-import { transactionSampleRateRt } from '../../common/runtime_types/transaction_sample_rate_rt';
-import { transactionMaxSpansRt } from '../../common/runtime_types/transaction_max_spans_rt';
-import { getAgentNameByService } from '../lib/settings/agent_configuration/get_agent_name_by_service';
-import { markAppliedByAgent } from '../lib/settings/agent_configuration/mark_applied_by_agent';
+import { setupRequest } from '../../lib/helpers/setup_request';
+import { getServiceNames } from '../../lib/settings/agent_configuration/get_service_names';
+import { createOrUpdateConfiguration } from '../../lib/settings/agent_configuration/create_or_update_configuration';
+import { searchConfigurations } from '../../lib/settings/agent_configuration/search';
+import { listConfigurations } from '../../lib/settings/agent_configuration/list_configurations';
+import { getEnvironments } from '../../lib/settings/agent_configuration/get_environments';
+import { deleteConfiguration } from '../../lib/settings/agent_configuration/delete_configuration';
+import { createRoute } from '../create_route';
+import { transactionSampleRateRt } from '../../../common/runtime_types/transaction_sample_rate_rt';
+import { transactionMaxSpansRt } from '../../../common/runtime_types/transaction_max_spans_rt';
+import { getAgentNameByService } from '../../lib/settings/agent_configuration/get_agent_name_by_service';
+import { markAppliedByAgent } from '../../lib/settings/agent_configuration/mark_applied_by_agent';
// get list of configurations
export const agentConfigurationRoute = createRoute(core => ({
diff --git a/x-pack/legacy/plugins/apm/server/routes/settings/apm_indices.ts b/x-pack/legacy/plugins/apm/server/routes/settings/apm_indices.ts
new file mode 100644
index 0000000000000..3c82a35ec7903
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/server/routes/settings/apm_indices.ts
@@ -0,0 +1,56 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import * as t from 'io-ts';
+import { setupRequest } from '../../lib/helpers/setup_request';
+import { createRoute } from '../create_route';
+import {
+ getApmIndices,
+ getApmIndexSettings
+} from '../../lib/settings/apm_indices/get_apm_indices';
+import { saveApmIndices } from '../../lib/settings/apm_indices/save_apm_indices';
+
+// get list of apm indices and values
+export const apmIndexSettingsRoute = createRoute(core => ({
+ method: 'GET',
+ path: '/api/apm/settings/apm-index-settings',
+ handler: async req => {
+ const { server } = core.http;
+ const setup = await setupRequest(req);
+ return await getApmIndexSettings({ setup, server });
+ }
+}));
+
+// get apm indices configuration object
+export const apmIndicesRoute = createRoute(core => ({
+ method: 'GET',
+ path: '/api/apm/settings/apm-indices',
+ handler: async req => {
+ const { server } = core.http;
+ return await getApmIndices(server);
+ }
+}));
+
+// save ui indices
+export const saveApmIndicesRoute = createRoute(core => ({
+ method: 'POST',
+ path: '/api/apm/settings/apm-indices/save',
+ params: {
+ body: t.partial({
+ 'apm_oss.sourcemapIndices': t.string,
+ 'apm_oss.errorIndices': t.string,
+ 'apm_oss.onboardingIndices': t.string,
+ 'apm_oss.spanIndices': t.string,
+ 'apm_oss.transactionIndices': t.string,
+ 'apm_oss.metricsIndices': t.string,
+ 'apm_oss.apmAgentConfigurationIndex': t.string
+ })
+ },
+ handler: async (req, { body }) => {
+ const { server } = core.http;
+ return await saveApmIndices(server, body);
+ }
+}));
diff --git a/x-pack/legacy/plugins/apm/typings/common.ts b/x-pack/legacy/plugins/apm/typings/common.ts
index cfe6c9c572dc4..2fafceb32209c 100644
--- a/x-pack/legacy/plugins/apm/typings/common.ts
+++ b/x-pack/legacy/plugins/apm/typings/common.ts
@@ -4,10 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export interface StringMap {
- [key: string]: T;
-}
-
// Allow unknown properties in an object
export type AllowUnknownProperties = T extends Array
? Array>
@@ -24,9 +20,3 @@ export type PromiseReturnType = Func extends (
) => Promise
? Value
: Func;
-
-export type IndexAsString = {
- [k: string]: Map[keyof Map];
-} & Map;
-
-export type Omit = Pick>;
diff --git a/x-pack/legacy/plugins/apm/typings/elasticsearch/index.ts b/x-pack/legacy/plugins/apm/typings/elasticsearch/index.ts
index 657968fbd704f..56cd0ff23a3fb 100644
--- a/x-pack/legacy/plugins/apm/typings/elasticsearch/index.ts
+++ b/x-pack/legacy/plugins/apm/typings/elasticsearch/index.ts
@@ -4,10 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Omit } from 'utility-types';
import { SearchParams, SearchResponse } from 'elasticsearch';
import { AggregationResponseMap, AggregationInputMap } from './aggregations';
-import { StringMap } from '../common';
export interface ESSearchBody {
query?: any;
@@ -55,6 +53,11 @@ export type ESSearchResponse<
export interface ESFilter {
[key: string]: {
- [key: string]: string | string[] | number | StringMap | ESFilter[];
+ [key: string]:
+ | string
+ | string[]
+ | number
+ | Record
+ | ESFilter[];
};
}
diff --git a/x-pack/legacy/plugins/apm/typings/es_schemas/raw/ErrorRaw.ts b/x-pack/legacy/plugins/apm/typings/es_schemas/raw/ErrorRaw.ts
index 545bcc86b2f95..2f6e857e82470 100644
--- a/x-pack/legacy/plugins/apm/typings/es_schemas/raw/ErrorRaw.ts
+++ b/x-pack/legacy/plugins/apm/typings/es_schemas/raw/ErrorRaw.ts
@@ -21,7 +21,7 @@ interface Processor {
event: 'error';
}
-interface Exception {
+export interface Exception {
message?: string; // either message or type are given
type?: string;
module?: string;
diff --git a/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx b/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx
index 64e7bf6b7f09e..2ae475475829f 100644
--- a/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx
+++ b/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx
@@ -18,29 +18,23 @@ interface SuggestionItemProps {
suggestion: AutocompleteSuggestion;
}
-export class SuggestionItem extends React.Component {
- public static defaultProps: Partial = {
- isSelected: false,
- };
+export const SuggestionItem: React.SFC = props => {
+ const { isSelected, onClick, onMouseEnter, suggestion } = props;
- public render() {
- const { isSelected, onClick, onMouseEnter, suggestion } = this.props;
+ return (
+
+
+
+
+ {suggestion.text}
+ {suggestion.description}
+
+ );
+};
- return (
-
-
-
-
- {suggestion.text}
- {suggestion.description}
-
- );
- }
-}
+SuggestionItem.defaultProps = {
+ isSelected: false,
+};
const SuggestionItemContainer = styled.div<{
isSelected?: boolean;
diff --git a/x-pack/legacy/plugins/beats_management/public/lib/adapters/elasticsearch/rest.ts b/x-pack/legacy/plugins/beats_management/public/lib/adapters/elasticsearch/rest.ts
index d4a42ba662db4..526728bd77cac 100644
--- a/x-pack/legacy/plugins/beats_management/public/lib/adapters/elasticsearch/rest.ts
+++ b/x-pack/legacy/plugins/beats_management/public/lib/adapters/elasticsearch/rest.ts
@@ -7,16 +7,16 @@
import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
import { isEmpty } from 'lodash';
import { npStart } from 'ui/new_platform';
-import { RestAPIAdapter } from '../rest_api/adapter_types';
import { ElasticsearchAdapter } from './adapter_types';
import { AutocompleteSuggestion } from '../../../../../../../../src/plugins/data/public';
+import { setup as data } from '../../../../../../../../src/legacy/core_plugins/data/public/legacy';
const getAutocompleteProvider = (language: string) =>
npStart.plugins.data.autocomplete.getProvider(language);
export class RestElasticsearchAdapter implements ElasticsearchAdapter {
private cachedIndexPattern: any = null;
- constructor(private readonly api: RestAPIAdapter, private readonly indexPatternName: string) {}
+ constructor(private readonly indexPatternName: string) {}
public isKueryValid(kuery: string): boolean {
try {
@@ -65,9 +65,9 @@ export class RestElasticsearchAdapter implements ElasticsearchAdapter {
if (this.cachedIndexPattern) {
return this.cachedIndexPattern;
}
- const res = await this.api.get(
- `/api/index_patterns/_fields_for_wildcard?pattern=${this.indexPatternName}`
- );
+ const res = await data.indexPatterns.indexPatterns.getFieldsForWildcard({
+ pattern: this.indexPatternName,
+ });
if (isEmpty(res.fields)) {
return;
}
diff --git a/x-pack/legacy/plugins/beats_management/public/lib/compose/kibana.ts b/x-pack/legacy/plugins/beats_management/public/lib/compose/kibana.ts
index 3d8ca51e006bf..2ebda89ba13fd 100644
--- a/x-pack/legacy/plugins/beats_management/public/lib/compose/kibana.ts
+++ b/x-pack/legacy/plugins/beats_management/public/lib/compose/kibana.ts
@@ -35,7 +35,7 @@ const onKibanaReady = chrome.dangerouslyGetActiveInjector;
export function compose(): FrontendLibs {
const api = new AxiosRestAPIAdapter(chrome.getXsrfToken(), chrome.getBasePath());
- const esAdapter = new RestElasticsearchAdapter(api, INDEX_NAMES.BEATS);
+ const esAdapter = new RestElasticsearchAdapter(INDEX_NAMES.BEATS);
const elasticsearchLib = new ElasticsearchLib(esAdapter);
const configBlocks = new ConfigBlocksLib(
new RestConfigBlocksAdapter(api),
diff --git a/x-pack/legacy/plugins/beats_management/public/pages/walkthrough/initial/index.tsx b/x-pack/legacy/plugins/beats_management/public/pages/walkthrough/initial/index.tsx
index 6ac6643755765..26f2aa80de763 100644
--- a/x-pack/legacy/plugins/beats_management/public/pages/walkthrough/initial/index.tsx
+++ b/x-pack/legacy/plugins/beats_management/public/pages/walkthrough/initial/index.tsx
@@ -6,93 +6,90 @@
import { EuiBetaBadge, EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
-import React, { Component } from 'react';
+import React from 'react';
import { NoDataLayout } from '../../../components/layouts/no_data';
import { WalkthroughLayout } from '../../../components/layouts/walkthrough';
import { ChildRoutes } from '../../../components/navigation/child_routes';
import { ConnectedLink } from '../../../components/navigation/connected_link';
import { AppPageProps } from '../../../frontend_types';
-class InitialWalkthroughPageComponent extends Component<
- AppPageProps & {
- intl: InjectedIntl;
- }
-> {
- public render() {
- const { intl } = this.props;
+type Props = AppPageProps & {
+ intl: InjectedIntl;
+};
- if (this.props.location.pathname === '/walkthrough/initial') {
- return (
-
- {'Beats central management '}
-
-
-
-
- }
- actionSection={
-
-
- {' '}
-
-
- }
- >
-
-
-
-
- );
- }
+const InitialWalkthroughPageComponent: React.SFC = props => {
+ if (props.location.pathname === '/walkthrough/initial') {
return (
- {
- // FIXME implament goto
- }}
- activePath={this.props.location.pathname}
+
+ {'Beats central management '}
+
+
+
+
+ }
+ actionSection={
+
+
+ {' '}
+
+
+ }
>
-
-
+
+
+
+
);
}
-}
+ return (
+ {
+ // FIXME implament goto
+ }}
+ activePath={props.location.pathname}
+ >
+
+
+ );
+};
+
export const InitialWalkthroughPage = injectI18n(InitialWalkthroughPageComponent);
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts
index cad46e81ffc0c..063e69d1d2141 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ExpressionType } from 'src/plugins/expressions/common';
+import { ExpressionType } from 'src/plugins/expressions/public';
import { EmbeddableInput } from 'src/legacy/core_plugins/embeddable_api/public/np_ready/public';
import { EmbeddableTypes } from './embeddable_types';
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts
index 6efe6bc96dbba..546e8967a7439 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts
@@ -6,7 +6,7 @@
// @ts-ignore
import { MAP_SAVED_OBJECT_TYPE } from '../../../maps/common/constants';
-import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/visualize/embeddable';
+import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/visualize/embeddable/constants';
import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/discover/embeddable/constants';
export const EmbeddableTypes = {
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts
index 958d9c6a3a6f0..abaa16c4e3271 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts
@@ -3,7 +3,6 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter as ESFilterType } from '@kbn/es-query';
import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/public';
import { TimeRange } from 'src/plugins/data/public';
import { EmbeddableInput } from 'src/legacy/core_plugins/embeddable_api/public/np_ready/public';
@@ -15,6 +14,7 @@ import {
EmbeddableExpression,
} from '../../expression_types';
import { getFunctionHelp } from '../../../i18n';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
interface Arguments {
id: string;
@@ -29,7 +29,7 @@ interface SavedMapInput extends EmbeddableInput {
isPaused: boolean;
interval: number;
};
- filters: ESFilterType[];
+ filters: esFilters.Filter[];
}
type Return = EmbeddableExpression;
diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/flyout/snippets_step.tsx b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/flyout/snippets_step.tsx
index f933d9009d367..a65ec1ddba081 100644
--- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/flyout/snippets_step.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/flyout/snippets_step.tsx
@@ -58,7 +58,7 @@ export const SnippetsStep: FC<{ onCopy: OnCopyFn }> = ({ onCopy }) => (
- kbn-canvas-shareable="canvas" ({strings.getRequiredLabel()})
+ kbn-canvas-shareable="canvas" ({strings.getRequiredLabel()})
{strings.getShareableParameterDescription()}
diff --git a/x-pack/legacy/plugins/canvas/public/lib/clipboard.js b/x-pack/legacy/plugins/canvas/public/lib/clipboard.js
index 2cebf2a5bad96..f9d68769c9c3a 100644
--- a/x-pack/legacy/plugins/canvas/public/lib/clipboard.js
+++ b/x-pack/legacy/plugins/canvas/public/lib/clipboard.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Storage } from 'ui/storage';
+import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { LOCALSTORAGE_CLIPBOARD } from '../../common/lib/constants';
import { getWindow } from './get_window';
diff --git a/x-pack/legacy/plugins/canvas/scripts/shareable_runtime.js b/x-pack/legacy/plugins/canvas/scripts/shareable_runtime.js
index 760298c8a2dff..f867e4dc77a11 100644
--- a/x-pack/legacy/plugins/canvas/scripts/shareable_runtime.js
+++ b/x-pack/legacy/plugins/canvas/scripts/shareable_runtime.js
@@ -91,10 +91,20 @@ run(
clean();
log.info('Building Canvas Shareable Workpad Runtime...');
- execa.sync('yarn', ['webpack', '--config', webpackConfig, '--hide-modules', '--progress'], {
- ...options,
- env,
- });
+ execa.sync(
+ 'yarn',
+ [
+ 'webpack',
+ '--config',
+ webpackConfig,
+ '--hide-modules',
+ ...(process.stdout.isTTY ? ['--progress'] : []),
+ ],
+ {
+ ...options,
+ env,
+ }
+ );
log.success('...runtime built!');
},
{
diff --git a/x-pack/legacy/plugins/canvas/server/lib/build_embeddable_filters.ts b/x-pack/legacy/plugins/canvas/server/lib/build_embeddable_filters.ts
index 8de813255a230..ca34246531bff 100644
--- a/x-pack/legacy/plugins/canvas/server/lib/build_embeddable_filters.ts
+++ b/x-pack/legacy/plugins/canvas/server/lib/build_embeddable_filters.ts
@@ -4,14 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { buildQueryFilter, Filter as ESFilterType } from '@kbn/es-query';
import { TimeRange } from 'src/plugins/data/public';
import { Filter } from '../../types';
// @ts-ignore Untyped Local
import { buildBoolArray } from './build_bool_array';
+import { esFilters } from '../../../../../../src/plugins/data/common';
export interface EmbeddableFilterInput {
- filters: ESFilterType[];
+ filters: esFilters.Filter[];
timeRange?: TimeRange;
}
@@ -30,8 +30,10 @@ function getTimeRangeFromFilters(filters: Filter[]): TimeRange | undefined {
: undefined;
}
-function getQueryFilters(filters: Filter[]): ESFilterType[] {
- return buildBoolArray(filters.filter(filter => filter.type !== 'time')).map(buildQueryFilter);
+function getQueryFilters(filters: Filter[]): esFilters.Filter[] {
+ return buildBoolArray(filters.filter(filter => filter.type !== 'time')).map(
+ esFilters.buildQueryFilter
+ );
}
export function buildEmbeddableFilters(filters: Filter[]): EmbeddableFilterInput {
diff --git a/x-pack/legacy/plugins/canvas/server/routes/shareables.ts b/x-pack/legacy/plugins/canvas/server/routes/shareables.ts
index 5159cde48b3ef..e8186ceceb47f 100644
--- a/x-pack/legacy/plugins/canvas/server/routes/shareables.ts
+++ b/x-pack/legacy/plugins/canvas/server/routes/shareables.ts
@@ -16,7 +16,6 @@ import {
SHAREABLE_RUNTIME_FILE,
SHAREABLE_RUNTIME_NAME,
SHAREABLE_RUNTIME_SRC,
- SHAREABLE_RUNTIME_OUTPUT,
} from '../../shareable_runtime/constants';
import { CoreSetup } from '../shim';
@@ -26,14 +25,13 @@ export function shareableWorkpads(route: CoreSetup['http']['route']) {
route({
method: 'GET',
path: API_ROUTE_SHAREABLE_RUNTIME,
- options: {
- files: {
- relativeTo: SHAREABLE_RUNTIME_OUTPUT,
- },
- },
+
handler: {
file: {
path: SHAREABLE_RUNTIME_FILE,
+ // The option setting is not for typical use. We're using it here to avoid
+ // problems in Cloud environments. See elastic/kibana#47405.
+ confine: false,
},
},
});
@@ -42,14 +40,12 @@ export function shareableWorkpads(route: CoreSetup['http']['route']) {
route({
method: 'GET',
path: API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD,
- options: {
- files: {
- relativeTo: SHAREABLE_RUNTIME_OUTPUT,
- },
- },
+
handler(_request, handler) {
+ // The option setting is not for typical use. We're using it here to avoid
+ // problems in Cloud environments. See elastic/kibana#47405.
// @ts-ignore No type for inert Hapi handler
- const file = handler.file(SHAREABLE_RUNTIME_FILE);
+ const file = handler.file(SHAREABLE_RUNTIME_FILE, { confine: false });
file.type('application/octet-stream');
return file;
},
diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx b/x-pack/legacy/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx
index ea944bd30e9b8..a55c87c2d74a2 100644
--- a/x-pack/legacy/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx
+++ b/x-pack/legacy/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx
@@ -32,7 +32,7 @@ describe('Canvas Shareable Workpad API', () => {
test('Placed successfully with default properties', async () => {
const container = document.createElement('div');
document.body.appendChild(container);
- const wrapper = mount(
, {
+ const wrapper = mount(
, {
attachTo: container,
});
@@ -46,11 +46,7 @@ describe('Canvas Shareable Workpad API', () => {
const container = document.createElement('div');
document.body.appendChild(container);
const wrapper = mount(
-
,
+
,
{
attachTo: container,
}
@@ -69,11 +65,7 @@ describe('Canvas Shareable Workpad API', () => {
const container = document.createElement('div');
document.body.appendChild(container);
const wrapper = mount(
-
,
+
,
{
attachTo: container,
}
@@ -97,7 +89,7 @@ describe('Canvas Shareable Workpad API', () => {
kbn-canvas-width="350"
kbn-canvas-height="350"
kbn-canvas-url="workpad.json"
- > ,
+ />,
{
attachTo: container,
}
@@ -116,7 +108,7 @@ describe('Canvas Shareable Workpad API', () => {
const container = document.createElement('div');
document.body.appendChild(container);
const wrapper = mount(
-
,
+
,
{
attachTo: container,
}
diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/__snapshots__/settings.test.tsx.snap b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/__snapshots__/settings.test.tsx.snap
index baa0b509ccb73..072cf01255a0d 100644
--- a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/__snapshots__/settings.test.tsx.snap
+++ b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/__snapshots__/settings.test.tsx.snap
@@ -17,8 +17,11 @@ exports[` can navigate Autoplay Settings 1`] = `
data-focus-lock-disabled="disabled"
>
can navigate Autoplay Settings 2`] = `
data-focus-lock-disabled="disabled"
>
can navigate Toolbar Settings, closes when activated 1`] =
data-focus-lock-disabled="disabled"
>
can navigate Toolbar Settings, closes when activated 1`] =
`;
-exports[`
can navigate Toolbar Settings, closes when activated 2`] = `"
"`;
+exports[`
can navigate Toolbar Settings, closes when activated 2`] = `"
"`;
-exports[`
can navigate Toolbar Settings, closes when activated 3`] = `"
"`;
+exports[`
can navigate Toolbar Settings, closes when activated 3`] = `"
"`;
diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx
index 78fefead027e5..5ebb30d79e046 100644
--- a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx
+++ b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx
@@ -18,6 +18,11 @@ import { Settings } from '../settings';
jest.mock('../../../../supported_renderers');
jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `generated-id`);
+jest.mock('@elastic/eui/lib/services/accessibility', () => {
+ return {
+ htmlIdGenerator: () => () => `generated-id`,
+ };
+});
jest.mock('@elastic/eui/lib/components/portal/portal', () => {
// eslint-disable-next-line no-shadow
const React = require.requireActual('react');
diff --git a/x-pack/legacy/plugins/canvas/types/elements.ts b/x-pack/legacy/plugins/canvas/types/elements.ts
index b3af9e5eee70d..c70f2af1002aa 100644
--- a/x-pack/legacy/plugins/canvas/types/elements.ts
+++ b/x-pack/legacy/plugins/canvas/types/elements.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ExpressionAST } from 'src/plugins/expressions/common/expressions';
+import { ExpressionAST } from 'src/plugins/expressions/public';
import { CanvasElement } from '.';
export interface ElementSpec {
diff --git a/x-pack/legacy/plugins/canvas/types/index.ts b/x-pack/legacy/plugins/canvas/types/index.ts
index 8c857d8d5f3a9..54b73b2d2f362 100644
--- a/x-pack/legacy/plugins/canvas/types/index.ts
+++ b/x-pack/legacy/plugins/canvas/types/index.ts
@@ -10,7 +10,7 @@ export {
BackgroundRepeat,
BackgroundSize,
} from '../../../../../src/legacy/core_plugins/interpreter/public/types/style';
-export * from '../../../../../src/plugins/expressions/common';
+export * from '../../../../../src/plugins/expressions/public';
export * from './assets';
export * from './canvas';
export * from './elements';
diff --git a/x-pack/legacy/plugins/canvas/types/state.ts b/x-pack/legacy/plugins/canvas/types/state.ts
index 2deab0a6fc8a4..494965d060788 100644
--- a/x-pack/legacy/plugins/canvas/types/state.ts
+++ b/x-pack/legacy/plugins/canvas/types/state.ts
@@ -13,7 +13,7 @@ import {
Render,
Style,
Range,
-} from 'src/plugins/expressions/common/expressions/expression_types';
+} from 'src/plugins/expressions/public';
import { CanvasFunction } from './functions';
import { AssetType } from './assets';
import { CanvasWorkpad } from './canvas';
diff --git a/x-pack/legacy/plugins/encrypted_saved_objects/__snapshots__/index.test.ts.snap b/x-pack/legacy/plugins/encrypted_saved_objects/__snapshots__/index.test.ts.snap
deleted file mode 100644
index e3c069069bf14..0000000000000
--- a/x-pack/legacy/plugins/encrypted_saved_objects/__snapshots__/index.test.ts.snap
+++ /dev/null
@@ -1,14 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`config schema with context {"dist":false} produces correct config 1`] = `
-Object {
- "enabled": true,
- "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-}
-`;
-
-exports[`config schema with context {"dist":true} produces correct config 1`] = `
-Object {
- "enabled": true,
-}
-`;
diff --git a/x-pack/legacy/plugins/encrypted_saved_objects/index.test.ts b/x-pack/legacy/plugins/encrypted_saved_objects/index.test.ts
deleted file mode 100644
index 26c0166186c4c..0000000000000
--- a/x-pack/legacy/plugins/encrypted_saved_objects/index.test.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { encryptedSavedObjects } from './index';
-import { getConfigSchema } from '../../../test_utils';
-
-const describeWithContext = describe.each([[{ dist: false }], [{ dist: true }]]);
-
-describeWithContext('config schema with context %j', context => {
- it('produces correct config', async () => {
- const schema = await getConfigSchema(encryptedSavedObjects);
- await expect(schema.validate({}, { context })).resolves.toMatchSnapshot();
- });
-});
diff --git a/x-pack/legacy/plugins/encrypted_saved_objects/index.ts b/x-pack/legacy/plugins/encrypted_saved_objects/index.ts
index a5f28631f3d52..3969959d03cff 100644
--- a/x-pack/legacy/plugins/encrypted_saved_objects/index.ts
+++ b/x-pack/legacy/plugins/encrypted_saved_objects/index.ts
@@ -5,62 +5,41 @@
*/
import { Root } from 'joi';
-import { Legacy, Server } from 'kibana';
-
+import { Legacy } from 'kibana';
+import { PluginSetupContract } from '../../../plugins/encrypted_saved_objects/server';
// @ts-ignore
import { AuditLogger } from '../../server/lib/audit_logger';
-import { CONFIG_PREFIX, PLUGIN_ID, Plugin } from './server/plugin';
-
-/**
- * Public interface of the security plugin for the legacy plugin system.
- */
-export type EncryptedSavedObjectsPlugin = ReturnType
;
-
-export const encryptedSavedObjects = (kibana: any) =>
+export const encryptedSavedObjects = (kibana: {
+ Plugin: new (options: Legacy.PluginSpecOptions & { configPrefix?: string }) => unknown;
+}) =>
new kibana.Plugin({
- id: PLUGIN_ID,
- configPrefix: CONFIG_PREFIX,
- require: ['kibana', 'elasticsearch', 'xpack_main'],
-
- config(Joi: Root) {
- return Joi.object({
- enabled: Joi.boolean().default(true),
- encryptionKey: Joi.when(Joi.ref('$dist'), {
- is: true,
- then: Joi.string().min(32),
- otherwise: Joi.string()
- .min(32)
- .default('a'.repeat(32)),
- }),
- }).default();
- },
-
- async init(server: Legacy.Server) {
- const loggerFacade = {
- fatal: (errorOrMessage: string | Error) => server.log(['fatal', PLUGIN_ID], errorOrMessage),
- trace: (message: string) => server.log(['debug', PLUGIN_ID], message),
- error: (message: string) => server.log(['error', PLUGIN_ID], message),
- warn: (message: string) => server.log(['warning', PLUGIN_ID], message),
- debug: (message: string) => server.log(['debug', PLUGIN_ID], message),
- info: (message: string) => server.log(['info', PLUGIN_ID], message),
- } as Server.Logger;
-
- const config = server.config();
- const encryptedSavedObjectsSetup = new Plugin(loggerFacade).setup(
- {
- config: {
- encryptionKey: config.get(`${CONFIG_PREFIX}.encryptionKey`),
- },
- savedObjects: server.savedObjects,
- elasticsearch: server.plugins.elasticsearch,
- },
- { audit: new AuditLogger(server, PLUGIN_ID, config, server.plugins.xpack_main.info) }
- );
-
- // Re-expose plugin setup contract through legacy mechanism.
- for (const [setupMethodName, setupMethod] of Object.entries(encryptedSavedObjectsSetup)) {
- server.expose(setupMethodName, setupMethod);
+ id: 'encryptedSavedObjects',
+ configPrefix: 'xpack.encryptedSavedObjects',
+ require: ['xpack_main'],
+
+ // Some legacy plugins still use `enabled` config key, so we keep it here, but the rest of the
+ // keys is handled by the New Platform plugin.
+ config: (Joi: Root) =>
+ Joi.object({ enabled: Joi.boolean().default(true) })
+ .unknown(true)
+ .default(),
+
+ init(server: Legacy.Server) {
+ const encryptedSavedObjectsPlugin = (server.newPlatform.setup.plugins
+ .encryptedSavedObjects as unknown) as PluginSetupContract;
+ if (!encryptedSavedObjectsPlugin) {
+ throw new Error('New Platform XPack EncryptedSavedObjects plugin is not available.');
}
+
+ encryptedSavedObjectsPlugin.__legacyCompat.registerLegacyAPI({
+ savedObjects: server.savedObjects,
+ auditLogger: new AuditLogger(
+ server,
+ 'encryptedSavedObjects',
+ server.config(),
+ server.plugins.xpack_main.info
+ ),
+ });
},
});
diff --git a/x-pack/legacy/plugins/encrypted_saved_objects/server/lib/encrypted_saved_objects_service.mock.ts b/x-pack/legacy/plugins/encrypted_saved_objects/server/lib/encrypted_saved_objects_service.mock.ts
deleted file mode 100644
index 235d64cc348c9..0000000000000
--- a/x-pack/legacy/plugins/encrypted_saved_objects/server/lib/encrypted_saved_objects_service.mock.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import {
- EncryptedSavedObjectsService,
- EncryptedSavedObjectTypeRegistration,
- SavedObjectDescriptor,
-} from './encrypted_saved_objects_service';
-
-export function createEncryptedSavedObjectsServiceMock(
- registrations: EncryptedSavedObjectTypeRegistration[] = []
-) {
- const mock: jest.Mocked = new (jest.requireMock(
- './encrypted_saved_objects_service'
- )).EncryptedSavedObjectsService();
-
- function processAttributes>(
- descriptor: Pick,
- attrs: T,
- action: (attrs: T, attrName: string) => void
- ) {
- const registration = registrations.find(r => r.type === descriptor.type);
- if (!registration) {
- return attrs;
- }
-
- const clonedAttrs = { ...attrs };
- for (const attrName of registration.attributesToEncrypt) {
- if (attrName in clonedAttrs) {
- action(clonedAttrs, attrName);
- }
- }
- return clonedAttrs;
- }
-
- mock.isRegistered.mockImplementation(type => registrations.findIndex(r => r.type === type) >= 0);
- mock.encryptAttributes.mockImplementation(async (descriptor, attrs) =>
- processAttributes(
- descriptor,
- attrs,
- (clonedAttrs, attrName) => (clonedAttrs[attrName] = `*${clonedAttrs[attrName]}*`)
- )
- );
- mock.decryptAttributes.mockImplementation(async (descriptor, attrs) =>
- processAttributes(
- descriptor,
- attrs,
- (clonedAttrs, attrName) =>
- (clonedAttrs[attrName] = (clonedAttrs[attrName] as string).slice(1, -1))
- )
- );
- mock.stripEncryptedAttributes.mockImplementation((type, attrs) =>
- processAttributes({ type }, attrs, (clonedAttrs, attrName) => delete clonedAttrs[attrName])
- );
-
- return mock;
-}
diff --git a/x-pack/legacy/plugins/encrypted_saved_objects/server/plugin.mock.ts b/x-pack/legacy/plugins/encrypted_saved_objects/server/plugin.mock.ts
deleted file mode 100644
index 7c6e37c7e5d4c..0000000000000
--- a/x-pack/legacy/plugins/encrypted_saved_objects/server/plugin.mock.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { Plugin } from './plugin';
-type EncryptedSavedObjectsPlugin = ReturnType;
-
-const createEncryptedSavedObjectsMock = () => {
- const mocked: jest.Mocked = {
- isEncryptionError: jest.fn(),
- registerType: jest.fn(),
- getDecryptedAsInternalUser: jest.fn(),
- };
- return mocked;
-};
-
-export const encryptedSavedObjectsMock = {
- create: createEncryptedSavedObjectsMock,
-};
diff --git a/x-pack/legacy/plugins/encrypted_saved_objects/server/plugin.ts b/x-pack/legacy/plugins/encrypted_saved_objects/server/plugin.ts
deleted file mode 100644
index ad38ca0f7a881..0000000000000
--- a/x-pack/legacy/plugins/encrypted_saved_objects/server/plugin.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import crypto from 'crypto';
-import { Legacy, Server } from 'kibana';
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { SavedObjectsRepository } from 'src/core/server/saved_objects/service';
-import { SavedObjectsBaseOptions, SavedObject, SavedObjectAttributes } from 'src/core/server';
-import {
- EncryptedSavedObjectsService,
- EncryptedSavedObjectTypeRegistration,
- EncryptionError,
- EncryptedSavedObjectsAuditLogger,
- EncryptedSavedObjectsClientWrapper,
-} from './lib';
-
-export const PLUGIN_ID = 'encrypted_saved_objects';
-export const CONFIG_PREFIX = `xpack.${PLUGIN_ID}`;
-
-interface CoreSetup {
- config: { encryptionKey?: string };
- elasticsearch: Legacy.Plugins.elasticsearch.Plugin;
- savedObjects: Legacy.SavedObjectsService;
-}
-
-interface PluginsSetup {
- audit: unknown;
-}
-
-export class Plugin {
- constructor(private readonly log: Server.Logger) {}
-
- public setup(core: CoreSetup, plugins: PluginsSetup) {
- let encryptionKey = core.config.encryptionKey;
- if (encryptionKey == null) {
- this.log.warn(
- `Generating a random key for ${CONFIG_PREFIX}.encryptionKey. To be able ` +
- 'to decrypt encrypted saved objects attributes after restart, please set ' +
- `${CONFIG_PREFIX}.encryptionKey in kibana.yml`
- );
-
- encryptionKey = crypto.randomBytes(16).toString('hex');
- }
-
- const service = Object.freeze(
- new EncryptedSavedObjectsService(
- encryptionKey,
- core.savedObjects.types,
- this.log,
- new EncryptedSavedObjectsAuditLogger(plugins.audit)
- )
- );
-
- // Register custom saved object client that will encrypt, decrypt and strip saved object
- // attributes where appropriate for any saved object repository request. We choose max possible
- // priority for this wrapper to allow all other wrappers to set proper `namespace` for the Saved
- // Object (e.g. wrapper registered by the Spaces plugin) before we encrypt attributes since
- // `namespace` is included into AAD.
- core.savedObjects.addScopedSavedObjectsClientWrapperFactory(
- Number.MAX_SAFE_INTEGER,
- 'encrypted_saved_objects',
- ({ client: baseClient }) => new EncryptedSavedObjectsClientWrapper({ baseClient, service })
- );
-
- const internalRepository: SavedObjectsRepository = core.savedObjects.getSavedObjectsRepository(
- core.elasticsearch.getCluster('admin').callWithInternalUser
- );
-
- return {
- isEncryptionError: (error: Error) => error instanceof EncryptionError,
- registerType: (typeRegistration: EncryptedSavedObjectTypeRegistration) =>
- service.registerType(typeRegistration),
- getDecryptedAsInternalUser: async (
- type: string,
- id: string,
- options?: SavedObjectsBaseOptions
- ): Promise> => {
- const savedObject = await internalRepository.get(type, id, options);
- return {
- ...savedObject,
- attributes: await service.decryptAttributes(
- { type, id, namespace: options && options.namespace },
- savedObject.attributes
- ),
- };
- },
- };
- }
-}
diff --git a/x-pack/legacy/plugins/file_upload/public/kibana_services.js b/x-pack/legacy/plugins/file_upload/public/kibana_services.js
index 8dd2923752b99..10a6ae7179bc2 100644
--- a/x-pack/legacy/plugins/file_upload/public/kibana_services.js
+++ b/x-pack/legacy/plugins/file_upload/public/kibana_services.js
@@ -4,10 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { uiModules } from 'ui/modules';
+import { start as data } from '../../../../../src/legacy/core_plugins/data/public/legacy';
-export let indexPatternService;
-
-uiModules.get('app/file_upload').run(($injector) => {
- indexPatternService = $injector.get('indexPatterns');
-});
+export const indexPatternService = data.indexPatterns.indexPatterns;
diff --git a/x-pack/legacy/plugins/file_upload/public/util/indexing_service.test.js b/x-pack/legacy/plugins/file_upload/public/util/indexing_service.test.js
index 47582cb47a2aa..d6ca3d3180d6e 100644
--- a/x-pack/legacy/plugins/file_upload/public/util/indexing_service.test.js
+++ b/x-pack/legacy/plugins/file_upload/public/util/indexing_service.test.js
@@ -4,6 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
+// Not all index pattern dependencies are avab. in jest context,
+// prevent unrelated import errors by mocking kibana services
+jest.mock('../kibana_services', () => {});
import { checkIndexPatternValid } from './indexing_service';
describe('indexing_service', () => {
diff --git a/x-pack/legacy/plugins/file_upload/public/util/size_limited_chunking.js b/x-pack/legacy/plugins/file_upload/public/util/size_limited_chunking.js
index 4c49772b9ddce..387060279ca0d 100644
--- a/x-pack/legacy/plugins/file_upload/public/util/size_limited_chunking.js
+++ b/x-pack/legacy/plugins/file_upload/public/util/size_limited_chunking.js
@@ -5,16 +5,23 @@
*/
import { MAX_BYTES } from '../../common/constants/file_import';
+// MAX_BYTES is a good guideline for splitting up posts, but this logic
+// occasionally sizes chunks so closely to the limit, that the remaining content
+// of a post (besides features) tips it over the max. Adding a 2MB buffer
+// to ensure this doesn't happen
+const CHUNK_BUFFER = 2097152;
+
// Add data elements to chunk until limit is met
-export function sizeLimitedChunking(dataArr, maxChunkSize = MAX_BYTES) {
+export function sizeLimitedChunking(dataArr, maxByteSize = MAX_BYTES - CHUNK_BUFFER) {
let chunkSize = 0;
+
return dataArr.reduce((accu, el) => {
const featureByteSize = (
new Blob([JSON.stringify(el)], { type: 'application/json' })
).size;
- if (featureByteSize > maxChunkSize) {
- throw `Some features exceed maximum chunk size of ${maxChunkSize}`;
- } else if (chunkSize + featureByteSize < maxChunkSize) {
+ if (featureByteSize > maxByteSize) {
+ throw `Some features exceed maximum chunk size of ${maxByteSize}`;
+ } else if (chunkSize + featureByteSize < maxByteSize) {
const lastChunkRef = accu.length - 1;
chunkSize += featureByteSize;
accu[lastChunkRef].push(el);
diff --git a/x-pack/legacy/plugins/graph/public/angular/templates/index.html b/x-pack/legacy/plugins/graph/public/angular/templates/index.html
index 686f0f590a19c..b3f5bce7ea6ec 100644
--- a/x-pack/legacy/plugins/graph/public/angular/templates/index.html
+++ b/x-pack/legacy/plugins/graph/public/angular/templates/index.html
@@ -61,7 +61,7 @@
initial-query="initialQuery"
plugin-data-start="pluginDataStart"
core-start="coreStart"
- store="store"
+ storage="storage"
no-index-patterns="noIndexPatterns"
>
diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js
index 41e5819bcbf37..fd7a292762d59 100644
--- a/x-pack/legacy/plugins/graph/public/app.js
+++ b/x-pack/legacy/plugins/graph/public/app.js
@@ -11,9 +11,7 @@ import React from 'react';
import { Provider } from 'react-redux';
import { isColorDark, hexToRgb } from '@elastic/eui';
-import { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal';
-import { formatAngularHttpError } from 'ui/notify/lib';
import { addAppRedirectMessageToUrl } from 'ui/notify';
import appTemplate from './angular/templates/index.html';
@@ -39,6 +37,7 @@ import {
datasourceSelector,
hasFieldsSelector
} from './state_management';
+import { formatHttpError } from './helpers/format_http_error';
export function initGraphApp(angularModule, deps) {
const {
@@ -56,7 +55,6 @@ export function initGraphApp(angularModule, deps) {
savedObjectRegistry,
capabilities,
coreStart,
- $http,
Storage,
canEditDrillDownUrls,
graphSavePolicy,
@@ -100,7 +98,7 @@ export function initGraphApp(angularModule, deps) {
app.directive('graphApp', function (reactDirective) {
return reactDirective(GraphApp, [
- ['store', { watchDepth: 'reference' }],
+ ['storage', { watchDepth: 'reference' }],
['isInitialized', { watchDepth: 'reference' }],
['currentIndexPattern', { watchDepth: 'reference' }],
['indexPatternProvider', { watchDepth: 'reference' }],
@@ -208,31 +206,35 @@ export function initGraphApp(angularModule, deps) {
async function handleHttpError(error) {
checkLicense(kbnBaseUrl);
- toastNotifications.addDanger(formatAngularHttpError(error));
+ toastNotifications.addDanger(formatHttpError(error));
}
// Replacement function for graphClientWorkspace's comms so
// that it works with Kibana.
function callNodeProxy(indexName, query, responseHandler) {
const request = {
- index: indexName,
- query: query
+ body: JSON.stringify({
+ index: indexName,
+ query: query
+ })
};
$scope.loading = true;
- return $http.post('../api/graph/graphExplore', request)
- .then(function (resp) {
- if (resp.data.resp.timed_out) {
+ return coreStart.http.post('../api/graph/graphExplore', request)
+ .then(function (data) {
+ const response = data.resp;
+ if (response.timed_out) {
toastNotifications.addWarning(
i18n.translate('xpack.graph.exploreGraph.timedOutWarningText', {
defaultMessage: 'Exploration timed out',
})
);
}
- responseHandler(resp.data.resp);
+ responseHandler(response);
})
.catch(handleHttpError)
.finally(() => {
$scope.loading = false;
+ $scope.$digest();
});
}
@@ -240,17 +242,21 @@ export function initGraphApp(angularModule, deps) {
//Helper function for the graphClientWorkspace to perform a query
const callSearchNodeProxy = function (indexName, query, responseHandler) {
const request = {
- index: indexName,
- body: query
+ body: JSON.stringify({
+ index: indexName,
+ body: query
+ })
};
$scope.loading = true;
- $http.post('../api/graph/searchProxy', request)
- .then(function (resp) {
- responseHandler(resp.data.resp);
+ coreStart.http.post('../api/graph/searchProxy', request)
+ .then(function (data) {
+ const response = data.resp;
+ responseHandler(response);
})
.catch(handleHttpError)
.finally(() => {
$scope.loading = false;
+ $scope.$digest();
});
};
@@ -310,7 +316,7 @@ export function initGraphApp(angularModule, deps) {
// register things on scope passed down to react components
$scope.pluginDataStart = npData;
- $scope.store = new Storage(window.localStorage);
+ $scope.storage = new Storage(window.localStorage);
$scope.coreStart = coreStart;
$scope.loading = false;
$scope.reduxStore = store;
diff --git a/x-pack/legacy/plugins/graph/public/components/app.tsx b/x-pack/legacy/plugins/graph/public/components/app.tsx
index aa2221441793f..5ff7fc2e5da93 100644
--- a/x-pack/legacy/plugins/graph/public/components/app.tsx
+++ b/x-pack/legacy/plugins/graph/public/components/app.tsx
@@ -10,8 +10,8 @@ import { DataPublicPluginStart } from 'src/plugins/data/public';
import { Provider } from 'react-redux';
import React, { useState } from 'react';
import { I18nProvider } from '@kbn/i18n/react';
-import { Storage } from 'ui/storage';
import { CoreStart } from 'kibana/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { FieldManager } from './field_manager';
import { SearchBarProps, SearchBar } from './search_bar';
import { GraphStore } from '../state_management';
@@ -23,7 +23,7 @@ export interface GraphAppProps extends SearchBarProps {
coreStart: CoreStart;
// This is not named dataStart because of Angular treating data- prefix differently
pluginDataStart: DataPublicPluginStart;
- store: Storage;
+ storage: IStorageWrapper;
reduxStore: GraphStore;
isInitialized: boolean;
noIndexPatterns: boolean;
@@ -34,7 +34,7 @@ export function GraphApp(props: GraphAppProps) {
const {
coreStart,
pluginDataStart,
- store,
+ storage,
reduxStore,
noIndexPatterns,
...searchBarProps
@@ -45,7 +45,7 @@ export function GraphApp(props: GraphAppProps) {
{},
},
};
diff --git a/x-pack/legacy/plugins/graph/public/components/settings/blacklist_form.tsx b/x-pack/legacy/plugins/graph/public/components/settings/blacklist_form.tsx
index b321ea3a0d8ed..f7ae04ef9dbcc 100644
--- a/x-pack/legacy/plugins/graph/public/components/settings/blacklist_form.tsx
+++ b/x-pack/legacy/plugins/graph/public/components/settings/blacklist_form.tsx
@@ -39,7 +39,7 @@ export function BlacklistForm({
}}
+ values={{ stopSign: }}
/>
}
/>
diff --git a/x-pack/legacy/plugins/graph/public/helpers/format_http_error.ts b/x-pack/legacy/plugins/graph/public/helpers/format_http_error.ts
new file mode 100644
index 0000000000000..5e0ac1e1ce56f
--- /dev/null
+++ b/x-pack/legacy/plugins/graph/public/helpers/format_http_error.ts
@@ -0,0 +1,27 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { IHttpFetchError } from 'kibana/public';
+
+export function formatHttpError(error: IHttpFetchError) {
+ if (!error.response) {
+ return i18n.translate('xpack.graph.fatalError.unavailableServerErrorMessage', {
+ defaultMessage:
+ 'An HTTP request has failed to connect. ' +
+ 'Please check if the Kibana server is running and that your browser has a working connection, ' +
+ 'or contact your system administrator.',
+ });
+ }
+ return i18n.translate('xpack.graph.fatalError.errorStatusMessage', {
+ defaultMessage: 'Error {errStatus} {errStatusText}: {errMessage}',
+ values: {
+ errStatus: error.body.status,
+ errStatusText: error.body.statusText,
+ errMessage: error.body.message,
+ },
+ });
+}
diff --git a/x-pack/legacy/plugins/graph/public/index.ts b/x-pack/legacy/plugins/graph/public/index.ts
index 0249ca74035d6..48420d403653f 100644
--- a/x-pack/legacy/plugins/graph/public/index.ts
+++ b/x-pack/legacy/plugins/graph/public/index.ts
@@ -14,11 +14,11 @@ import chrome from 'ui/chrome';
import { IPrivate } from 'ui/private';
// @ts-ignore
import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
-import { Storage } from 'ui/storage';
// @ts-ignore
import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry';
import { npSetup, npStart } from 'ui/new_platform';
+import { Storage } from '../../../../../src/plugins/kibana_utils/public';
import { start as data } from '../../../../../src/legacy/core_plugins/data/public/legacy';
import { GraphPlugin } from './plugin';
@@ -36,7 +36,6 @@ async function getAngularInjectedDependencies(): Promise('Private');
return {
- $http: injector.get('$http'),
savedObjectRegistry: Private(SavedObjectRegistryProvider),
kbnBaseUrl: injector.get('kbnBaseUrl'),
savedGraphWorkspaces: Private(SavedWorkspacesProvider),
diff --git a/x-pack/legacy/plugins/graph/public/render_app.ts b/x-pack/legacy/plugins/graph/public/render_app.ts
index 8625e20ab9c52..a8a86f4d1f850 100644
--- a/x-pack/legacy/plugins/graph/public/render_app.ts
+++ b/x-pack/legacy/plugins/graph/public/render_app.ts
@@ -63,10 +63,6 @@ export interface GraphDependencies extends LegacyAngularInjectedDependencies {
* These dependencies have to be migrated to their NP counterparts.
*/
export interface LegacyAngularInjectedDependencies {
- /**
- * angular $http service
- */
- $http: any;
/**
* Instance of SavedObjectRegistryProvider
*/
diff --git a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js b/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js
index e96fc79967316..31d8337857911 100644
--- a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js
+++ b/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js
@@ -111,7 +111,7 @@ describe('policy table', () => {
});
test('should show more when per page value is increased', () => {
const rendered = mountWithIntl(component);
- const perPageButton = rendered.find('#customizablePagination').find('button');
+ const perPageButton = rendered.find('EuiTablePagination EuiPopover').find('button');
perPageButton.simulate('click');
rendered.update();
const fiftyButton = rendered.find('.euiContextMenuItem').at(1);
diff --git a/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js
index d6a53eefcdc95..278ec918100d9 100644
--- a/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js
+++ b/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js
@@ -155,7 +155,7 @@ describe('index table', () => {
});
test('should show more when per page value is increased', () => {
const rendered = mountWithIntl(component);
- const perPageButton = rendered.find('#customizablePagination').find('button');
+ const perPageButton = rendered.find('EuiTablePagination EuiPopover').find('button');
perPageButton.simulate('click');
rendered.update();
const fiftyButton = rendered.find('.euiContextMenuItem').at(1);
diff --git a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_aliases.tsx b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_aliases.tsx
index d1ed816bebd45..3a1dcbc7e762d 100644
--- a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_aliases.tsx
+++ b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_aliases.tsx
@@ -34,6 +34,6 @@ export const TabAliases: React.FunctionComponent = ({ templateDetails })
}
iconType="pin"
data-test-subj="noAliasesCallout"
- >
+ />
);
};
diff --git a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_mappings.tsx b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_mappings.tsx
index 91f84a5ecf726..9439b0e31ae84 100644
--- a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_mappings.tsx
+++ b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_mappings.tsx
@@ -34,6 +34,6 @@ export const TabMappings: React.FunctionComponent = ({ templateDetails })
}
iconType="pin"
data-test-subj="noMappingsCallout"
- >
+ />
);
};
diff --git a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_settings.tsx b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_settings.tsx
index 6a83b714519d7..0370a89850721 100644
--- a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_settings.tsx
+++ b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_settings.tsx
@@ -34,6 +34,6 @@ export const TabSettings: React.FunctionComponent = ({ templateDetails })
}
iconType="pin"
data-test-subj="noSettingsCallout"
- >
+ />
);
};
diff --git a/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx b/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx
index ca67aec9642ac..d7c9876a07a8d 100644
--- a/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx
@@ -11,36 +11,30 @@ import React from 'react';
import { AutocompleteSuggestion } from '../../../../../../../src/plugins/data/public';
import euiStyled from '../../../../../common/eui_styled_components';
-interface SuggestionItemProps {
+interface Props {
isSelected?: boolean;
onClick?: React.MouseEventHandler;
onMouseEnter?: React.MouseEventHandler;
suggestion: AutocompleteSuggestion;
}
-export class SuggestionItem extends React.Component {
- public static defaultProps: Partial = {
- isSelected: false,
- };
+export const SuggestionItem: React.SFC = props => {
+ const { isSelected, onClick, onMouseEnter, suggestion } = props;
- public render() {
- const { isSelected, onClick, onMouseEnter, suggestion } = this.props;
+ return (
+
+
+
+
+ {suggestion.text}
+ {suggestion.description}
+
+ );
+};
- return (
-
-
-
-
- {suggestion.text}
- {suggestion.description}
-
- );
- }
-}
+SuggestionItem.defaultProps = {
+ isSelected: false,
+};
const SuggestionItemContainer = euiStyled.div<{
isSelected?: boolean;
diff --git a/x-pack/legacy/plugins/infra/public/components/eui/toolbar/toolbar.tsx b/x-pack/legacy/plugins/infra/public/components/eui/toolbar/toolbar.tsx
index b65f3043c2144..6f1cfc4078ae2 100644
--- a/x-pack/legacy/plugins/infra/public/components/eui/toolbar/toolbar.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/eui/toolbar/toolbar.tsx
@@ -17,5 +17,4 @@ export const Toolbar = euiStyled(EuiPanel).attrs({
border-left: none;
border-radius: 0;
padding: ${props => props.theme.eui.euiSizeS} ${props => props.theme.eui.euiSizeL};
- z-index: ${props => props.theme.eui.euiZLevel1};
`;
diff --git a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx b/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx
index 3c2c3d3bd05d0..7cb86f6e4d0ec 100644
--- a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx
@@ -108,7 +108,7 @@ export const toMetricOpt = (metric: InfraSnapshotMetricType) => {
case InfraSnapshotMetricType.tx:
return {
text: ToolbarTranslations.OutboundTraffic,
- value: InfraSnapshotMetricType.rx,
+ value: InfraSnapshotMetricType.tx,
};
case InfraSnapshotMetricType.logRate:
return {
diff --git a/x-pack/legacy/plugins/infra/public/components/loading_overlay_wrapper.tsx b/x-pack/legacy/plugins/infra/public/components/loading_overlay_wrapper.tsx
new file mode 100644
index 0000000000000..0f70c40059c93
--- /dev/null
+++ b/x-pack/legacy/plugins/infra/public/components/loading_overlay_wrapper.tsx
@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiLoadingSpinner } from '@elastic/eui';
+import { transparentize } from 'polished';
+import React from 'react';
+
+import { euiStyled } from '../../../../common/eui_styled_components';
+
+export const LoadingOverlayWrapper: React.FC<
+ React.HTMLAttributes & {
+ isLoading: boolean;
+ loadingChildren?: React.ReactNode;
+ }
+> = ({ children, isLoading, loadingChildren, ...rest }) => {
+ return (
+
+ {children}
+ {isLoading ? {loadingChildren} : null}
+
+ );
+};
+
+const Overlay: React.FC = ({ children }) => (
+ {children ? children : }
+);
+
+const RelativeDiv = euiStyled.div`
+ position: relative;
+`;
+
+const OverlayDiv = euiStyled.div`
+ align-items: center;
+ background-color: ${props => transparentize(0.3, props.theme.eui.euiColorEmptyShade)};
+ display: flex;
+ height: 100%;
+ justify-content: center;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 100%;
+`;
diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx
index 218b42b48c9b9..752a0d6e27a7f 100644
--- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx
@@ -114,29 +114,28 @@ interface ProgressEntryProps {
isLoading: boolean;
}
-class ProgressEntry extends React.PureComponent {
- public render() {
- const { alignment, children, className, color, isLoading } = this.props;
- // NOTE: styled-components seems to make all props in EuiProgress required, so this
- // style attribute hacking replaces styled-components here for now until that can be fixed
- // see: https://github.com/elastic/eui/issues/1655
- const alignmentStyle =
- alignment === 'top' ? { top: 0, bottom: 'initial' } : { top: 'initial', bottom: 0 };
+const ProgressEntry: React.SFC = props => {
+ const { alignment, children, className, color, isLoading } = props;
- return (
-
-
- {children}
-
- );
- }
-}
+ // NOTE: styled-components seems to make all props in EuiProgress required, so this
+ // style attribute hacking replaces styled-components here for now until that can be fixed
+ // see: https://github.com/elastic/eui/issues/1655
+ const alignmentStyle =
+ alignment === 'top' ? { top: 0, bottom: 'initial' } : { top: 'initial', bottom: 0 };
+
+ return (
+
+
+ {children}
+
+ );
+};
const ProgressEntryWrapper = euiStyled.div`
align-items: center;
diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx
index d439308194d18..fc3c8b3bf2b31 100644
--- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx
@@ -102,6 +102,14 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
targetId: null,
items: [],
};
+ } else if (
+ hasItems &&
+ (nextItems.length !== prevState.items.length || nextItems[0] !== prevState.items[0])
+ ) {
+ return {
+ ...prevState,
+ items: nextItems,
+ };
}
return null;
@@ -180,6 +188,7 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
hideScrollbar={true}
data-test-subj={'logStream'}
isLocked={scrollLock.isEnabled}
+ entriesCount={items.length}
>
{registerChild => (
<>
diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx
index 7ff4a2cacee09..dd368ef4d8f92 100644
--- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx
@@ -30,6 +30,7 @@ interface VerticalScrollPanelProps {
hideScrollbar?: boolean;
'data-test-subj'?: string;
isLocked: boolean;
+ entriesCount: number;
}
interface VerticalScrollPanelSnapshot {
@@ -226,7 +227,7 @@ export class VerticalScrollPanel extends React.PureComponent<
if (
prevProps.height !== this.props.height ||
prevProps.target !== this.props.target ||
- React.Children.count(prevProps.children) !== React.Children.count(this.props.children)
+ prevProps.entriesCount !== this.props.entriesCount
) {
this.handleUpdatedChildren(snapshot.scrollTarget, snapshot.scrollOffset);
}
diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/sections/chart_section.tsx b/x-pack/legacy/plugins/infra/public/components/metrics/sections/chart_section.tsx
index cf148eefe8e8f..6d8503b333c0b 100644
--- a/x-pack/legacy/plugins/infra/public/components/metrics/sections/chart_section.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/metrics/sections/chart_section.tsx
@@ -127,7 +127,7 @@ export const ChartSection = ({
key={`series-${section.id}-${series.id}`}
id={`series-${section.id}-${series.id}`}
series={series}
- name={getChartName(section, series.id, series.label)}
+ name={getChartName(section, series.id, series.id)}
type={getChartType(section, series.id)}
color={getChartColor(section, series.id)}
stack={visConfig.stacked}
diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/sections/series_chart.tsx b/x-pack/legacy/plugins/infra/public/components/metrics/sections/series_chart.tsx
index 9fd1f3eadfb49..b75f669a6d1ec 100644
--- a/x-pack/legacy/plugins/infra/public/components/metrics/sections/series_chart.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/metrics/sections/series_chart.tsx
@@ -45,12 +45,6 @@ export const AreaChart = ({ id, color, series, name, type, stack }: Props) => {
strokeWidth: 'area' === type ? 1 : 2,
visible: true,
},
- point: {
- visible: true,
- radius: 1,
- strokeWidth: 2,
- opacity: 1,
- },
};
const colors: DataSeriesColorsValues = {
colorValues: [],
diff --git a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/series_chart.tsx b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/series_chart.tsx
index 5b70b0cef083a..8c3c80e0a3852 100644
--- a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/series_chart.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/series_chart.tsx
@@ -63,12 +63,6 @@ export const MetricsExplorerAreaChart = ({ metric, id, series, type, stack }: Pr
opacity: 0.5,
visible: type === MetricsExplorerChartType.area,
},
- point: {
- visible: true,
- radius: 2,
- strokeWidth: 2,
- opacity: 1,
- },
};
return (
{
+export const MetricsExplorerBarChart = ({ metric, id, series, stack }: Props) => {
const color =
(metric.color && colorTransformer(metric.color)) ||
colorTransformer(MetricsExplorerColor.color0);
diff --git a/x-pack/legacy/plugins/infra/public/components/navigation/routed_tabs.tsx b/x-pack/legacy/plugins/infra/public/components/navigation/routed_tabs.tsx
index 437a0eb513da0..0b1d34870a72d 100644
--- a/x-pack/legacy/plugins/infra/public/components/navigation/routed_tabs.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/navigation/routed_tabs.tsx
@@ -4,9 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiTab, EuiTabs, EuiLink } from '@elastic/eui';
+import { EuiBetaBadge, EuiLink, EuiTab, EuiTabs } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
import React from 'react';
import { Route } from 'react-router-dom';
+
import euiStyled from '../../../../../common/eui_styled_components';
interface TabConfiguration {
@@ -54,6 +56,24 @@ export class RoutedTabs extends React.Component {
}
}
+const tabBetaBadgeLabel = i18n.translate('xpack.infra.common.tabBetaBadgeLabel', {
+ defaultMessage: 'Beta',
+});
+
+const tabBetaBadgeTooltipContent = i18n.translate('xpack.infra.common.tabBetaBadgeTooltipContent', {
+ defaultMessage:
+ 'This feature is under active development. Extra functionality is coming, and some functionality may change.',
+});
+
+export const TabBetaBadge = euiStyled(EuiBetaBadge).attrs({
+ 'aria-label': tabBetaBadgeLabel,
+ label: tabBetaBadgeLabel,
+ tooltipContent: tabBetaBadgeTooltipContent,
+})`
+ margin-left: 4px;
+ vertical-align: baseline;
+`;
+
const TabContainer = euiStyled.div`
.euiLink {
color: inherit !important;
diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx
index 8bd9f1074ac54..81a80fb565a4b 100644
--- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx
+++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx
@@ -8,6 +8,23 @@ import createContainer from 'constate';
import { useMemo, useEffect } from 'react';
import { useLogEntryRate } from './log_entry_rate';
+import { GetLogEntryRateSuccessResponsePayload } from '../../../../common/http_api/log_analysis';
+
+type PartitionBucket = {
+ startTime: number;
+} & GetLogEntryRateSuccessResponsePayload['data']['histogramBuckets'][0]['partitions'][0];
+
+type PartitionRecord = Record<
+ string,
+ { buckets: PartitionBucket[]; topAnomalyScore: number; totalNumberOfLogEntries: number }
+>;
+
+export interface LogRateResults {
+ bucketDuration: number;
+ totalNumberOfLogEntries: number;
+ histogramBuckets: GetLogEntryRateSuccessResponsePayload['data']['histogramBuckets'];
+ partitionBuckets: PartitionRecord;
+}
export const useLogAnalysisResults = ({
sourceId,
@@ -35,10 +52,66 @@ export const useLogAnalysisResults = ({
getLogEntryRate();
}, [sourceId, startTime, endTime, bucketDuration, lastRequestTime]);
+ const logRateResults: LogRateResults | null = useMemo(() => {
+ if (logEntryRate) {
+ return {
+ bucketDuration: logEntryRate.bucketDuration,
+ totalNumberOfLogEntries: logEntryRate.totalNumberOfLogEntries,
+ histogramBuckets: logEntryRate.histogramBuckets,
+ partitionBuckets: formatLogEntryRateResultsByPartition(logEntryRate),
+ };
+ } else {
+ return null;
+ }
+ }, [logEntryRate]);
+
return {
isLoading,
- logEntryRate,
+ logRateResults,
};
};
export const LogAnalysisResults = createContainer(useLogAnalysisResults);
+
+const formatLogEntryRateResultsByPartition = (
+ results: GetLogEntryRateSuccessResponsePayload['data']
+): PartitionRecord => {
+ const partitionedBuckets = results.histogramBuckets.reduce<
+ Record
+ >((partitionResults, bucket) => {
+ return bucket.partitions.reduce>(
+ (_partitionResults, partition) => {
+ return {
+ ..._partitionResults,
+ [partition.partitionId]: {
+ buckets: _partitionResults[partition.partitionId]
+ ? [
+ ..._partitionResults[partition.partitionId].buckets,
+ { startTime: bucket.startTime, ...partition },
+ ]
+ : [{ startTime: bucket.startTime, ...partition }],
+ },
+ };
+ },
+ partitionResults
+ );
+ }, {});
+
+ const resultsByPartition: PartitionRecord = {};
+
+ Object.entries(partitionedBuckets).map(([key, value]) => {
+ const anomalyScores = value.buckets.reduce((scores: number[], bucket) => {
+ return [...scores, bucket.maximumAnomalyScore];
+ }, []);
+ const totalNumberOfLogEntries = value.buckets.reduce((total, bucket) => {
+ return (total += bucket.numberOfLogEntries);
+ }, 0);
+ resultsByPartition[key] = {
+ topAnomalyScore: Math.max(...anomalyScores),
+ totalNumberOfLogEntries,
+ buckets: value.buckets,
+ };
+ });
+
+ return resultsByPartition;
+};
diff --git a/x-pack/legacy/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx b/x-pack/legacy/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx
index cd9ce35a32b68..86beb28a7f3ca 100644
--- a/x-pack/legacy/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx
+++ b/x-pack/legacy/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx
@@ -106,6 +106,13 @@ export const withWaffleViewState = connect(
),
})
);
+ } else {
+ dispatch(
+ waffleFilterActions.applyWaffleFilterQuery({
+ query: null,
+ serializedQuery: null,
+ })
+ );
}
},
};
diff --git a/x-pack/legacy/plugins/infra/public/pages/link_to/link_to.tsx b/x-pack/legacy/plugins/infra/public/pages/link_to/link_to.tsx
index abb3aa6b26b15..1318e9ca6c2c5 100644
--- a/x-pack/legacy/plugins/infra/public/pages/link_to/link_to.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/link_to/link_to.tsx
@@ -16,27 +16,21 @@ interface LinkToPageProps {
match: RouteMatch<{}>;
}
-export class LinkToPage extends React.Component {
- public render() {
- const { match } = this.props;
-
- return (
-
-
-
-
-
-
-
- );
- }
-}
+export const LinkToPage: React.SFC = props => (
+
+
+
+
+
+
+
+);
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx
index ffc48a0af9de9..7fa9ff3c93db7 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx
@@ -6,23 +6,23 @@
import datemath from '@elastic/datemath';
import {
+ EuiBadge,
EuiFlexGroup,
EuiFlexItem,
EuiPage,
EuiPanel,
EuiSuperDatePicker,
- EuiBadge,
EuiText,
} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
import numeral from '@elastic/numeral';
import { FormattedMessage } from '@kbn/i18n/react';
import moment from 'moment';
import React, { useCallback, useContext, useMemo, useState } from 'react';
+
import euiStyled from '../../../../../../common/eui_styled_components';
import { TimeRange } from '../../../../common/http_api/shared/time_range';
import { bucketSpan } from '../../../../common/log_analysis';
-import { LoadingPage } from '../../../components/loading_page';
+import { LoadingOverlayWrapper } from '../../../components/loading_overlay_wrapper';
import {
LogAnalysisJobs,
StringTimeRange,
@@ -82,15 +82,15 @@ export const AnalysisResultsContent = ({
return roundedResult < bucketSpan ? bucketSpan : roundedResult;
}, [queryTimeRange.value.startTime, queryTimeRange.value.endTime]);
- const { isLoading, logEntryRate } = useLogAnalysisResults({
+ const { isLoading, logRateResults } = useLogAnalysisResults({
sourceId,
startTime: queryTimeRange.value.startTime,
endTime: queryTimeRange.value.endTime,
bucketDuration,
lastRequestTime: queryTimeRange.lastChangedTime,
});
- const hasResults = useMemo(() => logEntryRate && logEntryRate.histogramBuckets.length > 0, [
- logEntryRate,
+ const hasResults = useMemo(() => logRateResults && logRateResults.histogramBuckets.length > 0, [
+ logRateResults,
]);
const handleQueryTimeRangeChange = useCallback(
@@ -162,89 +162,77 @@ export const AnalysisResultsContent = ({
);
return (
- <>
- {isLoading && !logEntryRate ? (
-
- ) : (
- <>
-
-
+
+
+
+
+
-
-
-
- {!isLoading && logEntryRate ? (
-
-
-
- {numeral(logEntryRate.totalNumberOfLogEntries).format('0.00a')}
-
-
- ),
- startTime: (
- {moment(queryTimeRange.value.startTime).format(dateFormat)}
- ),
- endTime: (
- {moment(queryTimeRange.value.endTime).format(dateFormat)}
- ),
- }}
- />
-
- ) : null}
-
-
-
+
+
+
+ {numeral(logRateResults.totalNumberOfLogEntries).format('0.00a')}
+
+
+ ),
+ startTime: (
+ {moment(queryTimeRange.value.startTime).format(dateFormat)}
+ ),
+ endTime: {moment(queryTimeRange.value.endTime).format(dateFormat)} ,
+ }}
/>
-
-
-
-
-
-
- {isFirstUse && !hasResults ? : null}
-
-
+
+
+ ) : null}
-
-
-
+
-
- >
- )}
- >
+
+
+
+
+ {isFirstUse && !hasResults ? : null}
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/analyze_in_ml_button.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/analyze_in_ml_button.tsx
index 191e3cb7d7bfd..317bd6ec5e925 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/analyze_in_ml_button.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/analyze_in_ml_button.tsx
@@ -25,7 +25,7 @@ export const AnalyzeInMlButton: React.FunctionComponent<{
defaultMessage="Analyze in ML"
/>
);
- return partition ? (
+ return typeof partition === 'string' ? (
void;
timeRange: TimeRange;
jobId: string;
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx
index 5aa5891d7981d..26f44519312e5 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx
@@ -8,17 +8,17 @@ import {
EuiEmptyPrompt,
EuiFlexGroup,
EuiFlexItem,
- EuiLoadingChart,
EuiSpacer,
EuiStat,
EuiTitle,
+ EuiLoadingSpinner,
} from '@elastic/eui';
import numeral from '@elastic/numeral';
import { i18n } from '@kbn/i18n';
import React, { useMemo } from 'react';
import euiStyled from '../../../../../../../../common/eui_styled_components';
-import { GetLogEntryRateSuccessResponsePayload } from '../../../../../../common/http_api';
+import { LogRateResults } from '../../../../../containers/logs/log_analysis/log_analysis_results';
import { TimeRange } from '../../../../../../common/http_api/shared/time_range';
import { JobStatus, SetupStatus } from '../../../../../../common/log_analysis';
import {
@@ -31,11 +31,12 @@ import { AnomaliesChart } from './chart';
import { AnomaliesTable } from './table';
import { LogAnalysisJobProblemIndicator } from '../../../../../components/logging/log_analysis_job_status';
import { AnalyzeInMlButton } from '../analyze_in_ml_button';
+import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper';
export const AnomaliesResults: React.FunctionComponent<{
isLoading: boolean;
jobStatus: JobStatus;
- results: GetLogEntryRateSuccessResponsePayload['data'] | null;
+ results: LogRateResults | null;
setTimeRange: (timeRange: TimeRange) => void;
setupStatus: SetupStatus;
timeRange: TimeRange;
@@ -53,15 +54,6 @@ export const AnomaliesResults: React.FunctionComponent<{
viewSetupForUpdate,
jobId,
}) => {
- const title = i18n.translate('xpack.infra.logs.analysis.anomaliesSectionTitle', {
- defaultMessage: 'Anomalies',
- });
-
- const loadingAriaLabel = i18n.translate(
- 'xpack.infra.logs.analysis.anomaliesSectionLoadingAriaLabel',
- { defaultMessage: 'Loading anomalies' }
- );
-
const hasAnomalies = useMemo(() => {
return results && results.histogramBuckets
? results.histogramBuckets.some(bucket => {
@@ -117,92 +109,93 @@ export const AnomaliesResults: React.FunctionComponent<{
onRecreateMlJobForUpdate={viewSetupForUpdate}
/>
- {isLoading ? (
-
-
-
-
-
- ) : !results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? (
-
- {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoDataTitle', {
- defaultMessage: 'There is no data to display.',
- })}
-
- }
- titleSize="m"
- body={
-
- {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoDataBody', {
- defaultMessage: 'You may want to adjust your time range.',
- })}
-
- }
- />
- ) : !hasAnomalies ? (
-
- {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoAnomaliesTitle', {
- defaultMessage: 'No anomalies were detected.',
- })}
-
- }
- titleSize="m"
- />
- ) : (
- <>
-
-
-
-
-
-
-
-
-
-
- }>
+ {!results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? (
+
+ {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoDataTitle', {
+ defaultMessage: 'There is no data to display.',
+ })}
+
+ }
+ titleSize="m"
+ body={
+
+ {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoDataBody', {
+ defaultMessage: 'You may want to adjust your time range.',
+ })}
+
+ }
+ />
+ ) : !hasAnomalies ? (
+
+ {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoAnomaliesTitle', {
+ defaultMessage: 'No anomalies were detected.',
+ })}
+
+ }
+ titleSize="m"
/>
- >
- )}
+ ) : (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
>
);
};
+const title = i18n.translate('xpack.infra.logs.analysis.anomaliesSectionTitle', {
+ defaultMessage: 'Anomalies',
+});
+
interface ParsedAnnotationDetails {
- anomalyScoresByPartition: Array<{ partitionId: string; maximumAnomalyScore: number }>;
+ anomalyScoresByPartition: Array<{ partitionName: string; maximumAnomalyScore: number }>;
}
const overallAnomalyScoreLabel = i18n.translate(
@@ -211,6 +204,7 @@ const overallAnomalyScoreLabel = i18n.translate(
defaultMessage: 'Max anomaly scores:',
}
);
+
const AnnotationTooltip: React.FunctionComponent<{ details: string }> = ({ details }) => {
const parsedDetails: ParsedAnnotationDetails = JSON.parse(details);
return (
@@ -219,11 +213,11 @@ const AnnotationTooltip: React.FunctionComponent<{ details: string }> = ({ detai
{overallAnomalyScoreLabel}
- {parsedDetails.anomalyScoresByPartition.map(({ partitionId, maximumAnomalyScore }) => {
+ {parsedDetails.anomalyScoresByPartition.map(({ partitionName, maximumAnomalyScore }) => {
return (
-
+
- {`${partitionId}: `}
+ {`${partitionName}: `}
{maximumAnomalyScore}
@@ -237,7 +231,7 @@ const AnnotationTooltip: React.FunctionComponent<{ details: string }> = ({ detai
const renderAnnotationTooltip = (details?: string) => {
// Note: Seems to be necessary to get things typed correctly all the way through to elastic-charts components
if (!details) {
- return
;
+ return
;
}
return ;
};
@@ -245,3 +239,10 @@ const renderAnnotationTooltip = (details?: string) => {
const TooltipWrapper = euiStyled('div')`
white-space: nowrap;
`;
+
+const loadingAriaLabel = i18n.translate(
+ 'xpack.infra.logs.analysis.anomaliesSectionLoadingAriaLabel',
+ { defaultMessage: 'Loading anomalies' }
+);
+
+const LoadingOverlayContent = () => ;
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx
index 88ffcae6e9dea..ebf31d8320df5 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx
@@ -9,9 +9,9 @@ import { EuiBasicTable, EuiButtonIcon } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services';
import { TimeRange } from '../../../../../../common/http_api/shared/time_range';
-import { GetLogEntryRateSuccessResponsePayload } from '../../../../../../common/http_api/log_analysis/results/log_entry_rate';
+import { LogRateResults } from '../../../../../containers/logs/log_analysis/log_analysis_results';
import { AnomaliesTableExpandedRow } from './expanded_row';
-import { getTopAnomalyScoresByPartition, formatAnomalyScore } from '../helpers/data_formatters';
+import { formatAnomalyScore, getFriendlyNameForPartitionId } from '../helpers/data_formatters';
interface TableItem {
id: string;
@@ -49,17 +49,20 @@ const maxAnomalyScoreColumnName = i18n.translate(
);
export const AnomaliesTable: React.FunctionComponent<{
- results: GetLogEntryRateSuccessResponsePayload['data'];
+ results: LogRateResults;
setTimeRange: (timeRange: TimeRange) => void;
timeRange: TimeRange;
jobId: string;
}> = ({ results, timeRange, setTimeRange, jobId }) => {
const tableItems: TableItem[] = useMemo(() => {
- return Object.entries(getTopAnomalyScoresByPartition(results)).map(([key, value]) => {
+ return Object.entries(results.partitionBuckets).map(([key, value]) => {
return {
- id: key || 'unknown', // Note: EUI's table expanded rows won't work with a key of '' in itemIdToExpandedRowMap
- partition: key || 'unknown',
- topAnomalyScore: formatAnomalyScore(value),
+ // Note: EUI's table expanded rows won't work with a key of '' in itemIdToExpandedRowMap, so we have to use the friendly name here
+ id: getFriendlyNameForPartitionId(key),
+ // The real ID
+ partitionId: key,
+ partition: getFriendlyNameForPartitionId(key),
+ topAnomalyScore: formatAnomalyScore(value.topAnomalyScore),
};
});
}, [results]);
@@ -108,7 +111,7 @@ export const AnomaliesTable: React.FunctionComponent<{
...itemIdToExpandedRowMap,
[item.id]: (
;
@@ -17,15 +17,13 @@ const ML_SEVERITY_SCORES: MLSeverityScores = {
critical: 75,
};
-export const getLogEntryRatePartitionedSeries = (
- results: GetLogEntryRateSuccessResponsePayload['data']
-) => {
+export const getLogEntryRatePartitionedSeries = (results: LogRateResults) => {
return results.histogramBuckets.reduce>(
(buckets, bucket) => {
return [
...buckets,
...bucket.partitions.map(partition => ({
- group: partition.partitionId === '' ? 'unknown' : partition.partitionId,
+ group: getFriendlyNameForPartitionId(partition.partitionId),
time: bucket.startTime,
value: partition.averageActualLogEntryRate,
})),
@@ -35,9 +33,7 @@ export const getLogEntryRatePartitionedSeries = (
);
};
-export const getLogEntryRateCombinedSeries = (
- results: GetLogEntryRateSuccessResponsePayload['data']
-) => {
+export const getLogEntryRateCombinedSeries = (results: LogRateResults) => {
return results.histogramBuckets.reduce>(
(buckets, bucket) => {
return [
@@ -54,69 +50,27 @@ export const getLogEntryRateCombinedSeries = (
);
};
-export const getLogEntryRateSeriesForPartition = (
- results: GetLogEntryRateSuccessResponsePayload['data'],
- partitionId: string
-) => {
- return results.histogramBuckets.reduce>(
- (buckets, bucket) => {
- const partitionResults = bucket.partitions.find(partition => {
- return (
- partition.partitionId === partitionId ||
- (partition.partitionId === '' && partitionId === 'unknown')
- );
- });
- if (!partitionResults) {
- return buckets;
- }
- return [
- ...buckets,
- {
- time: bucket.startTime,
- value: partitionResults.averageActualLogEntryRate,
- },
- ];
- },
- []
- );
-};
-
-export const getTopAnomalyScoresByPartition = (
- results: GetLogEntryRateSuccessResponsePayload['data']
-) => {
- return results.histogramBuckets.reduce>((topScores, bucket) => {
- bucket.partitions.forEach(partition => {
- if (partition.maximumAnomalyScore > 0) {
- topScores = {
- ...topScores,
- [partition.partitionId]:
- !topScores[partition.partitionId] ||
- partition.maximumAnomalyScore > topScores[partition.partitionId]
- ? partition.maximumAnomalyScore
- : topScores[partition.partitionId],
- };
- }
- });
- return topScores;
- }, {});
+export const getLogEntryRateSeriesForPartition = (results: LogRateResults, partitionId: string) => {
+ return results.partitionBuckets[partitionId].buckets.reduce<
+ Array<{ time: number; value: number }>
+ >((buckets, bucket) => {
+ return [
+ ...buckets,
+ {
+ time: bucket.startTime,
+ value: bucket.averageActualLogEntryRate,
+ },
+ ];
+ }, []);
};
-export const getAnnotationsForPartition = (
- results: GetLogEntryRateSuccessResponsePayload['data'],
- partitionId: string
-) => {
- return results.histogramBuckets.reduce>(
+export const getAnnotationsForPartition = (results: LogRateResults, partitionId: string) => {
+ return results.partitionBuckets[partitionId].buckets.reduce<
+ Record
+ >(
(annotatedBucketsBySeverity, bucket) => {
- const partitionResults = bucket.partitions.find(partition => {
- return (
- partition.partitionId === partitionId ||
- (partition.partitionId === '' && partitionId === 'unknown')
- );
- });
- const severityCategory = partitionResults
- ? getSeverityCategoryForScore(partitionResults.maximumAnomalyScore)
- : null;
- if (!partitionResults || !partitionResults.maximumAnomalyScore || !severityCategory) {
+ const severityCategory = getSeverityCategoryForScore(bucket.maximumAnomalyScore);
+ if (!severityCategory) {
return annotatedBucketsBySeverity;
}
@@ -134,7 +88,7 @@ export const getAnnotationsForPartition = (
{
defaultMessage: 'Max anomaly score: {maxAnomalyScore}',
values: {
- maxAnomalyScore: formatAnomalyScore(partitionResults.maximumAnomalyScore),
+ maxAnomalyScore: formatAnomalyScore(bucket.maximumAnomalyScore),
},
}
),
@@ -152,29 +106,17 @@ export const getAnnotationsForPartition = (
};
export const getTotalNumberOfLogEntriesForPartition = (
- results: GetLogEntryRateSuccessResponsePayload['data'],
+ results: LogRateResults,
partitionId: string
) => {
- return results.histogramBuckets.reduce((sumPartitionNumberOfLogEntries, bucket) => {
- const partitionResults = bucket.partitions.find(partition => {
- return (
- partition.partitionId === partitionId ||
- (partition.partitionId === '' && partitionId === 'unknown')
- );
- });
- if (!partitionResults || !partitionResults.numberOfLogEntries) {
- return sumPartitionNumberOfLogEntries;
- } else {
- return (sumPartitionNumberOfLogEntries += partitionResults.numberOfLogEntries);
- }
- }, 0);
+ return results.partitionBuckets[partitionId].totalNumberOfLogEntries;
};
-export const getAnnotationsForAll = (results: GetLogEntryRateSuccessResponsePayload['data']) => {
+export const getAnnotationsForAll = (results: LogRateResults) => {
return results.histogramBuckets.reduce>(
(annotatedBucketsBySeverity, bucket) => {
const maxAnomalyScoresByPartition = bucket.partitions.reduce<
- Array<{ partitionId: string; maximumAnomalyScore: number }>
+ Array<{ partitionName: string; maximumAnomalyScore: number }>
>((bucketMaxAnomalyScoresByPartition, partition) => {
if (!getSeverityCategoryForScore(partition.maximumAnomalyScore)) {
return bucketMaxAnomalyScoresByPartition;
@@ -182,7 +124,7 @@ export const getAnnotationsForAll = (results: GetLogEntryRateSuccessResponsePayl
return [
...bucketMaxAnomalyScoresByPartition,
{
- partitionId: partition.partitionId ? partition.partitionId : 'unknown',
+ partitionName: getFriendlyNameForPartitionId(partition.partitionId),
maximumAnomalyScore: formatAnomalyScore(partition.maximumAnomalyScore),
},
];
@@ -227,16 +169,14 @@ export const getAnnotationsForAll = (results: GetLogEntryRateSuccessResponsePayl
);
};
-export const getTopAnomalyScoreAcrossAllPartitions = (
- results: GetLogEntryRateSuccessResponsePayload['data']
-) => {
- const allMaxScores = results.histogramBuckets.reduce((scores, bucket) => {
- const bucketMaxScores = bucket.partitions.reduce((bucketScores, partition) => {
- return [...bucketScores, partition.maximumAnomalyScore];
- }, []);
- return [...scores, ...bucketMaxScores];
- }, []);
- return Math.max(...allMaxScores);
+export const getTopAnomalyScoreAcrossAllPartitions = (results: LogRateResults) => {
+ const allTopScores = Object.values(results.partitionBuckets).reduce(
+ (scores: number[], partition) => {
+ return [...scores, partition.topAnomalyScore];
+ },
+ []
+ );
+ return Math.max(...allTopScores);
};
const getSeverityCategoryForScore = (score: number): MLSeverityScoreCategories | undefined => {
@@ -257,3 +197,7 @@ const getSeverityCategoryForScore = (score: number): MLSeverityScoreCategories |
export const formatAnomalyScore = (score: number) => {
return Math.round(score);
};
+
+export const getFriendlyNameForPartitionId = (partitionId: string) => {
+ return partitionId !== '' ? partitionId : 'unknown';
+};
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx
index d4ddd14bfaa28..44805520f3b9e 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx
@@ -4,22 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiEmptyPrompt,
- EuiFlexGroup,
- EuiFlexItem,
- EuiLoadingChart,
- EuiSpacer,
- EuiTitle,
- EuiText,
-} from '@elastic/eui';
+import { EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiTitle, EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useMemo } from 'react';
-import { GetLogEntryRateSuccessResponsePayload } from '../../../../../../common/http_api/log_analysis/results/log_entry_rate';
+import { LogRateResults as Results } from '../../../../../containers/logs/log_analysis/log_analysis_results';
import { TimeRange } from '../../../../../../common/http_api/shared/time_range';
import { LogEntryRateBarChart } from './bar_chart';
import { getLogEntryRatePartitionedSeries } from '../helpers/data_formatters';
+import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper';
export const LogRateResults = ({
isLoading,
@@ -28,19 +21,10 @@ export const LogRateResults = ({
timeRange,
}: {
isLoading: boolean;
- results: GetLogEntryRateSuccessResponsePayload['data'] | null;
+ results: Results | null;
setTimeRange: (timeRange: TimeRange) => void;
timeRange: TimeRange;
}) => {
- const title = i18n.translate('xpack.infra.logs.analysis.logRateSectionTitle', {
- defaultMessage: 'Log entries',
- });
-
- const loadingAriaLabel = i18n.translate(
- 'xpack.infra.logs.analysis.logRateSectionLoadingAriaLabel',
- { defaultMessage: 'Loading log rate results' }
- );
-
const logEntryRateSeries = useMemo(
() => (results && results.histogramBuckets ? getLogEntryRatePartitionedSeries(results) : []),
[results]
@@ -51,57 +35,61 @@ export const LogRateResults = ({
{title}
- {isLoading ? (
- <>
-
-
-
-
-
-
- >
- ) : !results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? (
- <>
-
-
- {i18n.translate('xpack.infra.logs.analysis.logRateSectionNoDataTitle', {
- defaultMessage: 'There is no data to display.',
- })}
-
- }
- titleSize="m"
- body={
+ }>
+ {!results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? (
+ <>
+
+
+ {i18n.translate('xpack.infra.logs.analysis.logRateSectionNoDataTitle', {
+ defaultMessage: 'There is no data to display.',
+ })}
+
+ }
+ titleSize="m"
+ body={
+
+ {i18n.translate('xpack.infra.logs.analysis.logRateSectionNoDataBody', {
+ defaultMessage: 'You may want to adjust your time range.',
+ })}
+
+ }
+ />
+ >
+ ) : (
+ <>
+
- {i18n.translate('xpack.infra.logs.analysis.logRateSectionNoDataBody', {
- defaultMessage: 'You may want to adjust your time range.',
+
+ {i18n.translate('xpack.infra.logs.analysis.logRateSectionBucketSpanLabel', {
+ defaultMessage: 'Bucket span: ',
+ })}
+
+ {i18n.translate('xpack.infra.logs.analysis.logRateSectionBucketSpanValue', {
+ defaultMessage: '15 minutes',
})}
- }
- />
- >
- ) : (
- <>
-
-
-
- {i18n.translate('xpack.infra.logs.analysis.logRateSectionBucketSpanLabel', {
- defaultMessage: 'Bucket span: ',
- })}
-
- {i18n.translate('xpack.infra.logs.analysis.logRateSectionBucketSpanValue', {
- defaultMessage: '15 minutes',
- })}
-
-
-
- >
- )}
+
+
+ >
+ )}
+
>
);
};
+
+const title = i18n.translate('xpack.infra.logs.analysis.logRateSectionTitle', {
+ defaultMessage: 'Log entries',
+});
+
+const loadingAriaLabel = i18n.translate(
+ 'xpack.infra.logs.analysis.logRateSectionLoadingAriaLabel',
+ { defaultMessage: 'Loading log rate results' }
+);
+
+const LoadingOverlayContent = () => ;
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx
index e966336567e59..17f1aa48c87a2 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx
@@ -4,18 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { useMemo } from 'react';
-import moment, { Moment } from 'moment';
-
-import { i18n } from '@kbn/i18n';
import {
- EuiDescribedFormGroup,
- EuiFormRow,
EuiDatePicker,
+ EuiDatePickerProps,
+ EuiDescribedFormGroup,
EuiFlexGroup,
EuiFormControlLayout,
+ EuiFormRow,
} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import moment, { Moment } from 'moment';
+import React, { useMemo } from 'react';
+
+import { euiStyled } from '../../../../../../../../common/eui_styled_components';
const startTimeLabel = i18n.translate('xpack.infra.analysisSetup.startTimeLabel', {
defaultMessage: 'Start time',
@@ -84,7 +86,7 @@ export const AnalysisSetupTimerangeForm: React.FunctionComponent<{
setStartTime(undefined) } : undefined}
>
- setStartTime(selectedDateToParam(date))}
@@ -105,7 +107,7 @@ export const AnalysisSetupTimerangeForm: React.FunctionComponent<{
setEndTime(undefined) } : undefined}
>
- setEndTime(selectedDateToParam(date))}
@@ -129,3 +131,18 @@ export const AnalysisSetupTimerangeForm: React.FunctionComponent<{
);
};
+
+const FixedDatePicker = euiStyled(
+ ({
+ className,
+ inputClassName,
+ ...datePickerProps
+ }: {
+ className?: string;
+ inputClassName?: string;
+ } & EuiDatePickerProps) => (
+
+ )
+)`
+ z-index: 3 !important;
+`;
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx
index 7e935f3fb73ea..895d95b1471a0 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx
@@ -5,7 +5,6 @@
*/
import { i18n } from '@kbn/i18n';
-import { EuiBetaBadge } from '@elastic/eui';
import React from 'react';
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import { UICapabilities } from 'ui/capabilities';
@@ -14,7 +13,7 @@ import { injectUICapabilities } from 'ui/capabilities/react';
import { DocumentTitle } from '../../components/document_title';
import { HelpCenterContent } from '../../components/help_center_content';
import { Header } from '../../components/header';
-import { RoutedTabs } from '../../components/navigation/routed_tabs';
+import { RoutedTabs, TabBetaBadge } from '../../components/navigation/routed_tabs';
import { ColumnarPage } from '../../components/page';
import { SourceLoadingPage } from '../../components/source_loading_page';
import { SourceErrorPage } from '../../components/source_error_page';
@@ -28,6 +27,7 @@ import {
LogAnalysisCapabilities,
} from '../../containers/logs/log_analysis';
import { useSourceId } from '../../containers/source_id';
+import { RedirectWithQueryParams } from '../../utils/redirect_with_query_params';
interface LogsPageProps extends RouteComponentProps {
uiCapabilities: UICapabilities;
@@ -39,76 +39,32 @@ export const LogsPage = injectUICapabilities(({ match, uiCapabilities }: LogsPag
const logAnalysisCapabilities = useLogAnalysisCapabilities();
const streamTab = {
- title: i18n.translate('xpack.infra.logs.index.streamTabTitle', { defaultMessage: 'Stream' }),
+ title: streamTabTitle,
path: `${match.path}/stream`,
};
- const analysisBetaBadgeTitle = i18n.translate('xpack.infra.logs.index.analysisBetaBadgeTitle', {
- defaultMessage: 'Analysis',
- });
- const analysisBetaBadgeLabel = i18n.translate('xpack.infra.logs.index.analysisBetaBadgeLabel', {
- defaultMessage: 'Beta',
- });
- const analysisBetaBadgeTooltipContent = i18n.translate(
- 'xpack.infra.logs.index.analysisBetaBadgeTooltipContent',
- {
- defaultMessage:
- 'This feature is under active development. Extra functionality is coming, and some functionality may change.',
- }
- );
- const analysisBetaBadge = (
-
- );
- const analysisTab = {
+
+ const logRateTab = {
title: (
<>
-
- {i18n.translate('xpack.infra.logs.index.analysisTabTitle', {
- defaultMessage: 'Analysis',
- })}
-
- {analysisBetaBadge}
+ {logRateTabTitle}
+
>
),
- path: `${match.path}/analysis`,
+ path: `${match.path}/log-rate`,
};
+
const settingsTab = {
- title: i18n.translate('xpack.infra.logs.index.settingsTabTitle', {
- defaultMessage: 'Settings',
- }),
+ title: settingsTabTitle,
path: `${match.path}/settings`,
};
- const pageTitle = i18n.translate('xpack.infra.header.logsTitle', {
- defaultMessage: 'Logs',
- });
+
return (
-
+
-
+
-
-
-
+
+
+
+
>
)}
@@ -152,3 +113,25 @@ export const LogsPage = injectUICapabilities(({ match, uiCapabilities }: LogsPag
);
});
+
+const pageTitle = i18n.translate('xpack.infra.header.logsTitle', {
+ defaultMessage: 'Logs',
+});
+
+const streamTabTitle = i18n.translate('xpack.infra.logs.index.streamTabTitle', {
+ defaultMessage: 'Stream',
+});
+
+const logRateTabTitle = i18n.translate('xpack.infra.logs.index.analysisBetaBadgeTitle', {
+ defaultMessage: 'Log Rate',
+});
+
+const settingsTabTitle = i18n.translate('xpack.infra.logs.index.settingsTabTitle', {
+ defaultMessage: 'Settings',
+});
+
+const feedbackLinkText = i18n.translate('xpack.infra.logsPage.logsHelpContent.feedbackLinkText', {
+ defaultMessage: 'Provide feedback for Logs',
+});
+
+const feedbackLinkUrl = 'https://discuss.elastic.co/c/logs';
diff --git a/x-pack/legacy/plugins/infra/public/store/local/waffle_filter/reducer.ts b/x-pack/legacy/plugins/infra/public/store/local/waffle_filter/reducer.ts
index a34cc9659f0b7..912ad96357334 100644
--- a/x-pack/legacy/plugins/infra/public/store/local/waffle_filter/reducer.ts
+++ b/x-pack/legacy/plugins/infra/public/store/local/waffle_filter/reducer.ts
@@ -16,8 +16,8 @@ export interface KueryFilterQuery {
export type FilterQuery = KueryFilterQuery;
export interface SerializedFilterQuery {
- query: FilterQuery;
- serializedQuery: string;
+ query: FilterQuery | null;
+ serializedQuery: string | null;
}
export interface WaffleFilterState {
diff --git a/x-pack/legacy/plugins/integrations_manager/public/hooks/use_links.tsx b/x-pack/legacy/plugins/integrations_manager/public/hooks/use_links.tsx
index e951b6827b1d7..b9b0079ec75e8 100644
--- a/x-pack/legacy/plugins/integrations_manager/public/hooks/use_links.tsx
+++ b/x-pack/legacy/plugins/integrations_manager/public/hooks/use_links.tsx
@@ -22,20 +22,16 @@ interface DetailParams {
const removeRelativePath = (relativePath: string): string =>
new URL(relativePath, 'http://example.com').pathname;
-function addBasePath(path: string) {
+export function useLinks() {
const { http } = useCore();
- return http.basePath.prepend(path);
-}
+ function appRoot(path: string) {
+ // include '#' because we're using HashRouter
+ return http.basePath.prepend(patterns.APP_ROOT + '#' + path);
+ }
-function appRoot(path: string) {
- // include '#' because we're using HashRouter
- return addBasePath(patterns.APP_ROOT + '#' + path);
-}
-
-export function useLinks() {
return {
- toAssets: (path: string) => addBasePath(`/plugins/${PLUGIN.ID}/assets/${path}`),
- toImage: (path: string) => addBasePath(getFilePath(path)),
+ toAssets: (path: string) => http.basePath.prepend(`/plugins/${PLUGIN.ID}/assets/${path}`),
+ toImage: (path: string) => http.basePath.prepend(getFilePath(path)),
toRelativeImage: ({
path,
packageName,
@@ -48,7 +44,7 @@ export function useLinks() {
const imagePath = removeRelativePath(path);
const pkgkey = `${packageName}-${version}`;
const filePath = `${getInfoPath(pkgkey)}/${imagePath}`;
- return addBasePath(filePath);
+ return http.basePath.prepend(filePath);
},
toListView: () => appRoot(patterns.LIST_VIEW),
toDetailView: ({ name, version, panel }: DetailParams) => {
diff --git a/x-pack/legacy/plugins/integrations_manager/public/screens/detail/readme.tsx b/x-pack/legacy/plugins/integrations_manager/public/screens/detail/readme.tsx
index cf9ca225e5c8a..e14041e441cb0 100644
--- a/x-pack/legacy/plugins/integrations_manager/public/screens/detail/readme.tsx
+++ b/x-pack/legacy/plugins/integrations_manager/public/screens/detail/readme.tsx
@@ -20,23 +20,22 @@ export function Readme({
version: string;
}) {
const [markdown, setMarkdown] = useState(undefined);
-
+ const { toRelativeImage } = useLinks();
const handleImageUri = React.useCallback(
(uri: string) => {
- const { toRelativeImage } = useLinks();
const isRelative =
uri.indexOf('http://') === 0 || uri.indexOf('https://') === 0 ? false : true;
const fullUri = isRelative ? toRelativeImage({ packageName, version, path: uri }) : uri;
return fullUri;
},
- [packageName, version]
+ [toRelativeImage, packageName, version]
);
useEffect(() => {
getFileByPath(readmePath).then(res => {
setMarkdown(res);
});
- }, []);
+ }, [readmePath]);
return (
diff --git a/x-pack/legacy/plugins/integrations_manager/public/screens/home/search_results.tsx b/x-pack/legacy/plugins/integrations_manager/public/screens/home/search_results.tsx
index b5dd7afc80f95..11c56fd4c33a8 100644
--- a/x-pack/legacy/plugins/integrations_manager/public/screens/home/search_results.tsx
+++ b/x-pack/legacy/plugins/integrations_manager/public/screens/home/search_results.tsx
@@ -24,7 +24,7 @@ export function SearchResults({ term, results }: SearchResultsProps) {
controls={
- {results.length} results for "{term}"
+ {results.length} results for "{term}"
}
diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__fixtures__/index_pattern_response.json b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__fixtures__/index_pattern_response.json
index 408e839596ae2..27e480623f311 100644
--- a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__fixtures__/index_pattern_response.json
+++ b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__fixtures__/index_pattern_response.json
@@ -161,8 +161,7 @@
"searchable": true,
"aggregatable": true,
"readFromDocValues": true,
- "parent": "machine.os",
- "subType": "multi"
+ "subType":{ "multi":{ "parent": "machine.os" } }
},
{
"name": "geo.src",
@@ -277,6 +276,28 @@
"searchable": true,
"aggregatable": true,
"readFromDocValues": false
+ },
+ {
+ "name": "nestedField.child",
+ "type": "string",
+ "esTypes": ["text"],
+ "count": 0,
+ "scripted": false,
+ "searchable": true,
+ "aggregatable": false,
+ "readFromDocValues": false,
+ "subType": { "nested": { "path": "nestedField" } }
+ },
+ {
+ "name": "nestedField.nestedChild.doublyNestedChild",
+ "type": "string",
+ "esTypes": ["text"],
+ "count": 0,
+ "scripted": false,
+ "searchable": true,
+ "aggregatable": false,
+ "readFromDocValues": false,
+ "subType": { "nested": { "path": "nestedField.nestedChild" } }
}
]
}
diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js
index d19fb47468829..8a20337317cfb 100644
--- a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js
+++ b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js
@@ -80,4 +80,60 @@ describe('Kuery field suggestions', function () {
expect(suggestion).to.have.property('description');
});
});
+
+ describe('nested fields', function () {
+
+ it('should automatically wrap nested fields in KQL\'s nested syntax', () => {
+ const prefix = 'ch';
+ const suffix = '';
+ const suggestions = getSuggestions({ prefix, suffix });
+
+ const suggestion = suggestions.find(({ field }) => field.name === 'nestedField.child');
+ expect(suggestion.text).to.be('nestedField:{ child }');
+
+ // For most suggestions the cursor can be placed at the end of the suggestion text, but
+ // for the nested field syntax we want to place the cursor inside the curly braces
+ expect(suggestion.cursorIndex).to.be(20);
+ });
+
+ it('should narrow suggestions to children of a nested path if provided', () => {
+ const prefix = 'ch';
+ const suffix = '';
+
+ const allSuggestions = getSuggestions({ prefix, suffix });
+ expect(allSuggestions.length).to.be.greaterThan(2);
+
+ const nestedSuggestions = getSuggestions({ prefix, suffix, nestedPath: 'nestedField' });
+ expect(nestedSuggestions).to.have.length(2);
+ });
+
+ it('should not wrap the suggestion in KQL\'s nested syntax if the correct nested path is already provided', () => {
+ const prefix = 'ch';
+ const suffix = '';
+
+ const suggestions = getSuggestions({ prefix, suffix, nestedPath: 'nestedField' });
+ const suggestion = suggestions.find(({ field }) => field.name === 'nestedField.child');
+ expect(suggestion.text).to.be('child ');
+ });
+
+ it('should handle fields nested multiple levels deep', () => {
+ const prefix = 'doubly';
+ const suffix = '';
+
+ const suggestionsWithNoPath = getSuggestions({ prefix, suffix });
+ expect(suggestionsWithNoPath).to.have.length(1);
+ const [ noPathSuggestion ] = suggestionsWithNoPath;
+ expect(noPathSuggestion.text).to.be('nestedField.nestedChild:{ doublyNestedChild }');
+
+ const suggestionsWithPartialPath = getSuggestions({ prefix, suffix, nestedPath: 'nestedField' });
+ expect(suggestionsWithPartialPath).to.have.length(1);
+ const [ partialPathSuggestion ] = suggestionsWithPartialPath;
+ expect(partialPathSuggestion.text).to.be('nestedChild:{ doublyNestedChild }');
+
+ const suggestionsWithFullPath = getSuggestions({ prefix, suffix, nestedPath: 'nestedField.nestedChild' });
+ expect(suggestionsWithFullPath).to.have.length(1);
+ const [ fullPathSuggestion ] = suggestionsWithFullPath;
+ expect(fullPathSuggestion.text).to.be('doublyNestedChild ');
+ });
+ });
});
diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js
index 57d38ddab5c3d..bb20e927039c0 100644
--- a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js
+++ b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js
@@ -56,4 +56,9 @@ describe('Kuery operator suggestions', function () {
expect(suggestion).to.have.property('description');
});
});
+
+ it('should handle nested paths', () => {
+ const suggestions = getSuggestions({ fieldName: 'child', nestedPath: 'nestedField' });
+ expect(suggestions.length).to.be.greaterThan(0);
+ });
});
diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/field.js b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/field.js
index 4f62c6344e9a0..3d7e1979d224b 100644
--- a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/field.js
+++ b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/field.js
@@ -29,15 +29,28 @@ export function getSuggestionsProvider({ indexPatterns }) {
const allFields = flatten(indexPatterns.map(indexPattern => {
return indexPattern.fields.filter(isFilterable);
}));
- return function getFieldSuggestions({ start, end, prefix, suffix }) {
- const search = `${prefix}${suffix}`.toLowerCase();
- const fieldNames = allFields.map(field => field.name);
- const matchingFieldNames = fieldNames.filter(name => name.toLowerCase().includes(search));
- const sortedFieldNames = sortPrefixFirst(matchingFieldNames.sort(keywordComparator), search);
- const suggestions = sortedFieldNames.map(fieldName => {
- const text = `${escapeKuery(fieldName)} `;
- const description = getDescription(fieldName);
- return { type, text, description, start, end };
+ return function getFieldSuggestions({ start, end, prefix, suffix, nestedPath = '' }) {
+ const search = `${prefix}${suffix}`.trim().toLowerCase();
+ const matchingFields = allFields.filter(field => {
+ return (
+ !nestedPath
+ || (nestedPath && (field.subType && field.subType.nested && field.subType.nested.path.includes(nestedPath)))
+ )
+ && field.name.toLowerCase().includes(search) && field.name !== search;
+ });
+ const sortedFields = sortPrefixFirst(matchingFields.sort(keywordComparator), search, 'name');
+ const suggestions = sortedFields.map(field => {
+ const remainingPath = field.subType && field.subType.nested
+ ? field.subType.nested.path.slice(nestedPath ? nestedPath.length + 1 : 0)
+ : '';
+ const text = field.subType && field.subType.nested && remainingPath.length > 0
+ ? `${escapeKuery(remainingPath)}:{ ${escapeKuery(field.name.slice(field.subType.nested.path.length + 1))} }`
+ : `${escapeKuery(field.name.slice(nestedPath ? nestedPath.length + 1 : 0))} `;
+ const description = getDescription(field.name);
+ const cursorIndex = field.subType && field.subType.nested && remainingPath.length > 0
+ ? text.length - 2
+ : text.length;
+ return { type, text, description, start, end, cursorIndex, field };
});
return suggestions;
};
@@ -45,10 +58,10 @@ export function getSuggestionsProvider({ indexPatterns }) {
function keywordComparator(first, second) {
const extensions = ['raw', 'keyword'];
- if (extensions.map(ext => `${first}.${ext}`).includes(second)) {
+ if (extensions.map(ext => `${first.name}.${ext}`).includes(second.name)) {
return 1;
- } else if (extensions.map(ext => `${second}.${ext}`).includes(first)) {
+ } else if (extensions.map(ext => `${second.name}.${ext}`).includes(first.name)) {
return -1;
}
- return first.localeCompare(second);
+ return first.name.localeCompare(second.name);
}
diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/operator.js b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/operator.js
index a60216bd9316a..3955fdfd9afe7 100644
--- a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/operator.js
+++ b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/operator.js
@@ -123,8 +123,9 @@ export function getSuggestionsProvider({ indexPatterns }) {
const allFields = flatten(indexPatterns.map(indexPattern => {
return indexPattern.fields.slice();
}));
- return function getOperatorSuggestions({ end, fieldName }) {
- const fields = allFields.filter(field => field.name === fieldName);
+ return function getOperatorSuggestions({ end, fieldName, nestedPath }) {
+ const fullFieldName = nestedPath ? `${nestedPath}.${fieldName}` : fieldName;
+ const fields = allFields.filter(field => field.name === fullFieldName);
return flatten(fields.map(field => {
const matchingOperators = Object.keys(operators).filter(operator => {
const { fieldTypes } = operators[operator];
diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.js b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.js
index 66e62e884e9b3..52bf347a94075 100644
--- a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.js
+++ b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.js
@@ -26,9 +26,11 @@ export function getSuggestionsProvider({ indexPatterns, boolFilter }) {
prefix,
suffix,
fieldName,
+ nestedPath,
}) {
- const fields = allFields.filter(field => field.name === fieldName);
- const query = `${prefix}${suffix}`;
+ const fullFieldName = nestedPath ? `${nestedPath}.${fieldName}` : fieldName;
+ const fields = allFields.filter(field => field.name === fullFieldName);
+ const query = `${prefix}${suffix}`.trim();
const { getSuggestions } = npStart.plugins.data;
const suggestionsByField = fields.map(field => {
diff --git a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.test.js b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.test.js
index c59917ebdc3bf..591833d646360 100644
--- a/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.test.js
+++ b/x-pack/legacy/plugins/kuery_autocomplete/public/autocomplete_providers/value.test.js
@@ -19,7 +19,11 @@ jest.mock('ui/new_platform', () => ({
res = [true, false];
} else if (field.name === 'machine.os') {
res = ['Windo"ws', 'Mac\'', 'Linux'];
- } else {
+ }
+ else if (field.name === 'nestedField.child') {
+ res = ['foo'];
+ }
+ else {
res = [];
}
return Promise.resolve(res);
@@ -67,6 +71,17 @@ describe('Kuery value suggestions', function () {
expect(suggestions[0].end).toEqual(end);
});
+ test('should handle nested paths', async () => {
+ const suggestions = await getSuggestions({
+ fieldName: 'child',
+ nestedPath: 'nestedField',
+ prefix: '',
+ suffix: '',
+ });
+ expect(suggestions.length).toEqual(1);
+ expect(suggestions[0].text).toEqual('"foo" ');
+ });
+
describe('Boolean suggestions', function () {
test('should stringify boolean fields', async () => {
const fieldName = 'ssl';
diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx
index 87f0872c52343..31d622c7089a8 100644
--- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx
@@ -7,12 +7,12 @@
import React from 'react';
import { ReactWrapper } from 'enzyme';
import { act } from 'react-dom/test-utils';
-import { buildExistsFilter } from '@kbn/es-query';
import { App } from './app';
import { EditorFrameInstance } from '../types';
-import { Storage } from 'ui/storage';
+import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { Document, SavedObjectStore } from '../persistence';
import { mount } from 'enzyme';
+import { esFilters } from '../../../../../../src/plugins/data/public';
import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks';
const dataStartMock = dataPluginMock.createStartContract();
@@ -80,7 +80,7 @@ describe('Lens App', () => {
data: typeof dataStartMock;
core: typeof core;
dataShim: DataStart;
- store: Storage;
+ storage: Storage;
docId?: string;
docStorage: SavedObjectStore;
redirectTo: (id?: string) => void;
@@ -97,6 +97,11 @@ describe('Lens App', () => {
},
},
},
+ data: {
+ query: {
+ filterManager: createMockFilterManager(),
+ },
+ },
dataShim: {
indexPatterns: {
indexPatterns: {
@@ -106,11 +111,8 @@ describe('Lens App', () => {
},
},
timefilter: { history: {} },
- filter: {
- filterManager: createMockFilterManager(),
- },
},
- store: {
+ storage: {
get: jest.fn(),
},
docStorage: {
@@ -123,7 +125,7 @@ describe('Lens App', () => {
data: typeof dataStartMock;
core: typeof core;
dataShim: DataStart;
- store: Storage;
+ storage: Storage;
docId?: string;
docStorage: SavedObjectStore;
redirectTo: (id?: string) => void;
@@ -592,8 +594,8 @@ describe('Lens App', () => {
const instance = mount( );
- args.dataShim.filter.filterManager.setFilters([
- buildExistsFilter({ name: 'myfield' }, { id: 'index1' }),
+ args.data.query.filterManager.setFilters([
+ esFilters.buildExistsFilter({ name: 'myfield' }, { id: 'index1' }),
]);
instance.update();
@@ -601,7 +603,7 @@ describe('Lens App', () => {
expect(frame.mount).toHaveBeenCalledWith(
expect.any(Element),
expect.objectContaining({
- filters: [buildExistsFilter({ name: 'myfield' }, { id: 'index1' })],
+ filters: [esFilters.buildExistsFilter({ name: 'myfield' }, { id: 'index1' })],
})
);
});
@@ -723,8 +725,8 @@ describe('Lens App', () => {
query: { query: 'new', language: 'lucene' },
});
- args.dataShim.filter.filterManager.setFilters([
- buildExistsFilter({ name: 'myfield' }, { id: 'index1' }),
+ args.data.query.filterManager.setFilters([
+ esFilters.buildExistsFilter({ name: 'myfield' }, { id: 'index1' }),
]);
instance.update();
diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx
index bd75198714dc3..2815ac9ddda4e 100644
--- a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx
+++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx
@@ -8,7 +8,6 @@ import _ from 'lodash';
import React, { useState, useEffect, useCallback } from 'react';
import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
-import { Storage } from 'ui/storage';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
import { CoreStart, NotificationsStart } from 'src/core/public';
@@ -19,13 +18,14 @@ import {
SavedQuery,
Query,
} from 'src/legacy/core_plugins/data/public';
-import { Filter } from '@kbn/es-query';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { start as navigation } from '../../../../../../src/legacy/core_plugins/navigation/public/legacy';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import { Document, SavedObjectStore } from '../persistence';
import { EditorFrameInstance } from '../types';
import { NativeRenderer } from '../native_renderer';
import { trackUiEvent } from '../lens_ui_telemetry';
+import { esFilters } from '../../../../../../src/plugins/data/public';
interface State {
isLoading: boolean;
@@ -40,7 +40,7 @@ interface State {
toDate: string;
};
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
savedQuery?: SavedQuery;
}
@@ -49,7 +49,7 @@ export function App({
data,
dataShim,
core,
- store,
+ storage,
docId,
docStorage,
redirectTo,
@@ -58,14 +58,14 @@ export function App({
data: DataPublicPluginStart;
core: CoreStart;
dataShim: DataStart;
- store: Storage;
+ storage: IStorageWrapper;
docId?: string;
docStorage: SavedObjectStore;
redirectTo: (id?: string) => void;
}) {
const timeDefaults = core.uiSettings.get('timepicker:timeDefaults');
const language =
- store.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage');
+ storage.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage');
const [state, setState] = useState({
isLoading: !!docId,
@@ -82,10 +82,9 @@ export function App({
const { lastKnownDoc } = state;
useEffect(() => {
- const subscription = dataShim.filter.filterManager.getUpdates$().subscribe({
+ const subscription = data.query.filterManager.getUpdates$().subscribe({
next: () => {
- setState(s => ({ ...s, filters: dataShim.filter.filterManager.getFilters() }));
-
+ setState(s => ({ ...s, filters: data.query.filterManager.getFilters() }));
trackUiEvent('app_filters_updated');
},
});
@@ -171,7 +170,7 @@ export function App({
services={{
appName: 'lens',
data,
- store,
+ storage,
...core,
}}
>
@@ -227,9 +226,7 @@ export function App({
setState(s => ({ ...s, savedQuery }));
}}
onSavedQueryUpdated={savedQuery => {
- dataShim.filter.filterManager.setFilters(
- savedQuery.attributes.filters || state.filters
- );
+ data.query.filterManager.setFilters(savedQuery.attributes.filters || state.filters);
setState(s => ({
...s,
savedQuery: { ...savedQuery }, // Shallow query for reference issues
@@ -242,7 +239,7 @@ export function App({
}));
}}
onClearSavedQuery={() => {
- dataShim.filter.filterManager.removeAll();
+ data.query.filterManager.removeAll();
setState(s => ({
...s,
savedQuery: undefined,
@@ -250,7 +247,7 @@ export function App({
query: {
query: '',
language:
- store.get('kibana.userQueryLanguage') ||
+ storage.get('kibana.userQueryLanguage') ||
core.uiSettings.get('search:queryLanguage'),
},
}));
diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx
index b7960b23651c6..56c19ea2bb9f2 100644
--- a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx
+++ b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx
@@ -8,12 +8,12 @@ import React from 'react';
import { I18nProvider, FormattedMessage } from '@kbn/i18n/react';
import { HashRouter, Switch, Route, RouteComponentProps } from 'react-router-dom';
import chrome from 'ui/chrome';
-import { Storage } from 'ui/storage';
import { CoreSetup, CoreStart } from 'src/core/public';
import { npSetup, npStart } from 'ui/new_platform';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { DataStart } from '../../../../../../src/legacy/core_plugins/data/public';
import { start as dataShimStart } from '../../../../../../src/legacy/core_plugins/data/public/legacy';
+import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { editorFrameSetup, editorFrameStart, editorFrameStop } from '../editor_frame_plugin';
import { indexPatternDatasourceSetup, indexPatternDatasourceStop } from '../indexpattern_plugin';
import { SavedObjectIndexStore } from '../persistence';
@@ -84,7 +84,7 @@ export class AppPlugin {
data={data}
dataShim={dataShim}
editorFrame={this.instance!}
- store={new Storage(localStorage)}
+ storage={new Storage(localStorage)}
docId={routeProps.match.params.id}
docStorage={store}
redirectTo={id => {
diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/expression.tsx b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/expression.tsx
index e350e36b3bdc0..30c955d45289b 100644
--- a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/expression.tsx
+++ b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/expression.tsx
@@ -8,7 +8,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { i18n } from '@kbn/i18n';
import { EuiBasicTable } from '@elastic/eui';
-import { ExpressionFunction } from '../../../../../../src/plugins/expressions/common';
+import { ExpressionFunction } from '../../../../../../src/plugins/expressions/public';
import { KibanaDatatable } from '../../../../../../src/legacy/core_plugins/interpreter/public';
import { LensMultiTable } from '../types';
import {
diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.test.tsx b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.test.tsx
index 083ceff3bb444..25d88fbae5b34 100644
--- a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.test.tsx
@@ -12,7 +12,7 @@ import {
DataTableLayer,
} from './visualization';
import { mount } from 'enzyme';
-import { Operation, DataType, FramePublicAPI } from '../types';
+import { Operation, DataType, FramePublicAPI, TableSuggestionColumn } from '../types';
import { generateId } from '../id_generator';
jest.mock('../id_generator');
@@ -72,6 +72,112 @@ describe('Datatable Visualization', () => {
});
});
+ describe('#getSuggestions', () => {
+ function numCol(columnId: string): TableSuggestionColumn {
+ return {
+ columnId,
+ operation: {
+ dataType: 'number',
+ label: `Avg ${columnId}`,
+ isBucketed: false,
+ },
+ };
+ }
+
+ function strCol(columnId: string): TableSuggestionColumn {
+ return {
+ columnId,
+ operation: {
+ dataType: 'string',
+ label: `Top 5 ${columnId}`,
+ isBucketed: true,
+ },
+ };
+ }
+
+ it('should accept a single-layer suggestion', () => {
+ const suggestions = datatableVisualization.getSuggestions({
+ state: {
+ layers: [{ layerId: 'first', columns: ['col1'] }],
+ },
+ table: {
+ isMultiRow: true,
+ layerId: 'first',
+ changeType: 'initial',
+ columns: [numCol('col1'), strCol('col2')],
+ },
+ keptLayerIds: [],
+ });
+
+ expect(suggestions.length).toBeGreaterThan(0);
+ });
+
+ it('should not make suggestions when the table is unchanged', () => {
+ const suggestions = datatableVisualization.getSuggestions({
+ state: {
+ layers: [{ layerId: 'first', columns: ['col1'] }],
+ },
+ table: {
+ isMultiRow: true,
+ layerId: 'first',
+ changeType: 'unchanged',
+ columns: [numCol('col1')],
+ },
+ keptLayerIds: ['first'],
+ });
+
+ expect(suggestions).toEqual([]);
+ });
+
+ it('should not make suggestions when multiple layers are involved', () => {
+ const suggestions = datatableVisualization.getSuggestions({
+ state: {
+ layers: [{ layerId: 'first', columns: ['col1'] }],
+ },
+ table: {
+ isMultiRow: true,
+ layerId: 'first',
+ changeType: 'unchanged',
+ columns: [numCol('col1')],
+ },
+ keptLayerIds: ['first', 'second'],
+ });
+
+ expect(suggestions).toEqual([]);
+ });
+
+ it('should not make suggestions when the suggestion keeps a different layer', () => {
+ const suggestions = datatableVisualization.getSuggestions({
+ state: {
+ layers: [{ layerId: 'older', columns: ['col1'] }],
+ },
+ table: {
+ isMultiRow: true,
+ layerId: 'newer',
+ changeType: 'initial',
+ columns: [numCol('col1'), strCol('col2')],
+ },
+ keptLayerIds: ['older'],
+ });
+
+ expect(suggestions).toEqual([]);
+ });
+
+ it('should suggest unchanged tables when the state is not passed in', () => {
+ const suggestions = datatableVisualization.getSuggestions({
+ table: {
+ isMultiRow: true,
+ layerId: 'first',
+ changeType: 'unchanged',
+ columns: [numCol('col1')],
+ },
+ keptLayerIds: ['first'],
+ });
+
+ expect(suggestions.length).toBeGreaterThan(0);
+ });
+ });
+
describe('DataTableLayer', () => {
it('allows all kinds of operations', () => {
const setState = jest.fn();
diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.tsx b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.tsx
index 65f97b6d4e4b5..f9a7ec419a9b9 100644
--- a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.tsx
+++ b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.tsx
@@ -134,10 +134,15 @@ export const datatableVisualization: Visualization<
getSuggestions({
table,
state,
+ keptLayerIds,
}: SuggestionRequest): Array<
VisualizationSuggestion
> {
- if (state && table.changeType === 'unchanged') {
+ if (
+ keptLayerIds.length > 1 ||
+ (keptLayerIds.length && table.layerId !== keptLayerIds[0]) ||
+ (state && table.changeType === 'unchanged')
+ ) {
return [];
}
const title =
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.test.tsx
index 298b25b5090c4..1b60098fd45ad 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.test.tsx
@@ -94,6 +94,7 @@ describe('chart_switch', () => {
layerId: 'a',
changeType: 'unchanged',
},
+ keptLayerIds: ['a'],
},
]);
return {
@@ -180,6 +181,8 @@ describe('chart_switch', () => {
switchTo('subvisB', component);
+ expect(frame.removeLayers).toHaveBeenCalledWith(['a']);
+
expect(dispatch).toHaveBeenCalledWith({
initialState: 'visB initial state',
newVisualizationId: 'visB',
@@ -219,6 +222,7 @@ describe('chart_switch', () => {
isMultiRow: true,
changeType: 'unchanged',
},
+ keptLayerIds: [],
},
]);
datasourceMap.testDatasource.publicAPIMock.getTableSpec.mockReturnValue([
@@ -307,11 +311,7 @@ describe('chart_switch', () => {
it('should not indicate data loss if visualization is not changed', () => {
const dispatch = jest.fn();
- const removeLayers = jest.fn();
- const frame = {
- ...mockFrame(['a', 'b', 'c']),
- removeLayers,
- };
+ const frame = mockFrame(['a', 'b', 'c']);
const visualizations = mockVisualizations();
const switchVisualizationType = jest.fn(() => 'therebedragons');
@@ -332,30 +332,6 @@ describe('chart_switch', () => {
expect(getMenuItem('subvisC2', component).prop('betaBadgeIconType')).toBeUndefined();
});
- it('should remove unused layers', () => {
- const removeLayers = jest.fn();
- const frame = {
- ...mockFrame(['a', 'b', 'c']),
- removeLayers,
- };
- const component = mount(
-
- );
-
- switchTo('subvisB', component);
-
- expect(removeLayers).toHaveBeenCalledTimes(1);
- expect(removeLayers).toHaveBeenCalledWith(['b', 'c']);
- });
-
it('should remove all layers if there is no suggestion', () => {
const dispatch = jest.fn();
const visualizations = mockVisualizations();
@@ -378,15 +354,24 @@ describe('chart_switch', () => {
expect(frame.removeLayers).toHaveBeenCalledTimes(1);
expect(frame.removeLayers).toHaveBeenCalledWith(['a', 'b', 'c']);
+
+ expect(visualizations.visB.getSuggestions).toHaveBeenCalledWith(
+ expect.objectContaining({
+ keptLayerIds: ['a'],
+ })
+ );
+
+ expect(dispatch).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: 'SWITCH_VISUALIZATION',
+ initialState: 'visB initial state',
+ })
+ );
});
- it('should not remove layers if the visualization is not changing', () => {
+ it('should not remove layers when switching between subtypes', () => {
const dispatch = jest.fn();
- const removeLayers = jest.fn();
- const frame = {
- ...mockFrame(['a', 'b', 'c']),
- removeLayers,
- };
+ const frame = mockFrame(['a', 'b', 'c']);
const visualizations = mockVisualizations();
const switchVisualizationType = jest.fn(() => 'therebedragons');
@@ -405,7 +390,6 @@ describe('chart_switch', () => {
);
switchTo('subvisC2', component);
- expect(removeLayers).not.toHaveBeenCalled();
expect(switchVisualizationType).toHaveBeenCalledWith('subvisC2', 'therebegriffins');
expect(dispatch).toHaveBeenCalledWith(
expect.objectContaining({
@@ -413,6 +397,7 @@ describe('chart_switch', () => {
initialState: 'therebedragons',
})
);
+ expect(frame.removeLayers).not.toHaveBeenCalled();
});
it('should switch to the updated datasource state', () => {
@@ -447,6 +432,7 @@ describe('chart_switch', () => {
isMultiRow: true,
changeType: 'unchanged',
},
+ keptLayerIds: [],
},
]);
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx
index 2e95aa10bf4db..dca6b3e7616d6 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx
@@ -28,6 +28,7 @@ interface VisualizationSelection {
dataLoss: 'nothing' | 'layers' | 'everything' | 'columns';
datasourceId?: string;
datasourceState?: unknown;
+ sameDatasources?: boolean;
}
interface Props {
@@ -88,6 +89,13 @@ export function ChartSwitch(props: Props) {
},
'SWITCH_VISUALIZATION'
);
+
+ if (
+ (!selection.datasourceId && !selection.sameDatasources) ||
+ selection.dataLoss === 'everything'
+ ) {
+ props.framePublicAPI.removeLayers(Object.keys(props.framePublicAPI.datasourceLayers));
+ }
};
function getSelection(
@@ -105,6 +113,7 @@ export function ChartSwitch(props: Props) {
dataLoss: 'nothing',
keptLayerIds: Object.keys(props.framePublicAPI.datasourceLayers),
getVisualizationState: () => switchVisType(subVisualizationId, props.visualizationState),
+ sameDatasources: true,
};
}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/data_panel_wrapper.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/data_panel_wrapper.tsx
index 115e8cbf002c3..a5509cdc94559 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/data_panel_wrapper.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/data_panel_wrapper.tsx
@@ -6,7 +6,6 @@
import React, { useMemo, memo, useContext, useState } from 'react';
import { i18n } from '@kbn/i18n';
-import { Filter } from '@kbn/es-query';
import { EuiPopover, EuiButtonIcon, EuiContextMenuPanel, EuiContextMenuItem } from '@elastic/eui';
import { Query } from 'src/plugins/data/common';
import { DatasourceDataPanelProps, Datasource } from '../../../public';
@@ -14,6 +13,7 @@ import { NativeRenderer } from '../../native_renderer';
import { Action } from './state_management';
import { DragContext } from '../../drag_drop';
import { StateSetter, FramePublicAPI } from '../../types';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
interface DataPanelWrapperProps {
datasourceState: unknown;
@@ -24,7 +24,7 @@ interface DataPanelWrapperProps {
core: DatasourceDataPanelProps['core'];
query: Query;
dateRange: FramePublicAPI['dateRange'];
- filters: Filter[];
+ filters: esFilters.Filter[];
}
export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => {
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
index fb3f8774be92a..1e8f50f4ddb1f 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
@@ -35,6 +35,7 @@ function generateSuggestion(state = {}): DatasourceSuggestion {
layerId: 'first',
changeType: 'unchanged',
},
+ keptLayerIds: ['first'],
};
}
@@ -807,30 +808,38 @@ describe('editor_frame', () => {
await waitForPromises();
expect(mockDatasource.getPublicAPI).toHaveBeenCalledWith(
- datasource1State,
- expect.anything(),
- 'first'
+ expect.objectContaining({
+ state: datasource1State,
+ setState: expect.anything(),
+ layerId: 'first',
+ })
);
expect(mockDatasource2.getPublicAPI).toHaveBeenCalledWith(
- datasource2State,
- expect.anything(),
- 'second'
+ expect.objectContaining({
+ state: datasource2State,
+ setState: expect.anything(),
+ layerId: 'second',
+ })
);
expect(mockDatasource2.getPublicAPI).toHaveBeenCalledWith(
- datasource2State,
- expect.anything(),
- 'third'
+ expect.objectContaining({
+ state: datasource2State,
+ setState: expect.anything(),
+ layerId: 'third',
+ })
);
});
it('should give access to the datasource state in the datasource factory function', async () => {
const datasourceState = {};
+ const dateRange = { fromDate: 'now-1w', toDate: 'now' };
mockDatasource.initialize.mockResolvedValue(datasourceState);
mockDatasource.getLayers.mockReturnValue(['first']);
mount(
{
await waitForPromises();
- expect(mockDatasource.getPublicAPI).toHaveBeenCalledWith(
- datasourceState,
- expect.any(Function),
- 'first'
- );
+ expect(mockDatasource.getPublicAPI).toHaveBeenCalledWith({
+ dateRange,
+ state: datasourceState,
+ setState: expect.any(Function),
+ layerId: 'first',
+ });
});
it('should re-create the public api after state has been set', async () => {
@@ -872,15 +882,17 @@ describe('editor_frame', () => {
await waitForPromises();
const updatedState = {};
- const setDatasourceState = mockDatasource.getPublicAPI.mock.calls[0][1];
+ const setDatasourceState = mockDatasource.getPublicAPI.mock.calls[0][0].setState;
act(() => {
setDatasourceState(updatedState);
});
expect(mockDatasource.getPublicAPI).toHaveBeenLastCalledWith(
- updatedState,
- expect.any(Function),
- 'first'
+ expect.objectContaining({
+ state: updatedState,
+ setState: expect.any(Function),
+ layerId: 'first',
+ })
);
});
});
@@ -917,6 +929,7 @@ describe('editor_frame', () => {
layerId: 'first',
changeType: 'unchanged',
},
+ keptLayerIds: [],
},
]);
@@ -1062,6 +1075,7 @@ describe('editor_frame', () => {
isMultiRow: true,
layerId: 'first',
},
+ keptLayerIds: [],
},
]);
mount(
@@ -1509,7 +1523,7 @@ describe('editor_frame', () => {
query: { query: '', language: 'lucene' },
filters: [],
},
- title: 'New visualization',
+ title: '',
type: 'lens',
visualizationType: 'testVis',
},
@@ -1528,7 +1542,7 @@ describe('editor_frame', () => {
query: { query: '', language: 'lucene' },
filters: [],
},
- title: 'New visualization',
+ title: '',
type: 'lens',
visualizationType: 'testVis',
},
@@ -1585,7 +1599,7 @@ describe('editor_frame', () => {
query: { query: 'new query', language: 'lucene' },
filters: [],
},
- title: 'New visualization',
+ title: '',
type: 'lens',
visualizationType: 'testVis',
},
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx
index 04c0b22c378d7..6d782d119525d 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx
@@ -6,7 +6,6 @@
import React, { useEffect, useReducer } from 'react';
import { CoreSetup, CoreStart } from 'src/core/public';
-import { Filter } from '@kbn/es-query';
import { Query, SavedQuery } from '../../../../../../../src/legacy/core_plugins/data/public';
import { ExpressionRenderer } from '../../../../../../../src/legacy/core_plugins/expressions/public';
import {
@@ -26,6 +25,7 @@ import { Document } from '../../persistence/saved_object_store';
import { getSavedObjectFormat } from './save';
import { WorkspacePanelWrapper } from './workspace_panel_wrapper';
import { generateId } from '../../id_generator';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
export interface EditorFrameProps {
doc?: Document;
@@ -41,7 +41,7 @@ export interface EditorFrameProps {
toDate: string;
};
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
savedQuery?: SavedQuery;
onChange: (arg: {
filterableIndexPatterns: DatasourceMetaData['filterableIndexPatterns'];
@@ -89,9 +89,9 @@ export function EditorFrame(props: EditorFrameProps) {
const layers = datasource.getLayers(datasourceState);
layers.forEach(layer => {
- const publicAPI = props.datasourceMap[id].getPublicAPI(
- datasourceState,
- (newState: unknown) => {
+ const publicAPI = props.datasourceMap[id].getPublicAPI({
+ state: datasourceState,
+ setState: (newState: unknown) => {
dispatch({
type: 'UPDATE_DATASOURCE_STATE',
datasourceId: id,
@@ -99,8 +99,9 @@ export function EditorFrame(props: EditorFrameProps) {
clearStagedPreview: true,
});
},
- layer
- );
+ layerId: layer,
+ dateRange: props.dateRange,
+ });
datasourceLayers[layer] = publicAPI;
});
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/expression_helpers.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/expression_helpers.ts
index 1ddfc54cc187b..f03b64295641b 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/expression_helpers.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/expression_helpers.ts
@@ -6,9 +6,9 @@
import { TimeRange } from 'src/plugins/data/public';
import { Query } from 'src/legacy/core_plugins/data/public';
-import { Filter } from '@kbn/es-query';
import { Ast, fromExpression, ExpressionFunctionAST } from '@kbn/interpreter/common';
import { Visualization, Datasource, FramePublicAPI } from '../../types';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
export function prependDatasourceExpression(
visualizationExpression: Ast | string | null,
@@ -71,7 +71,7 @@ export function prependKibanaContext(
}: {
timeRange?: TimeRange;
query?: Query;
- filters?: Filter[];
+ filters?: esFilters.Filter[];
}
): Ast {
const parsedExpression = typeof expression === 'string' ? fromExpression(expression) : expression;
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/save.test.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/save.test.ts
index ef8194aa6f924..f223a9c06a2a7 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/save.test.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/save.test.ts
@@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { buildExistsFilter } from '@kbn/es-query';
import { getSavedObjectFormat, Props } from './save';
import { createMockDatasource, createMockVisualization } from '../mocks';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
describe('save editor frame state', () => {
const mockVisualization = createMockVisualization();
@@ -37,7 +37,7 @@ describe('save editor frame state', () => {
},
query: { query: '', language: 'lucene' },
dateRange: { fromDate: 'now-7d', toDate: 'now' },
- filters: [buildExistsFilter({ name: '@timestamp' }, { id: 'indexpattern' })],
+ filters: [esFilters.buildExistsFilter({ name: '@timestamp' }, { id: 'indexpattern' })],
},
};
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts
index 5104ace7c79a3..78a9a13f48d6a 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { i18n } from '@kbn/i18n';
import { EditorFrameProps } from '../editor_frame';
import { Document } from '../../persistence/saved_object_store';
@@ -113,7 +112,7 @@ export const getInitialState = (props: EditorFrameProps): EditorFrameState => {
}
return {
- title: i18n.translate('xpack.lens.chartTitle', { defaultMessage: 'New visualization' }),
+ title: '',
datasourceStates,
activeDatasourceId: getInitialDatasourceId(props),
visualization: {
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.test.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.test.ts
index 7b3e4454a5e39..487a91c22b5d5 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.test.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.test.ts
@@ -16,6 +16,7 @@ const generateSuggestion = (state = {}, layerId: string = 'first'): DatasourceSu
layerId,
changeType: 'unchanged',
},
+ keptLayerIds: [layerId],
});
let datasourceMap: Record;
@@ -235,8 +236,8 @@ describe('suggestion helpers', () => {
changeType: 'unchanged',
};
datasourceMap.mock.getDatasourceSuggestionsFromCurrentState.mockReturnValue([
- { state: {}, table: table1 },
- { state: {}, table: table2 },
+ { state: {}, table: table1, keptLayerIds: ['first'] },
+ { state: {}, table: table2, keptLayerIds: ['first'] },
]);
getSuggestions({
visualizationMap: {
@@ -343,45 +344,4 @@ describe('suggestion helpers', () => {
})
);
});
-
- it('should drop other layers only on visualization switch', () => {
- const mockVisualization1 = createMockVisualization();
- const mockVisualization2 = createMockVisualization();
- datasourceMap.mock.getDatasourceSuggestionsFromCurrentState.mockReturnValue([
- generateSuggestion(),
- ]);
- datasourceMap.mock.getLayers.mockReturnValue(['first', 'second']);
- const suggestions = getSuggestions({
- visualizationMap: {
- vis1: {
- ...mockVisualization1,
- getSuggestions: () => [
- {
- score: 0.8,
- title: 'Test2',
- state: {},
- previewIcon: 'empty',
- },
- ],
- },
- vis2: {
- ...mockVisualization2,
- getSuggestions: () => [
- {
- score: 0.6,
- title: 'Test3',
- state: {},
- previewIcon: 'empty',
- },
- ],
- },
- },
- activeVisualizationId: 'vis1',
- visualizationState: {},
- datasourceMap,
- datasourceStates,
- });
- expect(suggestions[0].keptLayerIds).toEqual(['first', 'second']);
- expect(suggestions[1].keptLayerIds).toEqual(['first']);
- });
});
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.ts
index d3e768a1932dc..173f64c6292a8 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.ts
@@ -13,6 +13,7 @@ import {
FramePublicAPI,
TableChangeType,
TableSuggestion,
+ DatasourceSuggestion,
} from '../../types';
import { Action } from './state_management';
@@ -20,7 +21,6 @@ export interface Suggestion {
visualizationId: string;
datasourceState?: unknown;
datasourceId?: string;
- keptLayerIds: string[];
columns: number;
score: number;
title: string;
@@ -29,6 +29,7 @@ export interface Suggestion {
previewIcon: IconType;
hide?: boolean;
changeType: TableChangeType;
+ keptLayerIds: string[];
}
/**
@@ -64,12 +65,6 @@ export function getSuggestions({
([datasourceId]) => datasourceStates[datasourceId] && !datasourceStates[datasourceId].isLoading
);
- const allLayerIds = _.flatten(
- datasources.map(([datasourceId, datasource]) =>
- datasource.getLayers(datasourceStates[datasourceId].state)
- )
- );
-
// Collect all table suggestions from available datasources
const datasourceTableSuggestions = _.flatten(
datasources.map(([datasourceId, datasource]) => {
@@ -90,17 +85,12 @@ export function getSuggestions({
const table = datasourceSuggestion.table;
const currentVisualizationState =
visualizationId === activeVisualizationId ? visualizationState : undefined;
- const keptLayerIds =
- visualizationId !== activeVisualizationId
- ? [datasourceSuggestion.table.layerId]
- : allLayerIds;
return getVisualizationSuggestions(
visualization,
table,
visualizationId,
datasourceSuggestion,
- currentVisualizationState,
- keptLayerIds
+ currentVisualizationState
);
})
)
@@ -118,20 +108,20 @@ function getVisualizationSuggestions(
visualization: Visualization,
table: TableSuggestion,
visualizationId: string,
- datasourceSuggestion: { datasourceId: string; state: unknown; table: TableSuggestion },
- currentVisualizationState: unknown,
- keptLayerIds: string[]
+ datasourceSuggestion: DatasourceSuggestion & { datasourceId: string },
+ currentVisualizationState: unknown
) {
return visualization
.getSuggestions({
table,
state: currentVisualizationState,
+ keptLayerIds: datasourceSuggestion.keptLayerIds,
})
.map(({ state, ...visualizationSuggestion }) => ({
...visualizationSuggestion,
visualizationId,
visualizationState: state,
- keptLayerIds,
+ keptLayerIds: datasourceSuggestion.keptLayerIds,
datasourceState: datasourceSuggestion.state,
datasourceId: datasourceSuggestion.datasourceId,
columns: table.columns.length,
@@ -144,7 +134,7 @@ export function switchToSuggestion(
dispatch: (action: Action) => void,
suggestion: Pick<
Suggestion,
- 'visualizationId' | 'visualizationState' | 'datasourceState' | 'datasourceId' | 'keptLayerIds'
+ 'visualizationId' | 'visualizationState' | 'datasourceState' | 'datasourceId'
>,
type: 'SWITCH_VISUALIZATION' | 'SELECT_SUGGESTION' = 'SELECT_SUGGESTION'
) {
@@ -156,10 +146,4 @@ export function switchToSuggestion(
datasourceId: suggestion.datasourceId!,
};
dispatch(action);
- const layerIds = Object.keys(frame.datasourceLayers).filter(id => {
- return !suggestion.keptLayerIds.includes(id);
- });
- if (layerIds.length > 0) {
- frame.removeLayers(layerIds);
- }
}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx
index 8840f7dfd3b78..e32fe5f1f866d 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx
@@ -218,36 +218,6 @@ describe('suggestion_panel', () => {
);
});
- it('should remove unused layers if suggestion is clicked', () => {
- defaultProps.frame.datasourceLayers.a = mockDatasource.publicAPIMock;
- defaultProps.frame.datasourceLayers.b = mockDatasource.publicAPIMock;
- const wrapper = mount(
-
- );
-
- act(() => {
- wrapper
- .find('button[data-test-subj="lnsSuggestion"]')
- .at(1)
- .simulate('click');
- });
-
- wrapper.update();
-
- act(() => {
- wrapper
- .find('[data-test-subj="lensSubmitSuggestion"]')
- .first()
- .simulate('click');
- });
-
- expect(defaultProps.frame.removeLayers).toHaveBeenCalledWith(['b']);
- });
-
it('should render preview expression if there is one', () => {
mockDatasource.getLayers.mockReturnValue(['first']);
(getSuggestions as jest.Mock).mockReturnValue([
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
index 6aee215d11591..e29ac84486d0b 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
@@ -367,7 +367,12 @@ function getPreviewExpression(
const changedLayers = datasource.getLayers(visualizableState.datasourceState);
changedLayers.forEach(layerId => {
if (updatedLayerApis[layerId]) {
- updatedLayerApis[layerId] = datasource.getPublicAPI(datasourceState, () => {}, layerId);
+ updatedLayerApis[layerId] = datasource.getPublicAPI({
+ layerId,
+ dateRange: frame.dateRange,
+ state: datasourceState,
+ setState: () => {},
+ });
}
});
}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx
index 9cf59f69c0cc2..fd35ecd702d23 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx
@@ -5,8 +5,6 @@
*/
import React from 'react';
-
-import { buildExistsFilter } from '@kbn/es-query';
import { ExpressionRendererProps } from '../../../../../../../src/legacy/core_plugins/expressions/public';
import { Visualization, FramePublicAPI, TableSuggestion } from '../../types';
import {
@@ -22,6 +20,7 @@ import { ReactWrapper } from 'enzyme';
import { DragDrop, ChildDragDropProvider } from '../../drag_drop';
import { Ast } from '@kbn/interpreter/common';
import { coreMock } from 'src/core/public/mocks';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
const waitForPromises = () => new Promise(resolve => setTimeout(resolve));
@@ -382,7 +381,7 @@ describe('workspace_panel', () => {
instance.setProps({
framePublicAPI: {
...framePublicAPI,
- filters: [buildExistsFilter({ name: 'myfield' }, { id: 'index1' })],
+ filters: [esFilters.buildExistsFilter({ name: 'myfield' }, { id: 'index1' })],
},
});
@@ -574,6 +573,7 @@ describe('workspace_panel', () => {
{
state: {},
table: expectedTable,
+ keptLayerIds: [],
},
]);
mockVisualization.getSuggestions.mockReturnValueOnce([
@@ -613,6 +613,7 @@ describe('workspace_panel', () => {
columns: [],
changeType: 'unchanged',
},
+ keptLayerIds: [],
},
]);
mockVisualization.getSuggestions.mockReturnValueOnce([
@@ -639,6 +640,7 @@ describe('workspace_panel', () => {
columns: [],
changeType: 'unchanged',
},
+ keptLayerIds: [],
},
]);
mockVisualization2.getSuggestions.mockReturnValueOnce([
@@ -665,6 +667,7 @@ describe('workspace_panel', () => {
columns: [],
changeType: 'unchanged',
},
+ keptLayerIds: [],
},
]);
mockVisualization.getSuggestions.mockReturnValueOnce([
@@ -694,6 +697,7 @@ describe('workspace_panel', () => {
layerId: '1',
changeType: 'unchanged',
},
+ keptLayerIds: [],
},
{
state: {},
@@ -703,6 +707,7 @@ describe('workspace_panel', () => {
layerId: '1',
changeType: 'unchanged',
},
+ keptLayerIds: [],
},
]);
mockVisualization.getSuggestions.mockReturnValueOnce([
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel_wrapper.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel_wrapper.tsx
index 18d5feac4edbe..cc91510146f35 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel_wrapper.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel_wrapper.tsx
@@ -15,9 +15,11 @@ interface Props {
export function WorkspacePanelWrapper({ children, title }: Props) {
return (
-
- {title}
-
+ {title && (
+
+ {title}
+
+ )}
{children}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.test.tsx
index d728457b7e3a3..95d39409c57de 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.test.tsx
@@ -5,10 +5,9 @@
*/
import { Embeddable } from './embeddable';
-import { TimeRange } from 'src/plugins/data/public';
+import { TimeRange, esFilters } from 'src/plugins/data/public';
import { Query } from 'src/legacy/core_plugins/data/public';
import { ExpressionRendererProps } from 'src/legacy/core_plugins/expressions/public';
-import { Filter } from '@kbn/es-query';
import { Document } from '../../persistence';
jest.mock('../../../../../../../src/legacy/ui/public/inspector', () => ({
@@ -63,7 +62,9 @@ describe('embeddable', () => {
it('should re-render if new input is pushed', () => {
const timeRange: TimeRange = { from: 'now-15d', to: 'now' };
const query: Query = { language: 'kquery', query: '' };
- const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: false } }];
+ const filters: esFilters.Filter[] = [
+ { meta: { alias: 'test', negate: false, disabled: false } },
+ ];
const embeddable = new Embeddable(
expressionRenderer,
@@ -88,7 +89,9 @@ describe('embeddable', () => {
it('should pass context to embeddable', () => {
const timeRange: TimeRange = { from: 'now-15d', to: 'now' };
const query: Query = { language: 'kquery', query: '' };
- const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: false } }];
+ const filters: esFilters.Filter[] = [
+ { meta: { alias: 'test', negate: false, disabled: false } },
+ ];
const embeddable = new Embeddable(
expressionRenderer,
@@ -112,7 +115,9 @@ describe('embeddable', () => {
it('should not re-render if only change is in disabled filter', () => {
const timeRange: TimeRange = { from: 'now-15d', to: 'now' };
const query: Query = { language: 'kquery', query: '' };
- const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: true } }];
+ const filters: esFilters.Filter[] = [
+ { meta: { alias: 'test', negate: false, disabled: true } },
+ ];
const embeddable = new Embeddable(
expressionRenderer,
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.tsx
index e815a1951bdb7..0b5d4909c8e73 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.tsx
@@ -8,10 +8,9 @@ import _ from 'lodash';
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
-import { TimeRange } from 'src/plugins/data/public';
+import { TimeRange, esFilters } from 'src/plugins/data/public';
import { Query, StaticIndexPattern } from 'src/legacy/core_plugins/data/public';
import { ExpressionRenderer } from 'src/legacy/core_plugins/expressions/public';
-import { Filter } from '@kbn/es-query';
import { Subscription } from 'rxjs';
import {
Embeddable as AbstractEmbeddable,
@@ -32,7 +31,7 @@ export interface LensEmbeddableConfiguration {
export interface LensEmbeddableInput extends EmbeddableInput {
timeRange?: TimeRange;
query?: Query;
- filters?: Filter[];
+ filters?: esFilters.Filter[];
}
export interface LensEmbeddableOutput extends EmbeddableOutput {
@@ -50,7 +49,7 @@ export class Embeddable extends AbstractEmbeddable []),
getDatasourceSuggestionsFromCurrentState: jest.fn(_state => []),
getPersistableState: jest.fn(),
- getPublicAPI: jest.fn((_state, _setState, _layerId) => publicAPIMock),
+ getPublicAPI: jest.fn().mockReturnValue(publicAPIMock),
initialize: jest.fn((_state?) => Promise.resolve()),
renderDataPanel: jest.fn(),
toExpression: jest.fn((_frame, _state) => null),
diff --git a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx b/x-pack/legacy/plugins/lens/public/help_menu_util.tsx
index 3865f08862e1c..30a05dbc38537 100644
--- a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx
+++ b/x-pack/legacy/plugins/lens/public/help_menu_util.tsx
@@ -12,7 +12,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { render, unmountComponentAtNode } from 'react-dom';
import { Chrome } from 'ui/chrome';
-const docsPage = undefined;
+const docsPage = 'lens';
export function addHelpMenuToAppChrome(chrome: Chrome) {
chrome.helpExtension.set(domElement => {
@@ -47,7 +47,7 @@ function HelpMenu() {
-
+
{i18n.translate('xpack.lens.helpMenu.feedbackLinkText', {
defaultMessage: 'Provide feedback for the Lens application',
})}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.test.ts
new file mode 100644
index 0000000000000..8146bc39ef82e
--- /dev/null
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.test.ts
@@ -0,0 +1,76 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { autoDate } from './auto_date';
+
+jest.mock('ui/new_platform');
+jest.mock('ui/chrome');
+
+describe('auto_date', () => {
+ it('should do nothing if no time range is provided', () => {
+ const result = autoDate.fn(
+ {
+ type: 'kibana_context',
+ },
+ {
+ aggConfigs: 'canttouchthis',
+ },
+ {}
+ );
+
+ expect(result).toEqual('canttouchthis');
+ });
+
+ it('should not change anything if there are no auto date histograms', () => {
+ const aggConfigs = JSON.stringify([
+ { type: 'date_histogram', params: { interval: '35h' } },
+ { type: 'count' },
+ ]);
+ const result = autoDate.fn(
+ {
+ timeRange: {
+ from: 'now-10d',
+ to: 'now',
+ },
+ type: 'kibana_context',
+ },
+ {
+ aggConfigs,
+ },
+ {}
+ );
+
+ expect(result).toEqual(aggConfigs);
+ });
+
+ it('should change auto date histograms', () => {
+ const aggConfigs = JSON.stringify([
+ { type: 'date_histogram', params: { interval: 'auto' } },
+ { type: 'count' },
+ ]);
+ const result = autoDate.fn(
+ {
+ timeRange: {
+ from: 'now-10d',
+ to: 'now',
+ },
+ type: 'kibana_context',
+ },
+ {
+ aggConfigs,
+ },
+ {}
+ );
+
+ const interval = JSON.parse(result).find(
+ (agg: { type: string }) => agg.type === 'date_histogram'
+ ).params.interval;
+
+ expect(interval).toBeTruthy();
+ expect(typeof interval).toEqual('string');
+ expect(interval).not.toEqual('auto');
+ });
+});
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.ts
index 359c6d7c35c3a..dec0adba98103 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.ts
@@ -9,26 +9,39 @@ import dateMath from '@elastic/datemath';
import {
ExpressionFunction,
KibanaContext,
-} from '../../../../../../src/plugins/expressions/common';
+} from '../../../../../../src/plugins/expressions/public';
+import { DateRange } from '../../common';
interface LensAutoDateProps {
aggConfigs: string;
}
-export function getAutoInterval(ctx?: KibanaContext | null) {
- if (!ctx || !ctx.timeRange) {
- return;
+export function autoIntervalFromDateRange(dateRange?: DateRange, defaultValue: string = '1h') {
+ if (!dateRange) {
+ return defaultValue;
}
- const { timeRange } = ctx;
const buckets = new TimeBuckets();
buckets.setInterval('auto');
buckets.setBounds({
- min: dateMath.parse(timeRange.from),
- max: dateMath.parse(timeRange.to, { roundUp: true }),
+ min: dateMath.parse(dateRange.fromDate),
+ max: dateMath.parse(dateRange.toDate, { roundUp: true }),
});
- return buckets.getInterval();
+ return buckets.getInterval().expression;
+}
+
+function autoIntervalFromContext(ctx?: KibanaContext | null) {
+ if (!ctx || !ctx.timeRange) {
+ return;
+ }
+
+ const { timeRange } = ctx;
+
+ return autoIntervalFromDateRange({
+ fromDate: timeRange.from,
+ toDate: timeRange.to,
+ });
}
/**
@@ -56,7 +69,7 @@ export const autoDate: ExpressionFunction<
},
},
fn(ctx: KibanaContext, args: LensAutoDateProps) {
- const interval = getAutoInterval(ctx);
+ const interval = autoIntervalFromContext(ctx);
if (!interval) {
return args.aggConfigs;
@@ -76,7 +89,7 @@ export const autoDate: ExpressionFunction<
...c,
params: {
...c.params,
- interval: interval.expression,
+ interval,
},
};
});
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx
index ec933d8e82876..11294bedbfff0 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx
@@ -14,6 +14,7 @@ import { IndexPatternPrivateState } from './types';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
import { ChangeIndexPattern } from './change_indexpattern';
import { EuiProgress } from '@elastic/eui';
+import { documentField } from './document_field';
jest.mock('ui/new_platform');
jest.mock('../../../../../../src/legacy/ui/public/registry/field_formats');
@@ -121,6 +122,7 @@ const initialState: IndexPatternPrivateState = {
aggregatable: true,
searchable: true,
},
+ documentField,
],
},
'2': {
@@ -174,6 +176,7 @@ const initialState: IndexPatternPrivateState = {
},
},
},
+ documentField,
],
},
'3': {
@@ -199,6 +202,7 @@ const initialState: IndexPatternPrivateState = {
aggregatable: true,
searchable: true,
},
+ documentField,
],
},
},
@@ -565,6 +569,7 @@ describe('IndexPattern Data Panel', () => {
);
expect(wrapper.find(FieldItem).map(fieldItem => fieldItem.prop('field').name)).toEqual([
+ 'Records',
'bytes',
'client',
'memory',
@@ -630,6 +635,7 @@ describe('IndexPattern Data Panel', () => {
.simulate('click');
expect(wrapper.find(FieldItem).map(fieldItem => fieldItem.prop('field').name)).toEqual([
+ 'Records',
'bytes',
'client',
'memory',
@@ -698,6 +704,7 @@ describe('IndexPattern Data Panel', () => {
const wrapper = shallowWithIntl( );
expect(wrapper.find(FieldItem).map(fieldItem => fieldItem.prop('field').name)).toEqual([
+ 'Records',
'bytes',
'memory',
]);
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
index 35bb3d2de0192..8fc80e14dc166 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
@@ -18,12 +18,13 @@ import {
EuiPopoverTitle,
EuiPopoverFooter,
EuiCallOut,
- EuiText,
EuiFormControlLayout,
EuiSwitch,
EuiFacetButton,
EuiIcon,
- EuiButton,
+ EuiButtonEmpty,
+ EuiSpacer,
+ EuiFormLabel,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -60,10 +61,11 @@ function sortFields(fieldA: IndexPatternField, fieldB: IndexPatternField) {
return fieldA.name.localeCompare(fieldB.name, undefined, { sensitivity: 'base' });
}
-const supportedFieldTypes = new Set(['string', 'number', 'boolean', 'date', 'ip']);
+const supportedFieldTypes = new Set(['string', 'number', 'boolean', 'date', 'ip', 'document']);
const PAGINATION_SIZE = 50;
const fieldTypeNames: Record = {
+ document: i18n.translate('xpack.lens.datatypes.record', { defaultMessage: 'record' }),
string: i18n.translate('xpack.lens.datatypes.string', { defaultMessage: 'string' }),
number: i18n.translate('xpack.lens.datatypes.number', { defaultMessage: 'number' }),
boolean: i18n.translate('xpack.lens.datatypes.boolean', { defaultMessage: 'boolean' }),
@@ -255,7 +257,8 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
if (!showEmptyFields) {
const indexField = currentIndexPattern && fieldByName[field.name];
const exists =
- indexField && fieldExists(existingFields, currentIndexPattern.title, indexField.name);
+ field.type === 'document' ||
+ (indexField && fieldExists(existingFields, currentIndexPattern.title, indexField.name));
if (localState.typeFilter.length > 0) {
return exists && localState.typeFilter.includes(field.type as DataType);
}
@@ -270,7 +273,12 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
return true;
});
- const paginatedFields = displayedFields.sort(sortFields).slice(0, pageSize);
+ const specialFields = displayedFields.filter(f => f.type === 'document');
+ const paginatedFields = displayedFields
+ .filter(f => f.type !== 'document')
+ .sort(sortFields)
+ .slice(0, pageSize);
+ const hilight = localState.nameFilter.toLowerCase();
return (
@@ -320,7 +328,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
className="euiFieldText euiFieldText--fullWidth lnsInnerIndexPatternDataPanel__textField"
data-test-subj="lnsIndexPatternFieldSearch"
placeholder={i18n.translate('xpack.lens.indexPatterns.filterByNameLabel', {
- defaultMessage: 'Search for fields',
+ defaultMessage: 'Search field names',
description:
'Search the list of fields in the index pattern for the provided text',
})}
@@ -339,7 +347,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
id="dataPanelTypeFilter"
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
- anchorPosition="downLeft"
+ anchorPosition="rightDown"
display="block"
isOpen={localState.isTypeFilterOpen}
closePopover={() => setLocalState(() => ({ ...localState, isTypeFilterOpen: false }))}
@@ -418,6 +426,31 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
onScroll={lazyScroll}
>
+ {specialFields.map(field => (
+
0}
+ dateRange={dateRange}
+ query={query}
+ filters={filters}
+ hideDetails={true}
+ />
+ ))}
+ {specialFields.length > 0 && (
+ <>
+
+
+ {i18n.translate('xpack.lens.indexPattern.individualFieldsLabel', {
+ defaultMessage: 'Individual fields',
+ })}
+
+
+ >
+ )}
{paginatedFields.map(field => {
const overallField = fieldByName[field.name];
return (
@@ -426,7 +459,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
indexPattern={currentIndexPattern}
key={field.name}
field={field}
- highlight={localState.nameFilter.toLowerCase()}
+ highlight={hilight}
exists={
overallField &&
fieldExists(existingFields, currentIndexPattern.title, overallField.name)
@@ -439,9 +472,11 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
})}
{paginatedFields.length === 0 && (
-
-
- {showEmptyFields
+
-
+ })
+ }
+ >
{(!showEmptyFields ||
localState.typeFilter.length ||
localState.nameFilter.length) && (
- {
trackUiEvent('indexpattern_show_all_fields_clicked');
clearLocalState();
@@ -471,9 +508,9 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
{i18n.translate('xpack.lens.indexPatterns.showAllFields.buttonText', {
defaultMessage: 'Show all fields',
})}
-
+
)}
-
+
)}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.test.tsx
index 49a04e59b7cc9..d4cf4f7ffbaa6 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.test.tsx
@@ -18,13 +18,13 @@ import {
SavedObjectsClientContract,
HttpServiceBase,
} from 'src/core/public';
-import { Storage } from 'ui/storage';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { IndexPatternPrivateState } from '../types';
+import { documentField } from '../document_field';
jest.mock('ui/new_platform');
jest.mock('../loader');
jest.mock('../state_helpers');
-jest.mock('../operations');
// Used by indexpattern plugin, which is a dependency of a dependency
jest.mock('ui/chrome');
@@ -67,6 +67,7 @@ const expectedIndexPatterns = {
searchable: true,
exists: true,
},
+ documentField,
],
},
};
@@ -129,11 +130,12 @@ describe('IndexPatternDimensionPanel', () => {
dragDropContext,
state,
setState,
+ dateRange: { fromDate: 'now-1d', toDate: 'now' },
columnId: 'col1',
layerId: 'first',
uniqueLabel: 'stuff',
filterOperations: () => true,
- storage: {} as Storage,
+ storage: {} as IStorageWrapper,
uiSettings: {} as UiSettingsClientContract,
savedObjectsClient: {} as SavedObjectsClientContract,
http: {} as HttpServiceBase,
@@ -199,7 +201,7 @@ describe('IndexPatternDimensionPanel', () => {
expect(options).toHaveLength(2);
- expect(options![0].label).toEqual('Document');
+ expect(options![0].label).toEqual('Records');
expect(options![1].options!.map(({ label }) => label)).toEqual([
'timestamp',
@@ -231,7 +233,7 @@ describe('IndexPatternDimensionPanel', () => {
expect(options![1].options!.map(({ label }) => label)).toEqual(['timestamp', 'source']);
});
- it('should indicate fields which are imcompatible for the operation of the current column', () => {
+ it('should indicate fields which are incompatible for the operation of the current column', () => {
wrapper = mount(
{
const options = wrapper.find(EuiComboBox).prop('options');
- expect(options![0]['data-test-subj']).toEqual('lns-documentOptionIncompatible');
+ expect(options![0]['data-test-subj']).toEqual('lns-fieldOptionIncompatible-Records');
expect(
options![1].options!.filter(({ label }) => label === 'timestamp')[0]['data-test-subj']
@@ -658,6 +660,7 @@ describe('IndexPatternDimensionPanel', () => {
isBucketed: false,
label: '',
operationType: 'count',
+ sourceField: 'Records',
},
},
},
@@ -852,6 +855,7 @@ describe('IndexPatternDimensionPanel', () => {
isBucketed: false,
label: '',
operationType: 'count',
+ sourceField: 'Records',
},
},
},
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.tsx
index c0c774a225642..9f558b7354acd 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.tsx
@@ -7,13 +7,13 @@
import _ from 'lodash';
import React, { memo, useMemo } from 'react';
import { EuiButtonIcon } from '@elastic/eui';
-import { Storage } from 'ui/storage';
import { i18n } from '@kbn/i18n';
import {
UiSettingsClientContract,
SavedObjectsClientContract,
HttpServiceBase,
} from 'src/core/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { DatasourceDimensionPanelProps, StateSetter } from '../../types';
import { IndexPatternColumn, OperationType } from '../indexpattern';
import { getAvailableOperationsByMetadata, buildColumn, changeField } from '../operations';
@@ -23,23 +23,24 @@ import { changeColumn, deleteColumn } from '../state_helpers';
import { isDraggedField, hasField } from '../utils';
import { IndexPatternPrivateState, IndexPatternField } from '../types';
import { trackUiEvent } from '../../lens_ui_telemetry';
+import { DateRange } from '../../../common';
export type IndexPatternDimensionPanelProps = DatasourceDimensionPanelProps & {
state: IndexPatternPrivateState;
setState: StateSetter;
dragDropContext: DragContextState;
uiSettings: UiSettingsClientContract;
- storage: Storage;
+ storage: IStorageWrapper;
savedObjectsClient: SavedObjectsClientContract;
layerId: string;
http: HttpServiceBase;
uniqueLabel: string;
+ dateRange: DateRange;
};
export interface OperationFieldSupportMatrix {
operationByField: Partial>;
fieldByOperation: Partial>;
- operationByDocument: OperationType[];
}
export const IndexPatternDimensionPanel = memo(function IndexPatternDimensionPanel(
@@ -55,30 +56,25 @@ export const IndexPatternDimensionPanel = memo(function IndexPatternDimensionPan
const supportedOperationsByField: Partial> = {};
const supportedFieldsByOperation: Partial> = {};
- const supportedOperationsByDocument: OperationType[] = [];
+
filteredOperationsByMetadata.forEach(({ operations }) => {
operations.forEach(operation => {
- if (operation.type === 'field') {
- if (supportedOperationsByField[operation.field]) {
- supportedOperationsByField[operation.field]!.push(operation.operationType);
- } else {
- supportedOperationsByField[operation.field] = [operation.operationType];
- }
+ if (supportedOperationsByField[operation.field]) {
+ supportedOperationsByField[operation.field]!.push(operation.operationType);
+ } else {
+ supportedOperationsByField[operation.field] = [operation.operationType];
+ }
- if (supportedFieldsByOperation[operation.operationType]) {
- supportedFieldsByOperation[operation.operationType]!.push(operation.field);
- } else {
- supportedFieldsByOperation[operation.operationType] = [operation.field];
- }
+ if (supportedFieldsByOperation[operation.operationType]) {
+ supportedFieldsByOperation[operation.operationType]!.push(operation.field);
} else {
- supportedOperationsByDocument.push(operation.operationType);
+ supportedFieldsByOperation[operation.operationType] = [operation.field];
}
});
});
return {
operationByField: _.mapValues(supportedOperationsByField, _.uniq),
fieldByOperation: _.mapValues(supportedFieldsByOperation, _.uniq),
- operationByDocument: _.uniq(supportedOperationsByDocument),
};
}, [currentIndexPattern, props.filterOperations]);
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/field_select.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/field_select.tsx
index 7eeffdff383e1..ba18cd150c7a5 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/field_select.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/field_select.tsx
@@ -21,9 +21,11 @@ import { IndexPattern, IndexPatternField, IndexPatternPrivateState } from '../ty
import { trackUiEvent } from '../../lens_ui_telemetry';
import { fieldExists } from '../pure_helpers';
-export type FieldChoice =
- | { type: 'field'; field: string; operationType?: OperationType }
- | { type: 'document' };
+export interface FieldChoice {
+ type: 'field';
+ field: string;
+ operationType?: OperationType;
+}
export interface FieldSelectProps {
currentIndexPattern: IndexPattern;
@@ -50,8 +52,7 @@ export function FieldSelect({
onDeleteColumn,
existingFields,
}: FieldSelectProps) {
- const { operationByDocument, operationByField } = operationFieldSupportMatrix;
-
+ const { operationByField } = operationFieldSupportMatrix;
const memoizedFieldOptions = useMemo(() => {
const fields = Object.keys(operationByField).sort();
@@ -65,68 +66,58 @@ export function FieldSelect({
);
}
- const isCurrentOperationApplicableWithoutField =
- (!selectedColumnOperationType && !incompatibleSelectedOperationType) ||
- operationByDocument.includes(
- incompatibleSelectedOperationType || selectedColumnOperationType!
- );
+ const [specialFields, normalFields] = _.partition(
+ fields,
+ field => fieldMap[field].type === 'document'
+ );
- const fieldOptions = [];
-
- if (operationByDocument.length > 0) {
- fieldOptions.push({
- label: i18n.translate('xpack.lens.indexPattern.documentField', {
- defaultMessage: 'Document',
- }),
- value: { type: 'document' },
- className: classNames({
- 'lnFieldSelect__option--incompatible': !isCurrentOperationApplicableWithoutField,
- }),
- 'data-test-subj': `lns-documentOption${
- isCurrentOperationApplicableWithoutField ? '' : 'Incompatible'
- }`,
- });
+ function fieldNamesToOptions(items: string[]) {
+ return items
+ .map(field => ({
+ label: field,
+ value: {
+ type: 'field',
+ field,
+ dataType: fieldMap[field].type,
+ operationType:
+ selectedColumnOperationType && isCompatibleWithCurrentOperation(field)
+ ? selectedColumnOperationType
+ : undefined,
+ },
+ exists:
+ fieldMap[field].type === 'document' ||
+ fieldExists(existingFields, currentIndexPattern.title, field),
+ compatible: isCompatibleWithCurrentOperation(field),
+ }))
+ .filter(field => showEmptyFields || field.exists)
+ .sort((a, b) => {
+ if (a.compatible && !b.compatible) {
+ return -1;
+ }
+ if (!a.compatible && b.compatible) {
+ return 1;
+ }
+ return 0;
+ })
+ .map(({ label, value, compatible, exists }) => ({
+ label,
+ value,
+ className: classNames({
+ 'lnFieldSelect__option--incompatible': !compatible,
+ 'lnFieldSelect__option--nonExistant': !exists,
+ }),
+ 'data-test-subj': `lns-fieldOption${compatible ? '' : 'Incompatible'}-${label}`,
+ }));
}
+ const fieldOptions: unknown[] = fieldNamesToOptions(specialFields);
+
if (fields.length > 0) {
fieldOptions.push({
label: i18n.translate('xpack.lens.indexPattern.individualFieldsLabel', {
defaultMessage: 'Individual fields',
}),
- options: fields
- .map(field => ({
- label: field,
- value: {
- type: 'field',
- field,
- dataType: fieldMap[field].type,
- operationType:
- selectedColumnOperationType && isCompatibleWithCurrentOperation(field)
- ? selectedColumnOperationType
- : undefined,
- },
- exists: fieldExists(existingFields, currentIndexPattern.title, field),
- compatible: isCompatibleWithCurrentOperation(field),
- }))
- .filter(field => showEmptyFields || field.exists)
- .sort((a, b) => {
- if (a.compatible && !b.compatible) {
- return -1;
- }
- if (!a.compatible && b.compatible) {
- return 1;
- }
- return 0;
- })
- .map(({ label, value, compatible, exists }) => ({
- label,
- value,
- className: classNames({
- 'lnFieldSelect__option--incompatible': !compatible,
- 'lnFieldSelect__option--nonExistant': !exists,
- }),
- 'data-test-subj': `lns-fieldOption${compatible ? '' : 'Incompatible'}-${label}`,
- })),
+ options: fieldNamesToOptions(normalFields),
});
}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/popover_editor.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/popover_editor.tsx
index b9baa489f3382..0555787ec840d 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/popover_editor.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/popover_editor.tsx
@@ -38,10 +38,13 @@ import { trackUiEvent } from '../../lens_ui_telemetry';
const operationPanels = getOperationDisplay();
-export function asOperationOptions(
- operationTypes: OperationType[],
- compatibleWithCurrentField: boolean
-) {
+export interface PopoverEditorProps extends IndexPatternDimensionPanelProps {
+ selectedColumn?: IndexPatternColumn;
+ operationFieldSupportMatrix: OperationFieldSupportMatrix;
+ currentIndexPattern: IndexPattern;
+}
+
+function asOperationOptions(operationTypes: OperationType[], compatibleWithCurrentField: boolean) {
return [...operationTypes]
.sort((opType1, opType2) => {
return operationPanels[opType1].displayName.localeCompare(
@@ -54,12 +57,6 @@ export function asOperationOptions(
}));
}
-export interface PopoverEditorProps extends IndexPatternDimensionPanelProps {
- selectedColumn?: IndexPatternColumn;
- operationFieldSupportMatrix: OperationFieldSupportMatrix;
- currentIndexPattern: IndexPattern;
-}
-
export function PopoverEditor(props: PopoverEditorProps) {
const {
selectedColumn,
@@ -72,7 +69,7 @@ export function PopoverEditor(props: PopoverEditorProps) {
uniqueLabel,
hideGrouping,
} = props;
- const { operationByDocument, operationByField, fieldByOperation } = operationFieldSupportMatrix;
+ const { operationByField, fieldByOperation } = operationFieldSupportMatrix;
const [isPopoverOpen, setPopoverOpen] = useState(false);
const [
incompatibleSelectedOperationType,
@@ -87,19 +84,12 @@ export function PopoverEditor(props: PopoverEditorProps) {
currentIndexPattern.fields.forEach(field => {
fields[field.name] = field;
});
-
return fields;
}, [currentIndexPattern]);
function getOperationTypes() {
- const possibleOperationTypes = Object.keys(fieldByOperation).concat(
- operationByDocument
- ) as OperationType[];
-
+ const possibleOperationTypes = Object.keys(fieldByOperation) as OperationType[];
const validOperationTypes: OperationType[] = [];
- if (!selectedColumn || !hasField(selectedColumn)) {
- validOperationTypes.push(...operationByDocument);
- }
if (!selectedColumn) {
validOperationTypes.push(...(Object.keys(fieldByOperation) as OperationType[]));
@@ -139,12 +129,8 @@ export function PopoverEditor(props: PopoverEditorProps) {
onClick() {
if (!selectedColumn) {
const possibleFields = fieldByOperation[operationType] || [];
- const isFieldlessPossible = operationByDocument.includes(operationType);
- if (
- possibleFields.length === 1 ||
- (possibleFields.length === 0 && isFieldlessPossible)
- ) {
+ if (possibleFields.length === 1) {
setState(
changeColumn({
state,
@@ -156,8 +142,7 @@ export function PopoverEditor(props: PopoverEditorProps) {
layerId: props.layerId,
op: operationType,
indexPattern: currentIndexPattern,
- field: possibleFields.length === 1 ? fieldMap[possibleFields[0]] : undefined,
- asDocumentOperation: possibleFields.length === 0,
+ field: fieldMap[possibleFields[0]],
}),
})
);
@@ -184,7 +169,7 @@ export function PopoverEditor(props: PopoverEditorProps) {
layerId: props.layerId,
op: operationType,
indexPattern: currentIndexPattern,
- field: hasField(selectedColumn) ? fieldMap[selectedColumn.sourceField] : undefined,
+ field: fieldMap[selectedColumn.sourceField],
});
trackUiEvent(
`indexpattern_dimension_operation_from_${selectedColumn.operationType}_to_${operationType}`
@@ -307,12 +292,11 @@ export function PopoverEditor(props: PopoverEditorProps) {
}
column = buildColumn({
columns: props.state.layers[props.layerId].columns,
- field: 'field' in choice ? fieldMap[choice.field] : undefined,
+ field: fieldMap[choice.field],
indexPattern: currentIndexPattern,
layerId: props.layerId,
suggestedPriority: props.suggestedPriority,
op: operation as OperationType,
- asDocumentOperation: choice.type === 'document',
});
}
@@ -354,7 +338,7 @@ export function PopoverEditor(props: PopoverEditorProps) {
defaultMessage: 'To use this function, select a field.',
})}
iconType="sortUp"
- >
+ />
)}
{!incompatibleSelectedOperationType && ParamEditor && (
<>
@@ -368,6 +352,7 @@ export function PopoverEditor(props: PopoverEditorProps) {
savedObjectsClient={props.savedObjectsClient}
layerId={layerId}
http={props.http}
+ dateRange={props.dateRange}
/>
>
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/document_field.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/document_field.ts
new file mode 100644
index 0000000000000..e0a7f27835e42
--- /dev/null
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/document_field.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { i18n } from '@kbn/i18n';
+
+/**
+ * This is a special-case field which allows us to perform
+ * document-level operations such as count.
+ */
+export const documentField = {
+ name: i18n.translate('xpack.lens.indexPattern.records', {
+ defaultMessage: 'Records',
+ }),
+ type: 'document',
+ aggregatable: true,
+ searchable: true,
+};
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx
index 79a3ac4137f88..962eece4977e0 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx
@@ -35,8 +35,9 @@ import {
niceTimeFormatter,
} from '@elastic/charts';
import { i18n } from '@kbn/i18n';
-import { Filter, buildEsQuery, getEsQueryConfig } from '@kbn/es-query';
+import { buildEsQuery, getEsQueryConfig } from '@kbn/es-query';
import { Query } from 'src/plugins/data/common';
+import { esFilters } from '../../../../../../src/plugins/data/public';
// @ts-ignore
import { fieldFormats } from '../../../../../../src/legacy/ui/public/registry/field_formats';
import { DraggedField } from './indexpattern';
@@ -55,7 +56,8 @@ export interface FieldItemProps {
exists: boolean;
query: Query;
dateRange: DatasourceDataPanelProps['dateRange'];
- filters: Filter[];
+ filters: esFilters.Filter[];
+ hideDetails?: boolean;
}
interface State {
@@ -75,7 +77,17 @@ function wrapOnDot(str?: string) {
}
export function FieldItem(props: FieldItemProps) {
- const { core, field, indexPattern, highlight, exists, query, dateRange, filters } = props;
+ const {
+ core,
+ field,
+ indexPattern,
+ highlight,
+ exists,
+ query,
+ dateRange,
+ filters,
+ hideDetails,
+ } = props;
const [infoIsOpen, setOpen] = useState(false);
@@ -140,6 +152,10 @@ export function FieldItem(props: FieldItemProps) {
}
function togglePopover() {
+ if (hideDetails) {
+ return;
+ }
+
setOpen(!infoIsOpen);
if (!infoIsOpen) {
trackUiEvent('indexpattern_field_info_click');
@@ -175,7 +191,7 @@ export function FieldItem(props: FieldItemProps) {
}
}}
aria-label={i18n.translate('xpack.lens.indexPattern.fieldStatsButtonLabel', {
- defaultMessage: 'Click for a field preview. Or, drag and drop to visualize.',
+ defaultMessage: 'Click for a field preview, or drag and drop to visualize.',
})}
>
@@ -186,9 +202,15 @@ export function FieldItem(props: FieldItemProps) {
-
+
{Math.round((topValue.count / props.sampledValues!) * 100)}%
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts
index b4f01078f1f78..d998437f3e492 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts
@@ -5,7 +5,7 @@
*/
import chromeMock from 'ui/chrome';
-import { Storage } from 'ui/storage';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { SavedObjectsClientContract } from 'kibana/public';
import { getIndexPatternDatasource, IndexPatternColumn, uniqueLabels } from './indexpattern';
import { DatasourcePublicAPI, Operation, Datasource } from '../types';
@@ -143,7 +143,7 @@ describe('IndexPattern Data Source', () => {
beforeEach(() => {
indexPatternDatasource = getIndexPatternDatasource({
chrome: chromeMock,
- storage: {} as Storage,
+ storage: {} as IStorageWrapper,
core: coreMock.createStart(),
savedObjectsClient: {} as SavedObjectsClientContract,
data: pluginsMock.createStart().data,
@@ -183,6 +183,7 @@ describe('IndexPattern Data Source', () => {
isBucketed: false,
label: 'Foo',
operationType: 'count',
+ sourceField: 'Records',
};
const map = uniqueLabels({
a: {
@@ -243,16 +244,13 @@ describe('IndexPattern Data Source', () => {
label: 'Count of records',
dataType: 'number',
isBucketed: false,
-
- // Private
+ sourceField: 'Records',
operationType: 'count',
},
col2: {
label: 'Date',
dataType: 'date',
isBucketed: true,
-
- // Private
operationType: 'date_histogram',
sourceField: 'timestamp',
params: {
@@ -272,7 +270,7 @@ describe('IndexPattern Data Source', () => {
metricsAtAllLevels=false
partialRows=false
includeFormatHints=true
- aggConfigs={lens_auto_date aggConfigs='[{\\"id\\":\\"col1\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}},{\\"id\\":\\"col2\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"timestamp\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"1d\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}}]'} | lens_rename_columns idMap='{\\"col-0-col1\\":{\\"label\\":\\"Count of records\\",\\"dataType\\":\\"number\\",\\"isBucketed\\":false,\\"operationType\\":\\"count\\",\\"id\\":\\"col1\\"},\\"col-1-col2\\":{\\"label\\":\\"Date\\",\\"dataType\\":\\"date\\",\\"isBucketed\\":true,\\"operationType\\":\\"date_histogram\\",\\"sourceField\\":\\"timestamp\\",\\"params\\":{\\"interval\\":\\"1d\\"},\\"id\\":\\"col2\\"}}'"
+ aggConfigs={lens_auto_date aggConfigs='[{\\"id\\":\\"col1\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}},{\\"id\\":\\"col2\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"timestamp\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"1d\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}}]'} | lens_rename_columns idMap='{\\"col-0-col1\\":{\\"label\\":\\"Count of records\\",\\"dataType\\":\\"number\\",\\"isBucketed\\":false,\\"sourceField\\":\\"Records\\",\\"operationType\\":\\"count\\",\\"id\\":\\"col1\\"},\\"col-1-col2\\":{\\"label\\":\\"Date\\",\\"dataType\\":\\"date\\",\\"isBucketed\\":true,\\"operationType\\":\\"date_histogram\\",\\"sourceField\\":\\"timestamp\\",\\"params\\":{\\"interval\\":\\"1d\\"},\\"id\\":\\"col2\\"}}'"
`);
});
});
@@ -414,7 +412,15 @@ describe('IndexPattern Data Source', () => {
beforeEach(async () => {
const initialState = stateFromPersistedState(persistedState);
- publicAPI = indexPatternDatasource.getPublicAPI(initialState, () => {}, 'first');
+ publicAPI = indexPatternDatasource.getPublicAPI({
+ state: initialState,
+ setState: () => {},
+ layerId: 'first',
+ dateRange: {
+ fromDate: 'now-30d',
+ toDate: 'now',
+ },
+ });
});
describe('getTableSpec', () => {
@@ -453,8 +459,8 @@ describe('IndexPattern Data Source', () => {
suggestedPriority: 2,
},
};
- const api = indexPatternDatasource.getPublicAPI(
- {
+ const api = indexPatternDatasource.getPublicAPI({
+ state: {
...initialState,
layers: {
first: {
@@ -465,8 +471,12 @@ describe('IndexPattern Data Source', () => {
},
},
setState,
- 'first'
- );
+ layerId: 'first',
+ dateRange: {
+ fromDate: 'now-1y',
+ toDate: 'now',
+ },
+ });
api.removeColumnInTableSpec('b');
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
index 359eb687b5741..443667ab64476 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
@@ -9,13 +9,14 @@ import React from 'react';
import { render } from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
import { CoreStart, SavedObjectsClientContract } from 'src/core/public';
-import { Storage } from 'ui/storage';
import { i18n } from '@kbn/i18n';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import {
DatasourceDimensionPanelProps,
DatasourceDataPanelProps,
Operation,
DatasourceLayerPanelProps,
+ PublicAPIProps,
} from '../types';
import { loadInitialState, changeIndexPattern, changeLayerIndexPattern } from './loader';
import { toExpression } from './to_expression';
@@ -27,7 +28,7 @@ import {
getDatasourceSuggestionsFromCurrentState,
} from './indexpattern_suggestions';
-import { isDraggedField } from './utils';
+import { isDraggedField, normalizeOperationDataType } from './utils';
import { LayerPanel } from './layerpanel';
import { IndexPatternColumn } from './operations';
import {
@@ -50,7 +51,7 @@ export interface DraggedField {
export function columnToOperation(column: IndexPatternColumn, uniqueLabel?: string): Operation {
const { dataType, label, isBucketed, scale } = column;
return {
- dataType,
+ dataType: normalizeOperationDataType(dataType),
isBucketed,
scale,
label: uniqueLabel || label,
@@ -104,7 +105,7 @@ export function getIndexPatternDatasource({
// Core start is being required here because it contains the savedObject client
// In the new platform, this plugin wouldn't be initialized until after setup
core: CoreStart;
- storage: Storage;
+ storage: IStorageWrapper;
savedObjectsClient: SavedObjectsClientContract;
data: ReturnType;
}) {
@@ -196,11 +197,12 @@ export function getIndexPatternDatasource({
);
},
- getPublicAPI(
- state: IndexPatternPrivateState,
- setState: StateSetter,
- layerId: string
- ) {
+ getPublicAPI({
+ state,
+ setState,
+ layerId,
+ dateRange,
+ }: PublicAPIProps) {
const columnLabelMap = uniqueLabels(state.layers);
return {
@@ -221,7 +223,7 @@ export function getIndexPatternDatasource({
@@ -257,6 +260,7 @@ export function getIndexPatternDatasource({
state,
layerId: props.layerId,
onError: onIndexPatternLoadError,
+ replaceIfPossible: true,
});
}}
{...props}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern_suggestions.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern_suggestions.test.tsx
index ff6911bd25f84..e86a16c1af9d6 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern_suggestions.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern_suggestions.test.tsx
@@ -562,6 +562,62 @@ describe('IndexPattern Data Source suggestions', () => {
})
);
});
+
+ it('creates a new layer and replaces layer if no match is found', () => {
+ const suggestions = getDatasourceSuggestionsForField(stateWithEmptyLayer(), '2', {
+ name: 'source',
+ type: 'string',
+ aggregatable: true,
+ searchable: true,
+ });
+
+ expect(suggestions).toContainEqual(
+ expect.objectContaining({
+ state: expect.objectContaining({
+ layers: {
+ previousLayer: expect.objectContaining({
+ indexPatternId: '1',
+ }),
+ id1: expect.objectContaining({
+ indexPatternId: '2',
+ }),
+ },
+ }),
+ table: {
+ changeType: 'initial',
+ label: undefined,
+ isMultiRow: true,
+ columns: expect.arrayContaining([]),
+ layerId: 'id1',
+ },
+ keptLayerIds: ['previousLayer'],
+ })
+ );
+
+ expect(suggestions).toContainEqual(
+ expect.objectContaining({
+ state: expect.objectContaining({
+ layers: {
+ id1: expect.objectContaining({
+ indexPatternId: '2',
+ }),
+ },
+ }),
+ table: {
+ changeType: 'initial',
+ label: undefined,
+ isMultiRow: false,
+ columns: expect.arrayContaining([
+ expect.objectContaining({
+ columnId: expect.any(String),
+ }),
+ ]),
+ layerId: 'id1',
+ },
+ keptLayerIds: [],
+ })
+ );
+ });
});
describe('suggesting extensions to non-empty tables', () => {
@@ -979,12 +1035,25 @@ describe('IndexPattern Data Source suggestions', () => {
};
const result = getDatasourceSuggestionsFromCurrentState(state);
+
expect(result).toContainEqual(
expect.objectContaining({
- table: {
+ table: expect.objectContaining({
isMultiRow: true,
changeType: 'unchanged',
label: undefined,
+ layerId: 'first',
+ }),
+ keptLayerIds: ['first', 'second'],
+ })
+ );
+
+ expect(result).toContainEqual(
+ expect.objectContaining({
+ table: {
+ isMultiRow: true,
+ changeType: 'layers',
+ label: 'Show only layer 1',
columns: [
{
columnId: 'col1',
@@ -1005,8 +1074,8 @@ describe('IndexPattern Data Source suggestions', () => {
expect.objectContaining({
table: {
isMultiRow: true,
- changeType: 'unchanged',
- label: undefined,
+ changeType: 'layers',
+ label: 'Show only layer 2',
columns: [
{
columnId: 'cola',
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern_suggestions.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern_suggestions.ts
index 49944614edbb4..d2cf6261835fd 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern_suggestions.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern_suggestions.ts
@@ -23,6 +23,7 @@ import {
IndexPatternLayer,
IndexPatternField,
} from './types';
+import { documentField } from './document_field';
type IndexPatternSugestion = DatasourceSuggestion;
@@ -80,6 +81,8 @@ function buildSuggestion({
changeType,
label,
},
+
+ keptLayerIds: Object.keys(state.layers),
};
}
@@ -92,10 +95,13 @@ export function getDatasourceSuggestionsForField(
const layerIds = layers.filter(id => state.layers[id].indexPatternId === indexPatternId);
if (layerIds.length === 0) {
- // The field we're suggesting on does not match any existing layer. This will always add
- // a new layer if possible, but that might not be desirable if the layers are too complicated
- // already
- return getEmptyLayerSuggestionsForField(state, generateId(), indexPatternId, field);
+ // The field we're suggesting on does not match any existing layer.
+ // This generates a set of suggestions where we add a layer.
+ // A second set of suggestions is generated for visualizations that don't work with layers
+ const newId = generateId();
+ return getEmptyLayerSuggestionsForField(state, newId, indexPatternId, field).concat(
+ getEmptyLayerSuggestionsForField({ ...state, layers: {} }, newId, indexPatternId, field)
+ );
} else {
// The field we're suggesting on matches an existing layer. In this case we find the layer with
// the fewest configured columns and try to add the field to this table. If this layer does not
@@ -165,7 +171,7 @@ function addFieldAsMetricOperation(
layerId: string,
indexPattern: IndexPattern,
field: IndexPatternField
-) {
+): IndexPatternLayer | undefined {
const operations = getOperationTypesForField(field);
const operationsAlreadyAppliedToThisField = Object.values(layer.columns)
.filter(column => hasField(column) && column.sourceField === field.name)
@@ -175,7 +181,7 @@ function addFieldAsMetricOperation(
);
if (!operationCandidate) {
- return undefined;
+ return;
}
const newColumn = buildColumn({
@@ -205,7 +211,7 @@ function addFieldAsBucketOperation(
layerId: string,
indexPattern: IndexPattern,
field: IndexPatternField
-) {
+): IndexPatternLayer {
const applicableBucketOperation = getBucketOperation(field);
const newColumn = buildColumn({
op: applicableBucketOperation,
@@ -249,7 +255,7 @@ function getEmptyLayerSuggestionsForField(
layerId: string,
indexPatternId: string,
field: IndexPatternField
-) {
+): IndexPatternSugestion[] {
const indexPattern = state.indexPatterns[indexPatternId];
let newLayer: IndexPatternLayer | undefined;
if (getBucketOperation(field)) {
@@ -278,13 +284,14 @@ function createNewLayerWithBucketAggregation(
layerId: string,
indexPattern: IndexPattern,
field: IndexPatternField
-) {
+): IndexPatternLayer {
const countColumn = buildColumn({
op: 'count',
columns: {},
indexPattern,
layerId,
suggestedPriority: undefined,
+ field: documentField,
});
const col1 = generateId();
@@ -316,7 +323,7 @@ function createNewLayerWithMetricAggregation(
layerId: string,
indexPattern: IndexPattern,
field: IndexPatternField
-) {
+): IndexPatternLayer {
const dateField = indexPattern.fields.find(f => f.name === indexPattern.timeFieldName)!;
const operations = getOperationTypesForField(field);
@@ -354,16 +361,59 @@ function createNewLayerWithMetricAggregation(
export function getDatasourceSuggestionsFromCurrentState(
state: IndexPatternPrivateState
): Array> {
+ const layers = Object.entries(state.layers || {});
+ if (layers.length > 1) {
+ // Return suggestions that reduce the data to each layer individually
+ return layers
+ .map(([layerId, layer], index) => {
+ const hasMatchingLayer = layers.some(
+ ([otherLayerId, otherLayer]) =>
+ otherLayerId !== layerId && otherLayer.indexPatternId === layer.indexPatternId
+ );
+
+ const suggestionTitle = hasMatchingLayer
+ ? i18n.translate('xpack.lens.indexPatternSuggestion.removeLayerPositionLabel', {
+ defaultMessage: 'Show only layer {layerNumber}',
+ values: { layerNumber: index + 1 },
+ })
+ : i18n.translate('xpack.lens.indexPatternSuggestion.removeLayerLabel', {
+ defaultMessage: 'Show only {indexPatternTitle}',
+ values: { indexPatternTitle: state.indexPatterns[layer.indexPatternId].title },
+ });
+
+ return buildSuggestion({
+ state: {
+ ...state,
+ layers: {
+ [layerId]: layer,
+ },
+ },
+ layerId,
+ changeType: 'layers',
+ label: suggestionTitle,
+ });
+ })
+ .concat([
+ buildSuggestion({
+ state,
+ layerId: layers[0][0],
+ changeType: 'unchanged',
+ }),
+ ]);
+ }
return _.flatten(
Object.entries(state.layers || {})
- .filter(([_id, layer]) => layer.columnOrder.length)
- .map(([layerId, layer], index) => {
+ .filter(([_id, layer]) => layer.columnOrder.length && layer.indexPatternId)
+ .map(([layerId, layer]) => {
const indexPattern = state.indexPatterns[layer.indexPatternId];
const [buckets, metrics] = separateBucketColumns(layer);
const timeDimension = layer.columnOrder.find(
columnId =>
layer.columns[columnId].isBucketed && layer.columns[columnId].dataType === 'date'
);
+ const timeField = indexPattern.fields.find(
+ ({ name }) => name === indexPattern.timeFieldName
+ );
const suggestions: Array> = [];
if (metrics.length === 0) {
@@ -376,9 +426,9 @@ export function getDatasourceSuggestionsFromCurrentState(
})
);
} else if (buckets.length === 0) {
- if (indexPattern.timeFieldName) {
+ if (timeField) {
// suggest current metric over time if there is a default time field
- suggestions.push(createSuggestionWithDefaultDateHistogram(state, layerId));
+ suggestions.push(createSuggestionWithDefaultDateHistogram(state, layerId, timeField));
}
suggestions.push(...createAlternativeMetricSuggestions(indexPattern, layerId, state));
// also suggest simple current state
@@ -392,10 +442,10 @@ export function getDatasourceSuggestionsFromCurrentState(
} else {
suggestions.push(...createSimplifiedTableSuggestions(state, layerId));
- if (!timeDimension && indexPattern.timeFieldName) {
+ if (!timeDimension && timeField) {
// suggest current configuration over time if there is a default time field
// and no time dimension yet
- suggestions.push(createSuggestionWithDefaultDateHistogram(state, layerId));
+ suggestions.push(createSuggestionWithDefaultDateHistogram(state, layerId, timeField));
}
if (buckets.length === 2) {
@@ -427,7 +477,6 @@ function createMetricSuggestion(
state: IndexPatternPrivateState,
field: IndexPatternField
) {
- const layer = state.layers[layerId];
const operationDefinitionsMap = _.indexBy(operationDefinitions, 'type');
const [column] = getOperationTypesForField(field)
.map(type =>
@@ -439,20 +488,33 @@ function createMetricSuggestion(
suggestedPriority: 0,
})
)
- .filter(op => op.dataType === 'number' && !op.isBucketed);
+ .filter(op => (op.dataType === 'number' || op.dataType === 'document') && !op.isBucketed);
if (!column) {
return;
}
const newId = generateId();
+
return buildSuggestion({
layerId,
state,
changeType: 'initial',
updatedLayer: {
- ...layer,
- columns: { [newId]: column },
+ indexPatternId: indexPattern.id,
+ columns: {
+ [newId]:
+ column.dataType !== 'document'
+ ? column
+ : buildColumn({
+ op: 'count',
+ columns: {},
+ indexPattern,
+ layerId,
+ suggestedPriority: undefined,
+ field: documentField,
+ }),
+ },
columnOrder: [newId],
},
});
@@ -462,8 +524,8 @@ function getNestedTitle([outerBucket, innerBucket]: IndexPatternColumn[]) {
return i18n.translate('xpack.lens.indexpattern.suggestions.nestingChangeLabel', {
defaultMessage: '{innerOperation} for each {outerOperation}',
values: {
- innerOperation: hasField(innerBucket) ? innerBucket.sourceField : innerBucket.label,
- outerOperation: hasField(outerBucket) ? outerBucket.sourceField : outerBucket.label,
+ innerOperation: innerBucket.sourceField,
+ outerOperation: outerBucket.sourceField,
},
});
}
@@ -497,7 +559,7 @@ function createAlternativeMetricSuggestions(
suggestedPriority: undefined,
});
const updatedLayer = {
- ...layer,
+ indexPatternId: indexPattern.id,
columns: { [newId]: newColumn },
columnOrder: [newId],
};
@@ -515,7 +577,8 @@ function createAlternativeMetricSuggestions(
function createSuggestionWithDefaultDateHistogram(
state: IndexPatternPrivateState,
- layerId: string
+ layerId: string,
+ timeField: IndexPatternField
) {
const layer = state.layers[layerId];
const indexPattern = state.indexPatterns[layer.indexPatternId];
@@ -526,11 +589,11 @@ function createSuggestionWithDefaultDateHistogram(
op: 'date_histogram',
indexPattern,
columns: layer.columns,
- field: indexPattern.fields.find(({ name }) => name === indexPattern.timeFieldName),
+ field: timeField,
suggestedPriority: undefined,
});
const updatedLayer = {
- ...layer,
+ indexPatternId: layer.indexPatternId,
columns: { ...layer.columns, [newId]: timeColumn },
columnOrder: [...buckets, newId, ...metrics],
};
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.tsx
index 1773022bf6e1a..cd2bb69f6e580 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.tsx
@@ -8,9 +8,10 @@ import React from 'react';
import { palettes } from '@elastic/eui';
import { FieldIcon, typeToEuiIconMap } from '../../../../../../src/plugins/kibana_react/public';
import { DataType } from '../types';
+import { normalizeOperationDataType } from './utils';
export function getColorForDataType(type: string) {
- const iconMap = typeToEuiIconMap[type];
+ const iconMap = typeToEuiIconMap[normalizeOperationDataType(type as DataType)];
if (iconMap) {
return iconMap.color;
}
@@ -18,5 +19,12 @@ export function getColorForDataType(type: string) {
}
export function LensFieldIcon({ type }: { type: DataType }) {
- return ;
+ return (
+
+ );
}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts
index b3f296a96e56d..03bbddb998b3c 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts
@@ -14,6 +14,7 @@ import {
syncExistingFields,
} from './loader';
import { IndexPatternPersistedState, IndexPatternPrivateState } from './types';
+import { documentField } from './document_field';
// TODO: This should not be necessary
jest.mock('ui/new_platform');
@@ -63,6 +64,7 @@ const sampleIndexPatterns = {
searchable: true,
esTypes: ['keyword'],
},
+ documentField,
],
},
b: {
@@ -121,6 +123,7 @@ const sampleIndexPatterns = {
},
esTypes: ['keyword'],
},
+ documentField,
],
},
};
@@ -133,7 +136,7 @@ function indexPatternSavedObject({ id }: { id: keyof typeof sampleIndexPatterns
attributes: {
title: pattern.title,
timeFieldName: pattern.timeFieldName,
- fields: JSON.stringify(pattern.fields),
+ fields: JSON.stringify(pattern.fields.filter(f => f.type !== 'document')),
},
};
}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts
index dd1f43f7b9276..d83777b758da6 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts
@@ -23,6 +23,7 @@ import {
import { updateLayerIndexPattern } from './state_helpers';
import { DateRange, ExistingFields } from '../../common/types';
import { BASE_API_URL } from '../../common';
+import { documentField } from './document_field';
interface SavedIndexPatternAttributes extends SavedObjectAttributes {
title: string;
@@ -171,6 +172,7 @@ export async function changeLayerIndexPattern({
state,
setState,
onError,
+ replaceIfPossible,
}: {
indexPatternId: string;
layerId: string;
@@ -178,6 +180,7 @@ export async function changeLayerIndexPattern({
state: IndexPatternPrivateState;
setState: SetState;
onError: ErrorHandler;
+ replaceIfPossible?: boolean;
}) {
try {
const indexPatterns = await loadIndexPatterns({
@@ -196,6 +199,7 @@ export async function changeLayerIndexPattern({
...s.indexPatterns,
[indexPatternId]: indexPatterns[indexPatternId],
},
+ currentIndexPatternId: replaceIfPossible ? indexPatternId : s.currentIndexPatternId,
}));
} catch (err) {
onError(err);
@@ -211,10 +215,14 @@ async function loadIndexPatternRefs(
perPage: 10000,
});
- return result.savedObjects.map(o => ({
- id: String(o.id),
- title: (o.attributes as { title: string }).title,
- }));
+ return result.savedObjects
+ .map(o => ({
+ id: String(o.id),
+ title: (o.attributes as { title: string }).title,
+ }))
+ .sort((a, b) => {
+ return a.title.localeCompare(b.title);
+ });
}
export async function syncExistingFields({
@@ -278,10 +286,12 @@ function fromSavedObject(
id,
type,
title: attributes.title,
- fields: (JSON.parse(attributes.fields) as IndexPatternField[]).filter(
- ({ type: fieldType, esTypes }) =>
- fieldType !== 'string' || (esTypes && esTypes.includes('keyword'))
- ),
+ fields: (JSON.parse(attributes.fields) as IndexPatternField[])
+ .filter(
+ ({ type: fieldType, esTypes }) =>
+ fieldType !== 'string' || (esTypes && esTypes.includes('keyword'))
+ )
+ .concat(documentField),
typeMeta: attributes.typeMeta
? (JSON.parse(attributes.typeMeta) as SavedRestrictionsInfo)
: undefined,
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/column_types.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/column_types.ts
index ed0e2fb3c96c5..fe8a3d34d1c1c 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/column_types.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/column_types.ts
@@ -14,6 +14,7 @@ import { Operation, DimensionPriority } from '../../../types';
export interface BaseIndexPatternColumn extends Operation {
// Private
operationType: string;
+ sourceField: string;
suggestedPriority?: DimensionPriority;
}
@@ -35,6 +36,5 @@ export type ParameterlessIndexPatternColumn<
> = TBase & { operationType: TOperationType };
export interface FieldBasedIndexPatternColumn extends BaseIndexPatternColumn {
- sourceField: string;
suggestedPriority?: DimensionPriority;
}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/count.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/count.tsx
index 94cb17b340c36..d86e688fca013 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/count.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/count.tsx
@@ -7,6 +7,7 @@
import { i18n } from '@kbn/i18n';
import { OperationDefinition } from '.';
import { ParameterlessIndexPatternColumn, BaseIndexPatternColumn } from './column_types';
+import { IndexPatternField } from '../../types';
const countLabel = i18n.translate('xpack.lens.indexPattern.countOf', {
defaultMessage: 'Count of records',
@@ -23,14 +24,23 @@ export const countOperation: OperationDefinition = {
displayName: i18n.translate('xpack.lens.indexPattern.count', {
defaultMessage: 'Count',
}),
- getPossibleOperationForDocument: () => {
+ onFieldChange: (oldColumn, indexPattern, field) => {
return {
- dataType: 'number',
- isBucketed: false,
- scale: 'ratio',
+ ...oldColumn,
+ label: field.name,
+ sourceField: field.name,
};
},
- buildColumn({ suggestedPriority }) {
+ getPossibleOperationForField: (field: IndexPatternField) => {
+ if (field.type === 'document') {
+ return {
+ dataType: 'number',
+ isBucketed: false,
+ scale: 'ratio',
+ };
+ }
+ },
+ buildColumn({ suggestedPriority, field }) {
return {
label: countLabel,
dataType: 'number',
@@ -38,6 +48,7 @@ export const countOperation: OperationDefinition = {
suggestedPriority,
isBucketed: false,
scale: 'ratio',
+ sourceField: field.name,
};
},
toEsAggsConfig: (column, columnId) => ({
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.test.tsx
index f984597a8eb4b..d19493d579b64 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.test.tsx
@@ -8,17 +8,37 @@ import React from 'react';
import { DateHistogramIndexPatternColumn } from './date_histogram';
import { dateHistogramOperation } from '.';
import { shallow } from 'enzyme';
-import { EuiRange, EuiSwitch } from '@elastic/eui';
+import { EuiSwitch } from '@elastic/eui';
import {
UiSettingsClientContract,
SavedObjectsClientContract,
HttpServiceBase,
} from 'src/core/public';
-import { Storage } from 'ui/storage';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { createMockedIndexPattern } from '../../mocks';
import { IndexPatternPrivateState } from '../../types';
jest.mock('ui/new_platform');
+jest.mock('ui/chrome', () => ({
+ getUiSettingsClient: () => ({
+ get(path: string) {
+ if (path === 'histogram:maxBars') {
+ return 10;
+ }
+ },
+ }),
+}));
+
+const defaultOptions = {
+ storage: {} as IStorageWrapper,
+ uiSettings: {} as UiSettingsClientContract,
+ savedObjectsClient: {} as SavedObjectsClientContract,
+ dateRange: {
+ fromDate: 'now-1y',
+ toDate: 'now',
+ },
+ http: {} as HttpServiceBase,
+};
describe('date_histogram', () => {
let state: IndexPatternPrivateState;
@@ -72,7 +92,7 @@ describe('date_histogram', () => {
// Private
operationType: 'date_histogram',
params: {
- interval: 'w',
+ interval: '42w',
},
sourceField: 'timestamp',
},
@@ -118,6 +138,27 @@ describe('date_histogram', () => {
};
});
+ function stateWithInterval(interval: string) {
+ return ({
+ ...state,
+ layers: {
+ ...state.layers,
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: {
+ ...state.layers.first.columns.col1,
+ params: {
+ interval,
+ },
+ },
+ },
+ },
+ },
+ } as unknown) as IndexPatternPrivateState;
+ }
+
describe('buildColumn', () => {
it('should create column object with auto interval for primary time field', () => {
const column = dateHistogramOperation.buildColumn({
@@ -188,7 +229,7 @@ describe('date_histogram', () => {
expect(esAggsConfig).toEqual(
expect.objectContaining({
params: expect.objectContaining({
- interval: 'w',
+ interval: '42w',
field: 'timestamp',
}),
})
@@ -217,7 +258,7 @@ describe('date_histogram', () => {
expect(column.label).toContain('start_date');
});
- it('should change interval from auto when switching to a non primary time field', () => {
+ it('should not change interval from auto when switching to a non primary time field', () => {
const oldColumn: DateHistogramIndexPatternColumn = {
operationType: 'date_histogram',
sourceField: 'timestamp',
@@ -233,7 +274,7 @@ describe('date_histogram', () => {
const column = dateHistogramOperation.onFieldChange(oldColumn, indexPattern, newDateField);
expect(column).toHaveProperty('sourceField', 'start_date');
- expect(column).toHaveProperty('params.interval', 'd');
+ expect(column).toHaveProperty('params.interval', 'auto');
expect(column.label).toContain('start_date');
});
});
@@ -281,7 +322,7 @@ describe('date_histogram', () => {
);
});
- it('should remove time zone param and normalize interval param', () => {
+ it('should retain interval', () => {
const transferedColumn = dateHistogramOperation.transfer!(
{
dataType: 'date',
@@ -309,7 +350,7 @@ describe('date_histogram', () => {
expect(transferedColumn).toEqual(
expect.objectContaining({
params: {
- interval: 'M',
+ interval: '20s',
timeZone: undefined,
},
})
@@ -322,55 +363,49 @@ describe('date_histogram', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
- expect(instance.find(EuiRange).prop('value')).toEqual(1);
+ expect(instance.find('[data-test-subj="lensDateHistogramValue"]').prop('value')).toEqual(42);
+ expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('value')).toEqual('w');
});
it('should render current value for other index pattern', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
- expect(instance.find(EuiRange).prop('value')).toEqual(2);
+ expect(instance.find('[data-test-subj="lensDateHistogramValue"]').prop('value')).toEqual('');
+ expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('value')).toEqual('d');
});
- it('should render disabled switch and no time intervals control for auto interval', () => {
+ it('should render disabled switch and no time interval control for auto interval', () => {
const instance = shallow(
);
- expect(instance.find(EuiRange).exists()).toBe(false);
+ expect(instance.find('[data-test-subj="lensDateHistogramValue"]').exists()).toBeFalsy();
+ expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').exists()).toBeFalsy();
expect(instance.find(EuiSwitch).prop('checked')).toBe(false);
});
@@ -378,15 +413,12 @@ describe('date_histogram', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
instance.find(EuiSwitch).prop('onChange')!({
@@ -394,57 +426,124 @@ describe('date_histogram', () => {
} as React.ChangeEvent);
expect(setStateSpy).toHaveBeenCalled();
const newState = setStateSpy.mock.calls[0][0];
- expect(newState).toHaveProperty('layers.third.columns.col1.params.interval', 'd');
+ expect(newState).toHaveProperty('layers.third.columns.col1.params.interval', '30d');
});
- it('should update state with the interval value', () => {
+ it('should force calendar values to 1', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
+ instance.find('[data-test-subj="lensDateHistogramValue"]').prop('onChange')!({
+ target: {
+ value: '2',
+ },
+ } as React.ChangeEvent);
+ expect(setStateSpy).toHaveBeenCalledWith(stateWithInterval('1w'));
+ });
- instance.find(EuiRange).prop('onChange')!(
- {
- target: {
- value: '2',
- },
- } as React.ChangeEvent,
- true
+ it('should display error if an invalid interval is specified', () => {
+ const setStateSpy = jest.fn();
+ const testState = stateWithInterval('4quid');
+ const instance = shallow(
+
);
- expect(setStateSpy).toHaveBeenCalledWith({
- ...state,
- layers: {
- ...state.layers,
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: {
- ...state.layers.first.columns.col1,
- params: {
- interval: 'd',
- },
- },
- },
- },
+ expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeTruthy();
+ });
+
+ it('should not display error if interval value is blank', () => {
+ const setStateSpy = jest.fn();
+ const testState = stateWithInterval('d');
+ const instance = shallow(
+
+ );
+ expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeFalsy();
+ });
+
+ it('should display error if interval value is 0', () => {
+ const setStateSpy = jest.fn();
+ const testState = stateWithInterval('0d');
+ const instance = shallow(
+
+ );
+ expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeTruthy();
+ });
+
+ it('should update the unit', () => {
+ const setStateSpy = jest.fn();
+ const instance = shallow(
+
+ );
+ instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('onChange')!({
+ target: {
+ value: 'd',
},
- });
+ } as React.ChangeEvent);
+ expect(setStateSpy).toHaveBeenCalledWith(stateWithInterval('42d'));
+ });
+
+ it('should update the value', () => {
+ const setStateSpy = jest.fn();
+ const testState = stateWithInterval('42d');
+
+ const instance = shallow(
+
+ );
+ instance.find('[data-test-subj="lensDateHistogramValue"]').prop('onChange')!({
+ target: {
+ value: '9',
+ },
+ } as React.ChangeEvent);
+ expect(setStateSpy).toHaveBeenCalledWith(stateWithInterval('9d'));
});
it('should not render options if they are restricted', () => {
const setStateSpy = jest.fn();
const instance = shallow(
{
columnId="col1"
layerId="first"
currentColumn={state.layers.first.columns.col1 as DateHistogramIndexPatternColumn}
- storage={{} as Storage}
- uiSettings={{} as UiSettingsClientContract}
- savedObjectsClient={{} as SavedObjectsClientContract}
- http={{} as HttpServiceBase}
/>
);
- expect(instance.find(EuiRange)).toHaveLength(0);
+ expect(instance.find('[data-test-subj="lensDateHistogramValue"]').exists()).toBeFalsy();
});
});
});
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx
index e5c00542df7d3..017dccab64607 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx
@@ -7,31 +7,29 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { EuiForm, EuiFormRow, EuiRange, EuiSwitch } from '@elastic/eui';
+
+// TODO: make this new-platform compatible
+import { isValidInterval } from 'ui/agg_types/utils';
+
+import {
+ EuiForm,
+ EuiFormRow,
+ EuiSwitch,
+ EuiFieldNumber,
+ EuiSelect,
+ EuiFlexItem,
+ EuiFlexGroup,
+ EuiTextColor,
+ EuiSpacer,
+} from '@elastic/eui';
import { updateColumnParam } from '../../state_helpers';
import { OperationDefinition } from '.';
import { FieldBasedIndexPatternColumn } from './column_types';
-import { IndexPattern } from '../../types';
-
-type PropType = C extends React.ComponentType ? P : unknown;
+import { autoIntervalFromDateRange } from '../../auto_date';
+import { AggregationRestrictions } from '../../types';
const autoInterval = 'auto';
-const supportedIntervals = ['M', 'w', 'd', 'h', 'm'];
-const defaultCustomInterval = supportedIntervals[2];
-
-// Add ticks to EuiRange component props
-const FixedEuiRange = (EuiRange as unknown) as React.ComponentType<
- PropType & {
- ticks?: Array<{
- label: string;
- value: number;
- }>;
- }
->;
-
-function supportsAutoInterval(fieldName: string, indexPattern: IndexPattern): boolean {
- return indexPattern.timeFieldName ? indexPattern.timeFieldName === fieldName : false;
-}
+const calendarOnlyIntervals = new Set(['w', 'M', 'q', 'y']);
export interface DateHistogramIndexPatternColumn extends FieldBasedIndexPatternColumn {
operationType: 'date_histogram';
@@ -59,12 +57,11 @@ export const dateHistogramOperation: OperationDefinition {
return {
...oldColumn,
label: field.name,
sourceField: field.name,
- params: {
- ...oldColumn.params,
- // If we have an "auto" interval but the field we're switching to doesn't support auto intervals
- // we use the default custom interval instead
- interval:
- oldColumn.params.interval === 'auto' && !supportsAutoInterval(field.name, indexPattern)
- ? defaultCustomInterval
- : oldColumn.params.interval,
- },
};
},
toEsAggsConfig: (column, columnId) => ({
@@ -157,7 +135,7 @@ export const dateHistogramOperation: OperationDefinition {
+ paramEditor: ({ state, setState, currentColumn: currentColumn, layerId, dateRange }) => {
const field =
currentColumn &&
state.indexPatterns[state.layers[layerId].indexPatternId].fields.find(
@@ -166,20 +144,35 @@ export const dateHistogramOperation: OperationDefinition) {
- const interval = ev.target.checked ? defaultCustomInterval : autoInterval;
+ const value = ev.target.checked ? autoIntervalFromDateRange(dateRange) : autoInterval;
+ setState(updateColumnParam({ state, layerId, currentColumn, paramName: 'interval', value }));
+ }
+
+ const setInterval = (newInterval: typeof interval) => {
+ const isCalendarInterval = calendarOnlyIntervals.has(newInterval.unit);
+ const value = `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`;
+
setState(
- updateColumnParam({ state, layerId, currentColumn, paramName: 'interval', value: interval })
+ updateColumnParam({
+ state,
+ layerId,
+ currentColumn,
+ value,
+ paramName: 'interval',
+ })
);
- }
+ };
return (
@@ -187,7 +180,7 @@ export const dateHistogramOperation: OperationDefinition
{intervalIsRestricted ? (
@@ -209,33 +202,101 @@ export const dateHistogramOperation: OperationDefinition
) : (
- ({
- label: interval,
- value: index,
- }))}
- onChange={(
- e: React.ChangeEvent | React.MouseEvent
- ) =>
- setState(
- updateColumnParam({
- state,
- layerId,
- currentColumn,
- paramName: 'interval',
- value: numericToInterval(Number((e.target as HTMLInputElement).value)),
- })
- )
- }
- aria-label={i18n.translate('xpack.lens.indexPattern.dateHistogram.interval', {
- defaultMessage: 'Time intervals',
- })}
- />
+ <>
+
+
+ {
+ setInterval({
+ ...interval,
+ value: e.target.value,
+ });
+ }}
+ />
+
+
+ {
+ setInterval({
+ ...interval,
+ unit: e.target.value,
+ });
+ }}
+ isInvalid={!isValid}
+ options={[
+ {
+ value: 'ms',
+ text: i18n.translate(
+ 'xpack.lens.indexPattern.dateHistogram.milliseconds',
+ {
+ defaultMessage: 'milliseconds',
+ }
+ ),
+ },
+ {
+ value: 's',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.seconds', {
+ defaultMessage: 'seconds',
+ }),
+ },
+ {
+ value: 'm',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.minutes', {
+ defaultMessage: 'minutes',
+ }),
+ },
+ {
+ value: 'h',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.hours', {
+ defaultMessage: 'hours',
+ }),
+ },
+ {
+ value: 'd',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.days', {
+ defaultMessage: 'days',
+ }),
+ },
+ {
+ value: 'w',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.week', {
+ defaultMessage: 'week',
+ }),
+ },
+ {
+ value: 'M',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.month', {
+ defaultMessage: 'month',
+ }),
+ },
+ // Quarterly intervals appear to be unsupported by esaggs
+ {
+ value: 'y',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.year', {
+ defaultMessage: 'year',
+ }),
+ },
+ ]}
+ />
+
+
+ {!isValid && (
+ <>
+
+
+ {i18n.translate('xpack.lens.indexPattern.invalidInterval', {
+ defaultMessage: 'Invalid interval value',
+ })}
+
+ >
+ )}
+ >
)}
)}
@@ -243,3 +304,26 @@ export const dateHistogramOperation: OperationDefinition {
columnId: string;
layerId: string;
uiSettings: UiSettingsClientContract;
- storage: Storage;
+ storage: IStorageWrapper;
savedObjectsClient: SavedObjectsClientContract;
http: HttpServiceBase;
+ dateRange: DateRange;
}
interface BaseOperationDefinitionProps {
@@ -140,26 +142,14 @@ interface FieldBasedOperationDefinition
onFieldChange: (oldColumn: C, indexPattern: IndexPattern, field: IndexPatternField) => C;
}
-interface DocumentBasedOperationDefinition
- extends BaseOperationDefinitionProps {
- /**
- * Returns the meta data of the operation if applied to documents of the given index pattern.
- * Undefined if the operation is not applicable to the index pattern.
- */
- getPossibleOperationForDocument: (indexPattern: IndexPattern) => OperationMetadata | undefined;
- buildColumn: (arg: BaseBuildColumnArgs) => C;
-}
-
/**
* Shape of an operation definition. If the type parameter of the definition
* indicates a field based column, `getPossibleOperationForField` has to be
* specified, otherwise `getPossibleOperationForDocument` has to be defined.
*/
-export type OperationDefinition<
- C extends BaseIndexPatternColumn
-> = C extends FieldBasedIndexPatternColumn
- ? FieldBasedOperationDefinition
- : DocumentBasedOperationDefinition;
+export type OperationDefinition = FieldBasedOperationDefinition<
+ C
+>;
// Helper to to infer the column type out of the operation definition.
// This is done to avoid it to have to list out the column types along with
@@ -185,9 +175,7 @@ export type OperationType = (typeof internalOperationDefinitions)[number]['type'
* This is an operation definition of an unspecified column out of all possible
* column types. It
*/
-export type GenericOperationDefinition =
- | FieldBasedOperationDefinition
- | DocumentBasedOperationDefinition;
+export type GenericOperationDefinition = FieldBasedOperationDefinition;
/**
* List of all available operation definitions
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx
index df5bfac6d03a4..e57745c11fc69 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx
@@ -12,7 +12,7 @@ import {
SavedObjectsClientContract,
HttpServiceBase,
} from 'src/core/public';
-import { Storage } from 'ui/storage';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { createMockedIndexPattern } from '../../mocks';
import { TermsIndexPatternColumn } from './terms';
import { termsOperation } from '.';
@@ -20,6 +20,14 @@ import { IndexPatternPrivateState } from '../../types';
jest.mock('ui/new_platform');
+const defaultProps = {
+ storage: {} as IStorageWrapper,
+ uiSettings: {} as UiSettingsClientContract,
+ savedObjectsClient: {} as SavedObjectsClientContract,
+ dateRange: { fromDate: 'now-1d', toDate: 'now' },
+ http: {} as HttpServiceBase,
+};
+
describe('terms', () => {
let state: IndexPatternPrivateState;
const InlineOptions = termsOperation.paramEditor!;
@@ -40,8 +48,6 @@ describe('terms', () => {
label: 'Top value of category',
dataType: 'string',
isBucketed: true,
-
- // Private
operationType: 'terms',
params: {
orderBy: { type: 'alphabetical' },
@@ -54,8 +60,7 @@ describe('terms', () => {
label: 'Count',
dataType: 'number',
isBucketed: false,
-
- // Private
+ sourceField: 'Records',
operationType: 'count',
},
},
@@ -206,8 +211,7 @@ describe('terms', () => {
label: 'Count',
dataType: 'number',
isBucketed: false,
-
- // Private
+ sourceField: 'Records',
operationType: 'count',
},
},
@@ -247,8 +251,7 @@ describe('terms', () => {
label: 'Count',
dataType: 'number',
isBucketed: false,
-
- // Private
+ sourceField: 'Records',
operationType: 'count',
},
});
@@ -324,15 +327,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -350,15 +350,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -398,15 +395,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -422,15 +416,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -467,15 +458,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -486,15 +474,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/operations.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/operations.test.ts
index 82a93ee2a05e1..0161b93effc52 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/operations.test.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/operations.test.ts
@@ -8,6 +8,7 @@ import { getOperationTypesForField, getAvailableOperationsByMetadata, buildColum
import { AvgIndexPatternColumn, MinIndexPatternColumn } from './definitions/metrics';
import { CountIndexPatternColumn } from './definitions/count';
import { IndexPatternPrivateState } from '../types';
+import { documentField } from '../document_field';
jest.mock('ui/new_platform');
jest.mock('../loader');
@@ -179,6 +180,7 @@ describe('getOperationTypesForField', () => {
columns: state.layers.first.columns,
suggestedPriority: 0,
op: 'count',
+ field: documentField,
});
expect(column.operationType).toEqual('count');
});
@@ -216,7 +218,7 @@ describe('getOperationTypesForField', () => {
indexPattern: expectedIndexPatterns[1],
columns: state.layers.first.columns,
suggestedPriority: 0,
- asDocumentOperation: true,
+ field: documentField,
}) as CountIndexPatternColumn;
expect(column.operationType).toEqual('count');
});
@@ -296,10 +298,6 @@ describe('getOperationTypesForField', () => {
"operationType": "sum",
"type": "field",
},
- Object {
- "operationType": "count",
- "type": "document",
- },
],
},
]
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/operations.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/operations.ts
index f2ab68612868c..ecd0942eef7b4 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/operations.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/operations.ts
@@ -14,6 +14,7 @@ import {
IndexPatternColumn,
} from './definitions';
import { IndexPattern, IndexPatternField } from '../types';
+import { documentField } from '../document_field';
/**
* Returns all available operation types as a list at runtime.
@@ -68,9 +69,21 @@ export function getOperationTypesForField(field: IndexPatternField) {
.map(({ type }) => type);
}
-type OperationFieldTuple =
- | { type: 'field'; operationType: OperationType; field: string }
- | { type: 'document'; operationType: OperationType };
+let documentOperations: Set;
+
+export function isDocumentOperation(type: string) {
+ // This can't be done at the root level, because it breaks tests, thanks to mocking oddities
+ // so we do it here, and cache the result.
+ documentOperations =
+ documentOperations || new Set(getOperationTypesForField(documentField) as string[]);
+ return documentOperations.has(type);
+}
+
+interface OperationFieldTuple {
+ type: 'field';
+ operationType: OperationType;
+ field: string;
+}
/**
* Returns all possible operations (matches between operations and fields of the index
@@ -119,11 +132,6 @@ export function getAvailableOperationsByMetadata(indexPattern: IndexPattern) {
};
operationDefinitions.forEach(operationDefinition => {
- addToMap(
- { type: 'document', operationType: operationDefinition.type },
- getPossibleOperationForDocument(operationDefinition, indexPattern)
- );
-
indexPattern.fields.forEach(field => {
addToMap(
{
@@ -139,15 +147,6 @@ export function getAvailableOperationsByMetadata(indexPattern: IndexPattern) {
return Object.values(operationByMetadata);
}
-function getPossibleOperationForDocument(
- operationDefinition: GenericOperationDefinition,
- indexPattern: IndexPattern
-): OperationMetadata | undefined {
- return 'getPossibleOperationForDocument' in operationDefinition
- ? operationDefinition.getPossibleOperationForDocument(indexPattern)
- : undefined;
-}
-
function getPossibleOperationForField(
operationDefinition: GenericOperationDefinition,
field: IndexPatternField
@@ -203,24 +202,18 @@ export function buildColumn({
layerId,
indexPattern,
suggestedPriority,
- asDocumentOperation,
}: {
op?: OperationType;
columns: Partial>;
suggestedPriority: DimensionPriority | undefined;
layerId: string;
indexPattern: IndexPattern;
- field?: IndexPatternField;
- asDocumentOperation?: boolean;
+ field: IndexPatternField;
}): IndexPatternColumn {
let operationDefinition: GenericOperationDefinition | undefined;
if (op) {
operationDefinition = operationDefinitionMap[op];
- } else if (asDocumentOperation) {
- operationDefinition = getDefinition(definition =>
- Boolean(getPossibleOperationForDocument(definition, indexPattern))
- );
} else if (field) {
operationDefinition = getDefinition(definition =>
Boolean(getPossibleOperationForField(definition, field))
@@ -238,19 +231,14 @@ export function buildColumn({
indexPattern,
};
- // check for the operation for field getter to determine whether
- // this is a field based operation type
- if ('getPossibleOperationForField' in operationDefinition) {
- if (!field) {
- throw new Error(`Invariant error: ${operationDefinition.type} operation requires field`);
- }
- return operationDefinition.buildColumn({
- ...baseOptions,
- field,
- });
- } else {
- return operationDefinition.buildColumn(baseOptions);
+ if (!field) {
+ throw new Error(`Invariant error: ${operationDefinition.type} operation requires field`);
}
+
+ return operationDefinition.buildColumn({
+ ...baseOptions,
+ field,
+ });
}
export { operationDefinitionMap } from './definitions';
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/plugin.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/plugin.tsx
index 9c4835437546e..11bc52fc48378 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/plugin.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/plugin.tsx
@@ -4,17 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Registry } from '@kbn/interpreter/target/common';
import { CoreSetup } from 'src/core/public';
// The following dependencies on ui/* and src/legacy/core_plugins must be mocked when testing
import chrome, { Chrome } from 'ui/chrome';
-import { Storage } from 'ui/storage';
import { npSetup, npStart } from 'ui/new_platform';
-import { ExpressionFunction } from '../../../../../../src/legacy/core_plugins/interpreter/public';
-import { functionsRegistry } from '../../../../../../src/legacy/core_plugins/interpreter/public/registries';
+import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { getIndexPatternDatasource } from './indexpattern';
import { renameColumns } from './rename_columns';
import { autoDate } from './auto_date';
+import { ExpressionsSetup } from '../../../../../../src/plugins/expressions/public';
// TODO these are intermediary types because interpreter is not typed yet
// They can get replaced by references to the real interfaces as soon as they
@@ -22,22 +20,15 @@ import { autoDate } from './auto_date';
export interface IndexPatternDatasourceSetupPlugins {
chrome: Chrome;
- interpreter: InterpreterSetup;
-}
-
-export interface InterpreterSetup {
- functionsRegistry: Registry<
- ExpressionFunction,
- ExpressionFunction
- >;
+ expressions: ExpressionsSetup;
}
class IndexPatternDatasourcePlugin {
constructor() {}
- setup(core: CoreSetup, { interpreter }: IndexPatternDatasourceSetupPlugins) {
- interpreter.functionsRegistry.register(() => renameColumns);
- interpreter.functionsRegistry.register(() => autoDate);
+ setup(core: CoreSetup, { expressions }: IndexPatternDatasourceSetupPlugins) {
+ expressions.registerFunction(renameColumns);
+ expressions.registerFunction(autoDate);
}
stop() {}
@@ -48,9 +39,7 @@ const plugin = new IndexPatternDatasourcePlugin();
export const indexPatternDatasourceSetup = () => {
plugin.setup(npSetup.core, {
chrome,
- interpreter: {
- functionsRegistry,
- },
+ expressions: npSetup.plugins.expressions,
});
return getIndexPatternDatasource({
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/state_helpers.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/state_helpers.test.ts
index 9dbf671dffa90..ad3d3f3816262 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/state_helpers.test.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/state_helpers.test.ts
@@ -54,8 +54,7 @@ describe('state_helpers', () => {
label: 'Count',
dataType: 'number',
isBucketed: false,
-
- // Private
+ sourceField: 'Records',
operationType: 'count',
},
},
@@ -102,8 +101,7 @@ describe('state_helpers', () => {
label: 'Count',
dataType: 'number',
isBucketed: false,
-
- // Private
+ sourceField: 'Records',
operationType: 'count',
},
},
@@ -328,8 +326,7 @@ describe('state_helpers', () => {
label: 'Count',
dataType: 'number',
isBucketed: false,
-
- // Private
+ sourceField: 'Records',
operationType: 'count',
},
},
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts
index 3bf3be41f4c89..9ed5083633314 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts
@@ -20,25 +20,27 @@ export interface IndexPattern {
>;
}
+export type AggregationRestrictions = Partial<
+ Record<
+ string,
+ {
+ agg: string;
+ interval?: number;
+ fixed_interval?: string;
+ calendar_interval?: string;
+ delay?: string;
+ time_zone?: string;
+ }
+ >
+>;
+
export interface IndexPatternField {
name: string;
type: string;
esTypes?: string[];
aggregatable: boolean;
searchable: boolean;
- aggregationRestrictions?: Partial<
- Record<
- string,
- {
- agg: string;
- interval?: number;
- fixed_interval?: string;
- calendar_interval?: string;
- delay?: string;
- time_zone?: string;
- }
- >
- >;
+ aggregationRestrictions?: AggregationRestrictions;
}
export interface IndexPatternLayer {
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/utils.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/utils.ts
index aab991a27856a..fadee01e695d5 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/utils.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/utils.ts
@@ -10,6 +10,15 @@ import {
BaseIndexPatternColumn,
FieldBasedIndexPatternColumn,
} from './operations/definitions/column_types';
+import { DataType } from '../types';
+
+/**
+ * Normalizes the specified operation type. (e.g. document operations
+ * produce 'number')
+ */
+export function normalizeOperationDataType(type: DataType) {
+ return type === 'document' ? 'number' : type;
+}
export function hasField(column: BaseIndexPatternColumn): column is FieldBasedIndexPatternColumn {
return 'sourceField' in column;
diff --git a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts
index 6e860c594f4a5..15d36a7c31169 100644
--- a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts
+++ b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts
@@ -11,9 +11,9 @@ import {
trackUiEvent,
trackSuggestionEvent,
} from './factory';
-import { Storage } from 'src/legacy/core_plugins/data/public/types';
import { coreMock } from 'src/core/public/mocks';
import { HttpServiceBase } from 'kibana/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
jest.useFakeTimers();
@@ -30,7 +30,7 @@ const createMockStorage = () => {
};
describe('Lens UI telemetry', () => {
- let storage: jest.Mocked;
+ let storage: jest.Mocked;
let http: jest.Mocked;
let dateSpy: jest.SpyInstance;
diff --git a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts
index 673910deae339..1a8ec604eda54 100644
--- a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts
+++ b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts
@@ -7,7 +7,7 @@
import moment from 'moment';
import { HttpServiceBase } from 'src/core/public';
-import { Storage } from 'src/legacy/core_plugins/data/public/types';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { BASE_API_URL } from '../../common';
const STORAGE_KEY = 'lens-ui-telemetry';
@@ -43,11 +43,11 @@ export class LensReportManager {
private events: Record> = {};
private suggestionEvents: Record> = {};
- private storage: Storage;
+ private storage: IStorageWrapper;
private http: HttpServiceBase;
private timer: ReturnType;
- constructor({ storage, http }: { storage: Storage; http: HttpServiceBase }) {
+ constructor({ storage, http }: { storage: IStorageWrapper; http: HttpServiceBase }) {
this.storage = storage;
this.http = http;
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_suggestions.test.ts b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_suggestions.test.ts
index 770d8594172f1..c9bfadbefaf5f 100644
--- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_suggestions.test.ts
+++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_suggestions.test.ts
@@ -80,7 +80,9 @@ describe('metric_suggestions', () => {
layerId: 'l1',
changeType: 'unchanged',
},
- ] as TableSuggestion[]).map(table => expect(getSuggestions({ table })).toEqual([]))
+ ] as TableSuggestion[]).map(table =>
+ expect(getSuggestions({ table, keptLayerIds: ['l1'] })).toEqual([])
+ )
);
});
@@ -92,6 +94,7 @@ describe('metric_suggestions', () => {
layerId: 'l1',
changeType: 'unchanged',
},
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -107,4 +110,32 @@ describe('metric_suggestions', () => {
}
`);
});
+
+ test('does not suggest for multiple layers', () => {
+ const suggestions = getSuggestions({
+ table: {
+ columns: [numCol('bytes')],
+ isMultiRow: false,
+ layerId: 'l1',
+ changeType: 'unchanged',
+ },
+ keptLayerIds: ['l1', 'l2'],
+ });
+
+ expect(suggestions).toHaveLength(0);
+ });
+
+ test('does not suggest when the suggestion keeps a different layer', () => {
+ const suggestions = getSuggestions({
+ table: {
+ columns: [numCol('bytes')],
+ isMultiRow: false,
+ layerId: 'newer',
+ changeType: 'initial',
+ },
+ keptLayerIds: ['older'],
+ });
+
+ expect(suggestions).toHaveLength(0);
+ });
});
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_suggestions.ts b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_suggestions.ts
index f2b655a288270..23df3f55f2777 100644
--- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_suggestions.ts
+++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_suggestions.ts
@@ -16,11 +16,14 @@ import chartMetricSVG from '../assets/chart_metric.svg';
export function getSuggestions({
table,
state,
+ keptLayerIds,
}: SuggestionRequest): Array> {
// We only render metric charts for single-row queries. We require a single, numeric column.
if (
table.isMultiRow ||
- table.columns.length > 1 ||
+ keptLayerIds.length > 1 ||
+ (keptLayerIds.length && table.layerId !== keptLayerIds[0]) ||
+ table.columns.length !== 1 ||
table.columns[0].operation.dataType !== 'number'
) {
return [];
diff --git a/x-pack/legacy/plugins/lens/public/persistence/saved_object_store.ts b/x-pack/legacy/plugins/lens/public/persistence/saved_object_store.ts
index 5fa7e3f0aca4a..460cd76e8390d 100644
--- a/x-pack/legacy/plugins/lens/public/persistence/saved_object_store.ts
+++ b/x-pack/legacy/plugins/lens/public/persistence/saved_object_store.ts
@@ -6,8 +6,8 @@
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { SavedObjectAttributes } from 'src/core/server';
-import { Filter } from '@kbn/es-query';
import { Query } from 'src/plugins/data/common';
+import { esFilters } from '../../../../../../src/plugins/data/public';
export interface Document {
id?: string;
@@ -22,7 +22,7 @@ export interface Document {
datasourceStates: Record;
visualization: unknown;
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
};
}
diff --git a/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts b/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts
index 8c0b9cb25300d..562d0f0ef6135 100644
--- a/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts
+++ b/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts
@@ -20,7 +20,7 @@ visualizations.types.registerAlias({
}),
},
title: i18n.translate('xpack.lens.visTypeAlias.title', {
- defaultMessage: 'Lens Visualizations',
+ defaultMessage: 'Lens',
}),
description: i18n.translate('xpack.lens.visTypeAlias.description', {
defaultMessage: `Lens is a simpler way to create basic visualizations`,
diff --git a/x-pack/legacy/plugins/lens/public/types.ts b/x-pack/legacy/plugins/lens/public/types.ts
index 1efa123f4f0a3..b66bb7bee8f8a 100644
--- a/x-pack/legacy/plugins/lens/public/types.ts
+++ b/x-pack/legacy/plugins/lens/public/types.ts
@@ -6,28 +6,33 @@
import { Ast } from '@kbn/interpreter/common';
import { IconType } from '@elastic/eui/src/components/icon/icon';
-import { Filter } from '@kbn/es-query';
import { CoreSetup } from 'src/core/public';
import { Query } from 'src/plugins/data/common';
import { SavedQuery } from 'src/legacy/core_plugins/data/public';
import { KibanaDatatable } from '../../../../../src/legacy/core_plugins/interpreter/common';
import { DragContextState } from './drag_drop';
import { Document } from './persistence';
+import { DateRange } from '../common';
+import { esFilters } from '../../../../../src/plugins/data/public';
// eslint-disable-next-line
export interface EditorFrameOptions {}
export type ErrorCallback = (e: { message: string }) => void;
+export interface PublicAPIProps {
+ state: T;
+ setState: StateSetter;
+ layerId: string;
+ dateRange: DateRange;
+}
+
export interface EditorFrameProps {
onError: ErrorCallback;
doc?: Document;
- dateRange: {
- fromDate: string;
- toDate: string;
- };
+ dateRange: DateRange;
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
savedQuery?: SavedQuery;
// Frame loader (app or embeddable) is expected to call this when it loads and updates
@@ -99,12 +104,14 @@ export interface TableSuggestion {
* * `unchanged` means the table is the same in the currently active configuration
* * `reduced` means the table is a reduced version of the currently active table (some columns dropped, but not all of them)
* * `extended` means the table is an extended version of the currently active table (added one or multiple additional columns)
+ * * `layers` means the change is a change to the layer structure, not to the table
*/
-export type TableChangeType = 'initial' | 'unchanged' | 'reduced' | 'extended';
+export type TableChangeType = 'initial' | 'unchanged' | 'reduced' | 'extended' | 'layers';
export interface DatasourceSuggestion {
state: T;
table: TableSuggestion;
+ keptLayerIds: string[];
}
export interface DatasourceMetaData {
@@ -138,7 +145,7 @@ export interface Datasource {
getDatasourceSuggestionsForField: (state: T, field: unknown) => Array>;
getDatasourceSuggestionsFromCurrentState: (state: T) => Array>;
- getPublicAPI: (state: T, setState: StateSetter, layerId: string) => DatasourcePublicAPI;
+ getPublicAPI: (props: PublicAPIProps) => DatasourcePublicAPI;
}
/**
@@ -171,8 +178,8 @@ export interface DatasourceDataPanelProps {
setState: StateSetter;
core: Pick;
query: Query;
- dateRange: FramePublicAPI['dateRange'];
- filters: Filter[];
+ dateRange: DateRange;
+ filters: esFilters.Filter[];
}
// The only way a visualization has to restrict the query building
@@ -200,7 +207,7 @@ export interface DatasourceLayerPanelProps {
layerId: string;
}
-export type DataType = 'string' | 'number' | 'date' | 'boolean' | 'ip';
+export type DataType = 'document' | 'string' | 'number' | 'date' | 'boolean' | 'ip';
// An operation represents a column in a table, not any information
// about how the column was created such as whether it is a sum or average.
@@ -257,6 +264,10 @@ export interface SuggestionRequest {
* State is only passed if the visualization is active.
*/
state?: T;
+ /**
+ * The visualization needs to know which table is being suggested
+ */
+ keptLayerIds: string[];
}
/**
@@ -296,12 +307,9 @@ export interface VisualizationSuggestion {
export interface FramePublicAPI {
datasourceLayers: Record;
- dateRange: {
- fromDate: string;
- toDate: string;
- };
+ dateRange: DateRange;
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
// Adds a new layer. This has a side effect of updating the datasource state
addNewLayer: () => string;
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/__snapshots__/xy_expression.test.tsx.snap b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/__snapshots__/xy_expression.test.tsx.snap
index 473ee16ffe0c3..5089a3b8a3a22 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/__snapshots__/xy_expression.test.tsx.snap
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/__snapshots__/xy_expression.test.tsx.snap
@@ -150,12 +150,16 @@ exports[`xy_expression XYChart component it renders area 1`] = `
Object {
"Label A": 1,
"Label B": 2,
+ "Label D": "Foo",
"c": "I",
+ "d": "Foo",
},
Object {
"Label A": 1,
"Label B": 5,
+ "Label D": "Bar",
"c": "J",
+ "d": "Bar",
},
]
}
@@ -164,7 +168,7 @@ exports[`xy_expression XYChart component it renders area 1`] = `
key="0"
splitSeriesAccessors={
Array [
- "Label D",
+ "d",
]
}
stackAccessors={Array []}
@@ -332,12 +336,16 @@ exports[`xy_expression XYChart component it renders bar 1`] = `
Object {
"Label A": 1,
"Label B": 2,
+ "Label D": "Foo",
"c": "I",
+ "d": "Foo",
},
Object {
"Label A": 1,
"Label B": 5,
+ "Label D": "Bar",
"c": "J",
+ "d": "Bar",
},
]
}
@@ -346,7 +354,7 @@ exports[`xy_expression XYChart component it renders bar 1`] = `
key="0"
splitSeriesAccessors={
Array [
- "Label D",
+ "d",
]
}
stackAccessors={Array []}
@@ -514,12 +522,16 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = `
Object {
"Label A": 1,
"Label B": 2,
+ "Label D": "Foo",
"c": "I",
+ "d": "Foo",
},
Object {
"Label A": 1,
"Label B": 5,
+ "Label D": "Bar",
"c": "J",
+ "d": "Bar",
},
]
}
@@ -528,7 +540,7 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = `
key="0"
splitSeriesAccessors={
Array [
- "Label D",
+ "d",
]
}
stackAccessors={Array []}
@@ -696,12 +708,16 @@ exports[`xy_expression XYChart component it renders line 1`] = `
Object {
"Label A": 1,
"Label B": 2,
+ "Label D": "Foo",
"c": "I",
+ "d": "Foo",
},
Object {
"Label A": 1,
"Label B": 5,
+ "Label D": "Bar",
"c": "J",
+ "d": "Bar",
},
]
}
@@ -710,7 +726,7 @@ exports[`xy_expression XYChart component it renders line 1`] = `
key="0"
splitSeriesAccessors={
Array [
- "Label D",
+ "d",
]
}
stackAccessors={Array []}
@@ -878,12 +894,16 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = `
Object {
"Label A": 1,
"Label B": 2,
+ "Label D": "Foo",
"c": "I",
+ "d": "Foo",
},
Object {
"Label A": 1,
"Label B": 5,
+ "Label D": "Bar",
"c": "J",
+ "d": "Bar",
},
]
}
@@ -892,7 +912,7 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = `
key="0"
splitSeriesAccessors={
Array [
- "Label D",
+ "d",
]
}
stackAccessors={
@@ -1064,12 +1084,16 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = `
Object {
"Label A": 1,
"Label B": 2,
+ "Label D": "Foo",
"c": "I",
+ "d": "Foo",
},
Object {
"Label A": 1,
"Label B": 5,
+ "Label D": "Bar",
"c": "J",
+ "d": "Bar",
},
]
}
@@ -1078,7 +1102,7 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = `
key="0"
splitSeriesAccessors={
Array [
- "Label D",
+ "d",
]
}
stackAccessors={
@@ -1250,12 +1274,16 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] =
Object {
"Label A": 1,
"Label B": 2,
+ "Label D": "Foo",
"c": "I",
+ "d": "Foo",
},
Object {
"Label A": 1,
"Label B": 5,
+ "Label D": "Bar",
"c": "J",
+ "d": "Bar",
},
]
}
@@ -1264,7 +1292,7 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] =
key="0"
splitSeriesAccessors={
Array [
- "Label D",
+ "d",
]
}
stackAccessors={
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.test.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.test.tsx
index 58c321f34d094..31f1870ee54b4 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.test.tsx
@@ -26,8 +26,9 @@ function sampleArgs() {
},
{ id: 'b', name: 'b', formatHint: { id: 'number', params: { pattern: '000,0' } } },
{ id: 'c', name: 'c', formatHint: { id: 'string' } },
+ { id: 'd', name: 'ColD', formatHint: { id: 'string' } },
],
- rows: [{ a: 1, b: 2, c: 'I' }, { a: 1, b: 5, c: 'J' }],
+ rows: [{ a: 1, b: 2, c: 'I', d: 'Foo' }, { a: 1, b: 5, c: 'J', d: 'Bar' }],
},
},
};
@@ -338,8 +339,8 @@ describe('xy_expression', () => {
);
expect(component.find(LineSeries).prop('data')).toEqual([
- { 'Label A': 1, 'Label B': 2, c: 'I' },
- { 'Label A': 1, 'Label B': 5, c: 'J' },
+ { 'Label A': 1, 'Label B': 2, c: 'I', 'Label D': 'Foo', d: 'Foo' },
+ { 'Label A': 1, 'Label B': 5, c: 'J', 'Label D': 'Bar', d: 'Bar' },
]);
});
@@ -407,7 +408,6 @@ describe('xy_expression', () => {
/>
);
- expect(getFormatSpy).toHaveBeenCalledTimes(2);
expect(getFormatSpy).toHaveBeenCalledWith({ id: 'number' });
});
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx
index f55cd8f99a213..c4cc81239a485 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx
@@ -19,7 +19,7 @@ import {
Position,
} from '@elastic/charts';
import { I18nProvider } from '@kbn/i18n/react';
-import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/types';
+import { ExpressionFunction, KibanaDatatable } from 'src/legacy/core_plugins/interpreter/types';
import { IInterpreterRenderHandlers } from 'src/legacy/core_plugins/expressions/public';
import { EuiIcon, EuiText, IconType, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -243,33 +243,24 @@ export function XYChart({ data, args, formatFactory, timeZone }: XYChartRenderPr
}
const columnToLabelMap = columnToLabel ? JSON.parse(columnToLabel) : {};
-
- const rows = data.tables[layerId].rows.map(row => {
- const newRow: typeof row = {};
-
- // Remap data to { 'Count of records': 5 }
- Object.keys(row).forEach(key => {
- if (columnToLabelMap[key]) {
- newRow[columnToLabelMap[key]] = row[key];
- } else {
- newRow[key] = row[key];
- }
- });
- return newRow;
- });
-
const splitAccessorLabel = columnToLabelMap[splitAccessor];
const yAccessors = accessors.map(accessor => columnToLabelMap[accessor] || accessor);
const idForLegend = splitAccessorLabel || yAccessors;
+ const sanitized = sanitizeRows({
+ splitAccessor,
+ formatFactory,
+ columnToLabelMap,
+ table: data.tables[layerId],
+ });
const seriesProps = {
key: index,
- splitSeriesAccessors: [splitAccessorLabel || splitAccessor],
+ splitSeriesAccessors: sanitized.splitAccessor ? [sanitized.splitAccessor] : [],
stackAccessors: seriesType.includes('stacked') ? [xAccessor] : [],
id: getSpecId(idForLegend),
xAccessor,
yAccessors,
- data: rows,
+ data: sanitized.rows,
xScaleType,
yScaleType,
enableHistogramMode: isHistogram && (seriesType.includes('stacked') || !splitAccessor),
@@ -291,3 +282,40 @@ export function XYChart({ data, args, formatFactory, timeZone }: XYChartRenderPr
);
}
+
+/**
+ * Renames the columns to match the user-configured accessors in
+ * columnToLabelMap. If a splitAccessor is provided, formats the
+ * values in that column.
+ */
+function sanitizeRows({
+ splitAccessor,
+ table,
+ formatFactory,
+ columnToLabelMap,
+}: {
+ splitAccessor?: string;
+ table: KibanaDatatable;
+ formatFactory: FormatFactory;
+ columnToLabelMap: Record;
+}) {
+ const column = table.columns.find(c => c.id === splitAccessor);
+ const formatter = formatFactory(column && column.formatHint);
+
+ return {
+ splitAccessor: column && column.id,
+ rows: table.rows.map(r => {
+ const newRow: typeof r = {};
+
+ if (column) {
+ newRow[column.id] = formatter.convert(r[column.id]);
+ }
+
+ Object.keys(r).forEach(key => {
+ const newKey = columnToLabelMap[key] || key;
+ newRow[newKey] = r[key];
+ });
+ return newRow;
+ }),
+ };
+}
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_suggestions.test.ts b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_suggestions.test.ts
index a205fe433106a..04ff720309d62 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_suggestions.test.ts
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_suggestions.test.ts
@@ -100,7 +100,9 @@ describe('xy_suggestions', () => {
layerId: 'first',
changeType: 'unchanged',
},
- ] as TableSuggestion[]).map(table => expect(getSuggestions({ table })).toEqual([]))
+ ] as TableSuggestion[]).map(table =>
+ expect(getSuggestions({ table, keptLayerIds: [] })).toEqual([])
+ )
);
});
@@ -113,6 +115,7 @@ describe('xy_suggestions', () => {
layerId: 'first',
changeType: 'unchanged',
},
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -144,6 +147,7 @@ describe('xy_suggestions', () => {
layerId: 'first',
changeType: 'unchanged',
},
+ keptLayerIds: [],
});
expect(suggestions).toHaveLength(0);
@@ -157,6 +161,7 @@ describe('xy_suggestions', () => {
layerId: 'first',
changeType: 'unchanged',
},
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -184,6 +189,7 @@ describe('xy_suggestions', () => {
changeType: 'unchanged',
label: 'Datasource title',
},
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -211,6 +217,7 @@ describe('xy_suggestions', () => {
},
],
},
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -225,6 +232,7 @@ describe('xy_suggestions', () => {
layerId: 'first',
changeType: 'reduced',
},
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -254,6 +262,7 @@ describe('xy_suggestions', () => {
changeType: 'unchanged',
},
state: currentState,
+ keptLayerIds: ['first'],
});
expect(suggestions).toHaveLength(1);
@@ -288,6 +297,7 @@ describe('xy_suggestions', () => {
changeType: 'unchanged',
},
state: currentState,
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -328,6 +338,7 @@ describe('xy_suggestions', () => {
changeType: 'unchanged',
},
state: currentState,
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -358,6 +369,7 @@ describe('xy_suggestions', () => {
changeType: 'unchanged',
},
state: currentState,
+ keptLayerIds: [],
});
const suggestion = suggestions[suggestions.length - 1];
@@ -392,6 +404,7 @@ describe('xy_suggestions', () => {
changeType: 'extended',
},
state: currentState,
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -430,6 +443,7 @@ describe('xy_suggestions', () => {
changeType: 'extended',
},
state: currentState,
+ keptLayerIds: [],
});
expect(rest).toHaveLength(0);
@@ -454,6 +468,7 @@ describe('xy_suggestions', () => {
layerId: 'first',
changeType: 'unchanged',
},
+ keptLayerIds: [],
});
expect(suggestionSubset(suggestion)).toMatchInlineSnapshot(`
@@ -490,6 +505,7 @@ describe('xy_suggestions', () => {
layerId: 'first',
changeType: 'unchanged',
},
+ keptLayerIds: [],
});
expect(suggestionSubset(suggestion)).toMatchInlineSnapshot(`
@@ -525,6 +541,7 @@ describe('xy_suggestions', () => {
layerId: 'first',
changeType: 'unchanged',
},
+ keptLayerIds: [],
});
expect(suggestionSubset(suggestion)).toMatchInlineSnapshot(`
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_suggestions.ts b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_suggestions.ts
index 7c7e9caddd31b..33181b7f3a467 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_suggestions.ts
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_suggestions.ts
@@ -19,11 +19,12 @@ import { generateId } from '../id_generator';
import { getIconForSeries } from './state_helpers';
const columnSortOrder = {
- date: 0,
- string: 1,
- ip: 2,
- boolean: 3,
- number: 4,
+ document: 0,
+ date: 1,
+ string: 2,
+ ip: 3,
+ boolean: 4,
+ number: 5,
};
/**
@@ -34,6 +35,7 @@ const columnSortOrder = {
export function getSuggestions({
table,
state,
+ keptLayerIds,
}: SuggestionRequest): Array> {
if (
// We only render line charts for multi-row queries. We require at least
@@ -47,7 +49,7 @@ export function getSuggestions({
return [];
}
- const suggestions = getSuggestionForColumns(table, state);
+ const suggestions = getSuggestionForColumns(table, keptLayerIds, state);
if (suggestions && suggestions instanceof Array) {
return suggestions;
@@ -58,32 +60,35 @@ export function getSuggestions({
function getSuggestionForColumns(
table: TableSuggestion,
+ keptLayerIds: string[],
currentState?: State
): VisualizationSuggestion | Array> | undefined {
const [buckets, values] = partition(table.columns, col => col.operation.isBucketed);
if (buckets.length === 1 || buckets.length === 2) {
const [x, splitBy] = getBucketMappings(table, currentState);
- return getSuggestionsForLayer(
- table.layerId,
- table.changeType,
- x,
- values,
+ return getSuggestionsForLayer({
+ layerId: table.layerId,
+ changeType: table.changeType,
+ xValue: x,
+ yValues: values,
splitBy,
currentState,
- table.label
- );
+ tableLabel: table.label,
+ keptLayerIds,
+ });
} else if (buckets.length === 0) {
const [x, ...yValues] = prioritizeColumns(values);
- return getSuggestionsForLayer(
- table.layerId,
- table.changeType,
- x,
+ return getSuggestionsForLayer({
+ layerId: table.layerId,
+ changeType: table.changeType,
+ xValue: x,
yValues,
- undefined,
+ splitBy: undefined,
currentState,
- table.label
- );
+ tableLabel: table.label,
+ keptLayerIds,
+ });
}
}
@@ -137,15 +142,25 @@ function prioritizeColumns(columns: TableSuggestionColumn[]) {
);
}
-function getSuggestionsForLayer(
- layerId: string,
- changeType: TableChangeType,
- xValue: TableSuggestionColumn,
- yValues: TableSuggestionColumn[],
- splitBy?: TableSuggestionColumn,
- currentState?: State,
- tableLabel?: string
-): VisualizationSuggestion | Array> {
+function getSuggestionsForLayer({
+ layerId,
+ changeType,
+ xValue,
+ yValues,
+ splitBy,
+ currentState,
+ tableLabel,
+ keptLayerIds,
+}: {
+ layerId: string;
+ changeType: TableChangeType;
+ xValue: TableSuggestionColumn;
+ yValues: TableSuggestionColumn[];
+ splitBy?: TableSuggestionColumn;
+ currentState?: State;
+ tableLabel?: string;
+ keptLayerIds: string[];
+}): VisualizationSuggestion | Array> {
const title = getSuggestionTitle(yValues, xValue, tableLabel);
const seriesType: SeriesType = getSeriesType(currentState, layerId, xValue, changeType);
@@ -158,6 +173,7 @@ function getSuggestionsForLayer(
splitBy,
changeType,
xValue,
+ keptLayerIds,
};
const isSameState = currentState && changeType === 'unchanged';
@@ -323,6 +339,7 @@ function buildSuggestion({
splitBy,
changeType,
xValue,
+ keptLayerIds,
}: {
currentState: XYState | undefined;
seriesType: SeriesType;
@@ -332,6 +349,7 @@ function buildSuggestion({
splitBy: TableSuggestionColumn | undefined;
layerId: string;
changeType: TableChangeType;
+ keptLayerIds: string[];
}) {
const newLayer = {
...(getExistingLayer(currentState, layerId) || {}),
@@ -342,13 +360,16 @@ function buildSuggestion({
accessors: yValues.map(col => col.columnId),
};
+ const keptLayers = currentState
+ ? currentState.layers.filter(
+ layer => layer.layerId !== layerId && keptLayerIds.includes(layer.layerId)
+ )
+ : [];
+
const state: State = {
legend: currentState ? currentState.legend : { isVisible: true, position: Position.Right },
preferredSeriesType: seriesType,
- layers: [
- ...(currentState ? currentState.layers.filter(layer => layer.layerId !== layerId) : []),
- newLayer,
- ],
+ layers: [...keptLayers, newLayer],
};
return {
diff --git a/x-pack/legacy/plugins/lens/server/routes/existing_fields.test.ts b/x-pack/legacy/plugins/lens/server/routes/existing_fields.test.ts
index de2da49fd5c0e..1647dcccaed3c 100644
--- a/x-pack/legacy/plugins/lens/server/routes/existing_fields.test.ts
+++ b/x-pack/legacy/plugins/lens/server/routes/existing_fields.test.ts
@@ -10,7 +10,7 @@ describe('existingFields', () => {
function field(name: string, parent?: string) {
return {
name,
- parent,
+ subType: parent ? { multi: { parent } } : undefined,
aggregatable: true,
esTypes: [],
readFromDocValues: true,
diff --git a/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts b/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts
index ed9de067fdc48..ad1af966983fb 100644
--- a/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts
+++ b/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts
@@ -11,10 +11,7 @@ import _ from 'lodash';
import { IScopedClusterClient } from 'src/core/server';
import { CoreSetup } from 'src/core/server';
import { BASE_API_URL } from '../../common';
-import {
- FieldDescriptor,
- IndexPatternsService,
-} from '../../../../../../src/legacy/server/index_patterns/service';
+import { FieldDescriptor, IndexPatternsFetcher } from '../../../../../../src/plugins/data/server';
/**
* The number of docs to sample to determine field empty status.
@@ -42,11 +39,11 @@ export async function existingFieldsRoute(setup: CoreSetup) {
async (context, req, res) => {
const { indexPatternTitle } = req.params;
const requestClient = context.core.elasticsearch.dataClient;
- const indexPatternsService = new IndexPatternsService(requestClient.callAsCurrentUser);
+ const indexPatternsFetcher = new IndexPatternsFetcher(requestClient.callAsCurrentUser);
const { fromDate, toDate, timeFieldName } = req.query;
try {
- const fields = await indexPatternsService.getFieldsForWildcard({
+ const fields = await indexPatternsFetcher.getFieldsForWildcard({
pattern: indexPatternTitle,
// TODO: Pull this from kibana advanced settings
metaFields: ['_source', '_id', '_type', '_index', '_score'],
@@ -112,11 +109,14 @@ export function existingFields(
docs: Array<{ _source: Document }>,
fields: FieldDescriptor[]
): string[] {
- const allFields = fields.map(field => ({
- name: field.name,
- parent: field.parent,
- path: (field.parent || field.name).split('.'),
- }));
+ const allFields = fields.map(field => {
+ const parent = field.subType && field.subType.multi && field.subType.multi.parent;
+ return {
+ name: field.name,
+ parent,
+ path: (parent || field.name).split('.'),
+ };
+ });
const missingFields = new Set(allFields);
for (const doc of docs) {
diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap
index 41b5d5a70ae67..9d5e91c2d5f16 100644
--- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap
+++ b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap
@@ -330,7 +330,11 @@ exports[`UploadLicense should display a modal when license requires acknowledgem
as="div"
autoFocus={true}
disabled={false}
- lockProps={Object {}}
+ lockProps={
+ Object {
+ "style": undefined,
+ }
+ }
noFocusGuards={false}
persistentFocus={false}
returnFocus={true}
diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js
index 3bb9d48741ab9..739e98beec10f 100644
--- a/x-pack/legacy/plugins/maps/index.js
+++ b/x-pack/legacy/plugins/maps/index.js
@@ -16,7 +16,7 @@ import { watchStatusAndLicenseToInitialize } from
'../../server/lib/watch_status_and_license_to_initialize';
import { initTelemetryCollection } from './server/maps_telemetry';
import { i18n } from '@kbn/i18n';
-import { APP_ID, APP_ICON, createMapPath } from './common/constants';
+import { APP_ID, APP_ICON, createMapPath, MAP_SAVED_OBJECT_TYPE } from './common/constants';
import { getAppTitle } from './common/i18n_getters';
import _ from 'lodash';
@@ -43,6 +43,7 @@ export function maps(kibana) {
const mapConfig = serverConfig.get('map');
return {
+ showMapVisualizationTypes: serverConfig.get('xpack.maps.showMapVisualizationTypes'),
showMapsInspectorAdapter: serverConfig.get('xpack.maps.showMapsInspectorAdapter'),
preserveDrawingBuffer: serverConfig.get('xpack.maps.preserveDrawingBuffer'),
isEmsEnabled: mapConfig.includeElasticMapsService,
@@ -70,7 +71,7 @@ export function maps(kibana) {
}
},
savedObjectsManagement: {
- 'map': {
+ [MAP_SAVED_OBJECT_TYPE]: {
icon: APP_ICON,
defaultSearchField: 'title',
isImportableAndExportable: true,
@@ -92,6 +93,7 @@ export function maps(kibana) {
config(Joi) {
return Joi.object({
enabled: Joi.boolean().default(true),
+ showMapVisualizationTypes: Joi.boolean().default(false),
showMapsInspectorAdapter: Joi.boolean().default(false), // flag used in functional testing
preserveDrawingBuffer: Joi.boolean().default(false), // flag used in functional testing
}).default();
@@ -110,18 +112,18 @@ export function maps(kibana) {
let routesInitialized = false;
xpackMainPlugin.registerFeature({
- id: 'maps',
+ id: APP_ID,
name: i18n.translate('xpack.maps.featureRegistry.mapsFeatureName', {
defaultMessage: 'Maps',
}),
icon: APP_ICON,
- navLinkId: 'maps',
+ navLinkId: APP_ID,
app: [APP_ID, 'kibana'],
- catalogue: ['maps'],
+ catalogue: [APP_ID],
privileges: {
all: {
savedObject: {
- all: ['map', 'query'],
+ all: [MAP_SAVED_OBJECT_TYPE, 'query'],
read: ['index-pattern']
},
ui: ['save', 'show', 'saveQuery'],
@@ -129,7 +131,7 @@ export function maps(kibana) {
read: {
savedObject: {
all: [],
- read: ['map', 'index-pattern', 'query']
+ read: [MAP_SAVED_OBJECT_TYPE, 'index-pattern', 'query']
},
ui: ['show'],
},
@@ -156,7 +158,7 @@ export function maps(kibana) {
{
path: createMapPath('2c9c1f60-1909-11e9-919b-ffe5949a18d2'),
label: sampleDataLinkLabel,
- icon: 'gisApp'
+ icon: APP_ICON
}
]);
server.replacePanelInSampleDatasetDashboard({
@@ -175,7 +177,7 @@ export function maps(kibana) {
{
path: createMapPath('5dd88580-1906-11e9-919b-ffe5949a18d2'),
label: sampleDataLinkLabel,
- icon: 'gisApp'
+ icon: APP_ICON
}
]);
server.replacePanelInSampleDatasetDashboard({
@@ -183,7 +185,7 @@ export function maps(kibana) {
dashboardId: '7adfa750-4c81-11e8-b3d7-01146121b73d',
oldEmbeddableId: '334084f0-52fd-11e8-a160-89cc2ad9e8e2',
embeddableId: '5dd88580-1906-11e9-919b-ffe5949a18d2',
- embeddableType: 'map',
+ embeddableType: MAP_SAVED_OBJECT_TYPE,
embeddableConfig: {
isLayerTOCOpen: true
},
@@ -194,7 +196,7 @@ export function maps(kibana) {
{
path: createMapPath('de71f4f0-1902-11e9-919b-ffe5949a18d2'),
label: sampleDataLinkLabel,
- icon: 'gisApp'
+ icon: APP_ICON
}
]);
server.replacePanelInSampleDatasetDashboard({
@@ -202,13 +204,13 @@ export function maps(kibana) {
dashboardId: 'edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b',
oldEmbeddableId: '06cf9c40-9ee8-11e7-8711-e7a007dcef99',
embeddableId: 'de71f4f0-1902-11e9-919b-ffe5949a18d2',
- embeddableType: 'map',
+ embeddableType: MAP_SAVED_OBJECT_TYPE,
embeddableConfig: {
isLayerTOCOpen: false
},
});
- server.injectUiAppVars('maps', async () => {
+ server.injectUiAppVars(APP_ID, async () => {
return await server.getInjectedUiAppVars('kibana');
});
}
diff --git a/x-pack/legacy/plugins/maps/public/actions/map_actions.js b/x-pack/legacy/plugins/maps/public/actions/map_actions.js
index dbd6eb6ffb39c..33771a355ddd5 100644
--- a/x-pack/legacy/plugins/maps/public/actions/map_actions.js
+++ b/x-pack/legacy/plugins/maps/public/actions/map_actions.js
@@ -14,16 +14,22 @@ import {
getMapReady,
getWaitingForMapReadyLayerListRaw,
getTransientLayerId,
- getTooltipState
+ getTooltipState,
+ getQuery,
} from '../selectors/map_selectors';
import { FLYOUT_STATE } from '../reducers/ui';
import {
cancelRequest,
registerCancelCallback,
- unregisterCancelCallback
+ unregisterCancelCallback,
+ getEventHandlers,
} from '../reducers/non_serializable_instances';
import { updateFlyout } from '../actions/ui_actions';
-import { FEATURE_ID_PROPERTY_NAME, SOURCE_DATA_ID_ORIGIN } from '../../common/constants';
+import {
+ FEATURE_ID_PROPERTY_NAME,
+ LAYER_TYPE,
+ SOURCE_DATA_ID_ORIGIN
+} from '../../common/constants';
export const SET_SELECTED_LAYER = 'SET_SELECTED_LAYER';
export const SET_TRANSIENT_LAYER = 'SET_TRANSIENT_LAYER';
@@ -455,6 +461,14 @@ export function startDataLoad(layerId, dataId, requestToken, meta = {}) {
dispatch(cancelRequest(layer.getPrevRequestToken(dataId)));
}
+ const eventHandlers = getEventHandlers(getState());
+ if (eventHandlers && eventHandlers.onDataLoad) {
+ eventHandlers.onDataLoad({
+ layerId,
+ dataId,
+ });
+ }
+
dispatch({
meta,
type: LAYER_DATA_LOAD_STARTED,
@@ -479,9 +493,26 @@ export function updateSourceDataRequest(layerId, newData) {
}
export function endDataLoad(layerId, dataId, requestToken, data, meta) {
- return async (dispatch) => {
+ return async (dispatch, getState) => {
dispatch(unregisterCancelCallback(requestToken));
- const features = data ? data.features : [];
+
+ const features = data && data.features ? data.features : [];
+
+ const eventHandlers = getEventHandlers(getState());
+ if (eventHandlers && eventHandlers.onDataLoadEnd) {
+ const layer = getLayerById(layerId, getState());
+ const resultMeta = {};
+ if (layer && layer.getType() === LAYER_TYPE.VECTOR) {
+ resultMeta.featuresCount = features.length;
+ }
+
+ eventHandlers.onDataLoadEnd({
+ layerId,
+ dataId,
+ resultMeta
+ });
+ }
+
dispatch(cleanTooltipStateForLayer(layerId, features));
dispatch({
type: LAYER_DATA_LOAD_ENDED,
@@ -502,8 +533,18 @@ export function endDataLoad(layerId, dataId, requestToken, data, meta) {
}
export function onDataLoadError(layerId, dataId, requestToken, errorMessage) {
- return async (dispatch) => {
+ return async (dispatch, getState) => {
dispatch(unregisterCancelCallback(requestToken));
+
+ const eventHandlers = getEventHandlers(getState());
+ if (eventHandlers && eventHandlers.onDataLoadError) {
+ eventHandlers.onDataLoadError({
+ layerId,
+ dataId,
+ errorMessage,
+ });
+ }
+
dispatch(cleanTooltipStateForLayer(layerId));
dispatch({
type: LAYER_DATA_LOAD_ERROR,
@@ -645,15 +686,25 @@ function removeLayerFromLayerList(layerId) {
};
}
-export function setQuery({ query, timeFilters, filters = [] }) {
+export function setQuery({ query, timeFilters, filters = [], refresh = false }) {
+ function generateQueryTimestamp() {
+ return (new Date()).toISOString();
+ }
return async (dispatch, getState) => {
+ const prevQuery = getQuery(getState());
+ const prevTriggeredAt = (prevQuery && prevQuery.queryLastTriggeredAt)
+ ? prevQuery.queryLastTriggeredAt
+ : generateQueryTimestamp();
+
dispatch({
type: SET_QUERY,
timeFilters,
query: {
...query,
- // ensure query changes to trigger re-fetch even when query is the same because "Refresh" clicked
- queryLastTriggeredAt: (new Date()).toISOString(),
+ // ensure query changes to trigger re-fetch when "Refresh" clicked
+ queryLastTriggeredAt: refresh
+ ? generateQueryTimestamp()
+ : prevTriggeredAt,
},
filters,
});
diff --git a/x-pack/legacy/plugins/maps/public/angular/get_initial_layers.test.js b/x-pack/legacy/plugins/maps/public/angular/get_initial_layers.test.js
index b15b94a49cebc..5dc08751347e4 100644
--- a/x-pack/legacy/plugins/maps/public/angular/get_initial_layers.test.js
+++ b/x-pack/legacy/plugins/maps/public/angular/get_initial_layers.test.js
@@ -44,7 +44,6 @@ describe('kibana.yml configured with map.tilemap.url', () => {
expect(layers).toEqual([{
alpha: 1,
__dataRequests: [],
- __injectedData: null,
id: layers[0].id,
applyGlobalQuery: true,
label: null,
@@ -87,7 +86,6 @@ describe('EMS is enabled', () => {
expect(layers).toEqual([{
alpha: 1,
__dataRequests: [],
- __injectedData: null,
id: layers[0].id,
applyGlobalQuery: true,
label: null,
diff --git a/x-pack/legacy/plugins/maps/public/angular/map.html b/x-pack/legacy/plugins/maps/public/angular/map.html
index 7c4f9cb018e33..90d4ddbeb0092 100644
--- a/x-pack/legacy/plugins/maps/public/angular/map.html
+++ b/x-pack/legacy/plugins/maps/public/angular/map.html
@@ -11,7 +11,7 @@
show-save-query="showSaveQuery"
query="query"
saved-query="savedQuery"
- on-query-submit="updateQueryAndDispatch"
+ on-query-submit="onQuerySubmit"
filters="filters"
on-filters-updated="updateFiltersAndDispatch"
index-patterns="indexPatterns"
diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js
index d8f957bd38199..41c618d68a68e 100644
--- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js
+++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js
@@ -7,6 +7,7 @@
import _ from 'lodash';
import chrome from 'ui/chrome';
import 'ui/directives/listen';
+import 'ui/directives/storage';
import React from 'react';
import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
@@ -52,8 +53,9 @@ import {
MAP_SAVED_OBJECT_TYPE,
MAP_APP_PATH
} from '../../common/constants';
-import { FilterStateStore } from '@kbn/es-query';
import { start as data } from '../../../../../../src/legacy/core_plugins/data/public/legacy';
+import { npStart } from 'ui/new_platform';
+import { esFilters } from '../../../../../../src/plugins/data/public';
const { savedQueryService } = data.search.services;
@@ -62,7 +64,7 @@ const REACT_ANCHOR_DOM_ELEMENT_ID = 'react-maps-root';
const app = uiModules.get(MAP_APP_PATH, []);
app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppState, globalState) => {
-
+ const { filterManager } = npStart.plugins.data.query;
const savedMap = $route.current.locals.map;
let unsubscribe;
let initialLayerListConfig;
@@ -98,7 +100,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
$scope.$evalAsync(() => {
// appState
$state.query = $scope.query;
- $state.filters = data.filter.filterManager.getAppFilters();
+ $state.filters = filterManager.getAppFilters();
$state.save();
// globalState
@@ -107,7 +109,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
pause: $scope.refreshConfig.isPaused,
value: $scope.refreshConfig.interval,
};
- globalState.filters = data.filter.filterManager.getGlobalFilters();
+ globalState.filters = filterManager.getGlobalFilters();
globalState.save();
});
}
@@ -196,10 +198,10 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
}
});
/* End of Saved Queries */
- async function onQueryChange({ filters, query, time }) {
+ async function onQueryChange({ filters, query, time, refresh }) {
if (filters) {
- await data.filter.filterManager.setFilters(filters); // Maps and merges filters
- $scope.filters = data.filter.filterManager.getFilters();
+ filterManager.setFilters(filters); // Maps and merges filters
+ $scope.filters = filterManager.getFilters();
}
if (query) {
$scope.query = query;
@@ -208,22 +210,24 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
$scope.time = time;
}
syncAppAndGlobalState();
- dispatchSetQuery();
+ dispatchSetQuery(refresh);
}
- function dispatchSetQuery() {
+ function dispatchSetQuery(refresh) {
store.dispatch(setQuery({
filters: $scope.filters,
query: $scope.query,
- timeFilters: $scope.time
+ timeFilters: $scope.time,
+ refresh,
}));
}
$scope.indexPatterns = [];
- $scope.updateQueryAndDispatch = function ({ dateRange, query }) {
+ $scope.onQuerySubmit = function ({ dateRange, query }) {
onQueryChange({
query,
time: dateRange,
+ refresh: true,
});
};
$scope.updateFiltersAndDispatch = function (filters) {
@@ -243,7 +247,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
function addFilters(newFilters) {
newFilters.forEach(filter => {
- filter.$state = FilterStateStore.APP_STATE;
+ filter.$state = esFilters.FilterStateStore.APP_STATE;
});
$scope.updateFiltersAndDispatch([...$scope.filters, ...newFilters]);
}
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap
index c3d4ff673e3d5..4377fa4725483 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap
@@ -6,7 +6,7 @@ exports[`LayerPanel is rendered 1`] = `
Object {
"appName": "maps",
"data": undefined,
- "store": Storage {
+ "storage": Storage {
"clear": [Function],
"get": [Function],
"remove": [Function],
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js
index 28afabc40bd75..78cb8aa827e35 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js
@@ -30,8 +30,8 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public';
+import { Storage } from '../../../../../../../src/plugins/kibana_utils/public';
-import { Storage } from 'ui/storage';
const localStorage = new Storage(window.localStorage);
// This import will eventually become a dependency injected by the fully deangularized NP plugin.
@@ -154,7 +154,7 @@ export class LayerPanel extends React.Component {
{
+ // take action on data load
+ },
+ onDataLoadEnd: (layerId: string, dataId: string, resultMeta: object) => {
+ // take action on data load end
+ },
+ onDataLoadError: (layerId: string, dataId: string, errorMessage: string) => {
+ // take action on data load error
+ },
+}
+
+const mapEmbeddable = await factory.createFromState(state, input, parent, renderTooltipContent, eventHandlers);
+```
diff --git a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.js b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.js
index ad190f46f6876..53931d1953ab3 100644
--- a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.js
+++ b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.js
@@ -11,7 +11,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
import 'mapbox-gl/dist/mapbox-gl.css';
import { Embeddable, APPLY_FILTER_TRIGGER } from '../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public';
-import { onlyDisabledFiltersChanged } from '../../../../../../src/legacy/core_plugins/data/public';
+import { onlyDisabledFiltersChanged } from '../../../../../../src/plugins/data/public';
import { I18nContext } from 'ui/i18n';
@@ -31,14 +31,14 @@ import {
setOpenTOCDetails,
} from '../actions/ui_actions';
import { getIsLayerTOCOpen, getOpenTOCDetails } from '../selectors/ui_selectors';
-import { getInspectorAdapters } from '../reducers/non_serializable_instances';
+import { getInspectorAdapters, setEventHandlers } from '../reducers/non_serializable_instances';
import { getMapCenter, getMapZoom } from '../selectors/map_selectors';
import { MAP_SAVED_OBJECT_TYPE } from '../../common/constants';
export class MapEmbeddable extends Embeddable {
type = MAP_SAVED_OBJECT_TYPE;
- constructor(config, initialInput, parent, renderTooltipContent) {
+ constructor(config, initialInput, parent, renderTooltipContent, eventHandlers) {
super(
initialInput,
{
@@ -50,6 +50,7 @@ export class MapEmbeddable extends Embeddable {
parent);
this._renderTooltipContent = renderTooltipContent;
+ this._eventHandlers = eventHandlers;
this._layerList = config.layerList;
this._store = createMapStore();
@@ -72,7 +73,7 @@ export class MapEmbeddable extends Embeddable {
}
}
- _dispatchSetQuery({ query, timeRange, filters }) {
+ _dispatchSetQuery({ query, timeRange, filters, refresh }) {
this._prevTimeRange = timeRange;
this._prevQuery = query;
this._prevFilters = filters;
@@ -80,6 +81,7 @@ export class MapEmbeddable extends Embeddable {
filters: filters.filter(filter => !filter.meta.disabled),
query,
timeFilters: timeRange,
+ refresh,
}));
}
@@ -97,6 +99,7 @@ export class MapEmbeddable extends Embeddable {
* @param {ContainerState} containerState
*/
render(domNode) {
+ this._store.dispatch(setEventHandlers(this._eventHandlers));
this._store.dispatch(setReadOnly(true));
this._store.dispatch(disableScrollZoom());
@@ -165,7 +168,8 @@ export class MapEmbeddable extends Embeddable {
this._dispatchSetQuery({
query: this._prevQuery,
timeRange: this._prevTimeRange,
- filters: this._prevFilters
+ filters: this._prevFilters,
+ refresh: true
});
}
diff --git a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js
index 21c289d9eb281..f09726039b0c3 100644
--- a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js
+++ b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js
@@ -123,6 +123,7 @@ export class MapEmbeddableFactory extends EmbeddableFactory {
input,
parent,
renderTooltipContent,
+ eventHandlers,
) {
const layerList = state && state.layerList ? state.layerList : getInitialLayers();
const indexPatterns = await this._getIndexPatterns(layerList);
@@ -137,7 +138,8 @@ export class MapEmbeddableFactory extends EmbeddableFactory {
},
input,
parent,
- renderTooltipContent
+ renderTooltipContent,
+ eventHandlers,
);
}
diff --git a/x-pack/legacy/plugins/maps/public/index_pattern_util.js b/x-pack/legacy/plugins/maps/public/index_pattern_util.js
index ca43826f307eb..da75ced2d02af 100644
--- a/x-pack/legacy/plugins/maps/public/index_pattern_util.js
+++ b/x-pack/legacy/plugins/maps/public/index_pattern_util.js
@@ -28,6 +28,7 @@ export function getTermsFields(fields) {
export function getSourceFields(fields) {
return fields.filter(field => {
// Multi fields are not stored in _source and only exist in index.
- return field.subType !== 'multi';
+ const isMultiField = field.subType && field.subType.multi;
+ return !isMultiField;
});
}
diff --git a/x-pack/legacy/plugins/maps/public/index_pattern_util.test.js b/x-pack/legacy/plugins/maps/public/index_pattern_util.test.js
new file mode 100644
index 0000000000000..aedff273f646b
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/index_pattern_util.test.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+jest.mock('./kibana_services', () => ({}));
+
+import { getSourceFields } from './index_pattern_util';
+
+describe('getSourceFields', () => {
+ test('Should remove multi fields from field list', () => {
+ const fields = [
+ {
+ name: 'agent'
+ },
+ {
+ name: 'agent.keyword',
+ subType: {
+ multi: {
+ parent: 'agent'
+ }
+ }
+ }
+ ];
+ const sourceFields = getSourceFields(fields);
+ expect(sourceFields).toEqual([
+ { name: 'agent' }
+ ]);
+ });
+});
diff --git a/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js b/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js
index 629fb3284ff11..10e528d19785b 100644
--- a/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js
+++ b/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js
@@ -7,7 +7,7 @@
import _ from 'lodash';
import { AbstractLayer } from './layer';
import { VectorLayer } from './vector_layer';
-import { HeatmapStyle } from './styles/heatmap_style';
+import { HeatmapStyle } from './styles/heatmap/heatmap_style';
import { EMPTY_FEATURE_COLLECTION, LAYER_TYPE } from '../../common/constants';
const SCALED_PROPERTY_NAME = '__kbn_heatmap_weight__';//unique name to store scaled value for weighting
diff --git a/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.js b/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.js
index 8d1d1439a967e..9c9aa912f3a39 100644
--- a/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.js
+++ b/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.js
@@ -6,7 +6,7 @@
import { ESTermSource } from '../sources/es_term_source';
-import { VectorStyle } from '../styles/vector_style';
+import { VectorStyle } from '../styles/vector/vector_style';
export class InnerJoin {
diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js
index c8187fd83ee4d..6515ab608c2ea 100644
--- a/x-pack/legacy/plugins/maps/public/layers/layer.js
+++ b/x-pack/legacy/plugins/maps/public/layers/layer.js
@@ -9,7 +9,6 @@ import { EuiIcon, EuiLoadingSpinner } from '@elastic/eui';
import turf from 'turf';
import turfBooleanContains from '@turf/boolean-contains';
import { DataRequest } from './util/data_request';
-import { InjectedData } from './util/injected_data';
import {
MB_SOURCE_ID_LAYER_ID_PREFIX_DELIMITER,
SOURCE_DATA_ID_ORIGIN
@@ -32,11 +31,6 @@ export class AbstractLayer {
} else {
this._dataRequests = [];
}
- if (this._descriptor.__injectedData) {
- this._injectedData = new InjectedData(this._descriptor.__injectedData);
- } else {
- this._injectedData = null;
- }
}
static getBoundDataForSource(mbMap, sourceId) {
@@ -48,7 +42,6 @@ export class AbstractLayer {
const layerDescriptor = { ...options };
layerDescriptor.__dataRequests = _.get(options, '__dataRequests', []);
- layerDescriptor.__injectedData = _.get(options, '__injectedData', null);
layerDescriptor.id = _.get(options, 'id', uuid());
layerDescriptor.label = options.label && options.label.length > 0 ? options.label : null;
layerDescriptor.minZoom = _.get(options, 'minZoom', 0);
@@ -287,10 +280,6 @@ export class AbstractLayer {
return this._dataRequests.find(dataRequest => dataRequest.getDataId() === id);
}
- getInjectedData() {
- return this._injectedData ? this._injectedData.getData() : null;
- }
-
isLayerLoading() {
return this._dataRequests.some(dataRequest => dataRequest.isLoading());
}
@@ -417,5 +406,9 @@ export class AbstractLayer {
mbMap.setLayoutProperty(mbLayerId, 'visibility', this.isVisible() ? 'visible' : 'none');
}
+ getType() {
+ return this._descriptor.type;
+ }
+
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js
index cf876a59d0be4..59cfc7b486bdd 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js
@@ -35,9 +35,32 @@ export class GeojsonFileSource extends AbstractVectorSource {
applyGlobalQuery: DEFAULT_APPLY_GLOBAL_QUERY
}
- static createDescriptor(name) {
+ static createDescriptor(geoJson, name) {
+ // Wrap feature as feature collection if needed
+ let featureCollection;
+
+ if (!geoJson) {
+ featureCollection = {
+ type: 'FeatureCollection',
+ features: []
+ };
+ } else if (geoJson.type === 'FeatureCollection') {
+ featureCollection = geoJson;
+ } else if (geoJson.type === 'Feature') {
+ featureCollection = {
+ type: 'FeatureCollection',
+ features: [geoJson]
+ };
+ } else { // Missing or incorrect type
+ featureCollection = {
+ type: 'FeatureCollection',
+ features: []
+ };
+ }
+
return {
type: GeojsonFileSource.type,
+ __featureCollection: featureCollection,
name
};
}
@@ -85,16 +108,9 @@ export class GeojsonFileSource extends AbstractVectorSource {
onPreviewSource(null);
return;
}
- const sourceDescriptor = GeojsonFileSource.createDescriptor(name);
+ const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
const source = new GeojsonFileSource(sourceDescriptor, inspectorAdapters);
- const featureCollection = (geojsonFile.type === 'Feature')
- ? {
- type: 'FeatureCollection',
- features: [{ ...geojsonFile }]
- }
- : geojsonFile;
-
- onPreviewSource(source, { __injectedData: featureCollection });
+ onPreviewSource(source);
};
};
@@ -125,6 +141,22 @@ export class GeojsonFileSource extends AbstractVectorSource {
);
}
+ async getGeoJsonWithMeta() {
+ const copiedPropsFeatures = this._descriptor.__featureCollection.features
+ .map(feature => ({
+ type: 'Feature',
+ geometry: feature.geometry,
+ properties: feature.properties ? { ...feature.properties } : {}
+ }));
+ return {
+ data: {
+ type: 'FeatureCollection',
+ features: copiedPropsFeatures
+ },
+ meta: {}
+ };
+ }
+
async getDisplayName() {
return this._descriptor.name;
}
@@ -136,8 +168,4 @@ export class GeojsonFileSource extends AbstractVectorSource {
shouldBeIndexed() {
return GeojsonFileSource.isIndexingSource;
}
-
- isInjectedData() {
- return true;
- }
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js
new file mode 100644
index 0000000000000..d9639144dfc52
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js
@@ -0,0 +1,142 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { AbstractESSource } from './es_source';
+import { ESAggMetricTooltipProperty } from '../tooltips/es_aggmetric_tooltip_property';
+import { METRIC_TYPE } from '../../../common/constants';
+import _ from 'lodash';
+
+const COUNT_PROP_LABEL = 'count';
+const COUNT_PROP_NAME = 'doc_count';
+const AGG_DELIMITER = '_of_';
+
+export class AbstractESAggSource extends AbstractESSource {
+
+ static METRIC_SCHEMA_CONFIG = {
+ group: 'metrics',
+ name: 'metric',
+ title: 'Value',
+ min: 1,
+ max: Infinity,
+ aggFilter: [
+ METRIC_TYPE.AVG,
+ METRIC_TYPE.COUNT,
+ METRIC_TYPE.MAX,
+ METRIC_TYPE.MIN,
+ METRIC_TYPE.SUM,
+ METRIC_TYPE.UNIQUE_COUNT
+ ],
+ defaults: [
+ { schema: 'metric', type: METRIC_TYPE.COUNT }
+ ]
+ };
+
+ _formatMetricKey(metric) {
+ const aggType = metric.type;
+ const fieldName = metric.field;
+ return aggType !== METRIC_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${fieldName}` : COUNT_PROP_NAME;
+ }
+
+ _formatMetricLabel(metric) {
+ const aggType = metric.type;
+ const fieldName = metric.field;
+ return aggType !== METRIC_TYPE.COUNT ? `${aggType} of ${fieldName}` : COUNT_PROP_LABEL;
+ }
+
+ _getValidMetrics() {
+ const metrics = _.get(this._descriptor, 'metrics', []).filter(({ type, field }) => {
+ if (type === METRIC_TYPE.COUNT) {
+ return true;
+ }
+
+ if (field) {
+ return true;
+ }
+ return false;
+ });
+ if (metrics.length === 0) {
+ metrics.push({ type: METRIC_TYPE.COUNT });
+ }
+ return metrics;
+ }
+
+ getMetricFields() {
+ return this._getValidMetrics().map(metric => {
+ const metricKey = this._formatMetricKey(metric);
+ const metricLabel = metric.label ? metric.label : this._formatMetricLabel(metric);
+ const metricCopy = { ...metric };
+ delete metricCopy.label;
+ return {
+ ...metricCopy,
+ propertyKey: metricKey,
+ propertyLabel: metricLabel
+ };
+ });
+ }
+
+ async getNumberFields() {
+ return this.getMetricFields().map(({ propertyKey: name, propertyLabel: label }) => {
+ return { label, name };
+ });
+ }
+
+ getFieldNames() {
+ return this.getMetricFields().map(({ propertyKey }) => {
+ return propertyKey;
+ });
+ }
+
+ createMetricAggConfigs() {
+ return this.getMetricFields().map(metric => {
+ const metricAggConfig = {
+ id: metric.propertyKey,
+ enabled: true,
+ type: metric.type,
+ schema: 'metric',
+ params: {}
+ };
+ if (metric.type !== METRIC_TYPE.COUNT) {
+ metricAggConfig.params = { field: metric.field };
+ }
+ return metricAggConfig;
+ });
+ }
+
+ async filterAndFormatPropertiesToHtmlForMetricFields(properties) {
+ let indexPattern;
+ try {
+ indexPattern = await this._getIndexPattern();
+ } catch(error) {
+ console.warn(`Unable to find Index pattern ${this._descriptor.indexPatternId}, values are not formatted`);
+ return properties;
+ }
+
+ const metricFields = this.getMetricFields();
+ const tooltipProperties = [];
+ metricFields.forEach((metricField) => {
+ let value;
+ for (const key in properties) {
+ if (properties.hasOwnProperty(key) && metricField.propertyKey === key) {
+ value = properties[key];
+ break;
+ }
+ }
+
+ const tooltipProperty = new ESAggMetricTooltipProperty(
+ metricField.propertyKey,
+ metricField.propertyLabel,
+ value,
+ indexPattern,
+ metricField
+ );
+ tooltipProperties.push(tooltipProperty);
+ });
+
+ return tooltipProperties;
+
+ }
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.js
index e06568285dd6b..c83f12ce992ff 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.js
@@ -20,8 +20,7 @@ export function convertToGeoJson({ table, renderAs }) {
}
const metricColumns = table.columns.filter(column => {
- return column.aggConfig.type.type === 'metrics'
- && column.aggConfig.type.dslName !== 'geo_centroid';
+ return column.aggConfig.type.type === 'metrics' && column.aggConfig.type.dslName !== 'geo_centroid';
});
const geocentroidColumn = table.columns.find(column => column.aggConfig.type.dslName === 'geo_centroid');
if (!geocentroidColumn) {
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js
index 776980e17bb13..a8b52e586da28 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js
@@ -8,46 +8,29 @@ import React from 'react';
import uuid from 'uuid/v4';
import { VECTOR_SHAPE_TYPES } from '../vector_feature_types';
-import { AbstractESSource } from '../es_source';
import { HeatmapLayer } from '../../heatmap_layer';
import { VectorLayer } from '../../vector_layer';
import { Schemas } from 'ui/vis/editors/default/schemas';
import { AggConfigs } from 'ui/agg_types';
import { tabifyAggResponse } from 'ui/agg_response/tabify';
import { convertToGeoJson } from './convert_to_geojson';
-import { VectorStyle } from '../../styles/vector_style';
-import { vectorStyles } from '../../styles/vector_style_defaults';
+import { VectorStyle } from '../../styles/vector/vector_style';
+import { vectorStyles } from '../../styles/vector/vector_style_defaults';
import { RENDER_AS } from './render_as';
import { CreateSourceEditor } from './create_source_editor';
import { UpdateSourceEditor } from './update_source_editor';
import { GRID_RESOLUTION } from '../../grid_resolution';
-import { SOURCE_DATA_ID_ORIGIN, ES_GEO_GRID, METRIC_TYPE } from '../../../../common/constants';
+import { SOURCE_DATA_ID_ORIGIN, ES_GEO_GRID } from '../../../../common/constants';
import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
+import { AbstractESAggSource } from '../es_agg_source';
const COUNT_PROP_LABEL = 'count';
const COUNT_PROP_NAME = 'doc_count';
const MAX_GEOTILE_LEVEL = 29;
const aggSchemas = new Schemas([
- {
- group: 'metrics',
- name: 'metric',
- title: 'Value',
- min: 1,
- max: Infinity,
- aggFilter: [
- METRIC_TYPE.AVG,
- METRIC_TYPE.COUNT,
- METRIC_TYPE.MAX,
- METRIC_TYPE.MIN,
- METRIC_TYPE.SUM,
- METRIC_TYPE.UNIQUE_COUNT
- ],
- defaults: [
- { schema: 'metric', type: METRIC_TYPE.COUNT }
- ]
- },
+ AbstractESAggSource.METRIC_SCHEMA_CONFIG,
{
group: 'buckets',
name: 'segment',
@@ -58,7 +41,7 @@ const aggSchemas = new Schemas([
}
]);
-export class ESGeoGridSource extends AbstractESSource {
+export class ESGeoGridSource extends AbstractESAggSource {
static type = ES_GEO_GRID;
static title = i18n.translate('xpack.maps.source.esGridTitle', {
@@ -140,12 +123,6 @@ export class ESGeoGridSource extends AbstractESSource {
];
}
- getFieldNames() {
- return this.getMetricFields().map(({ propertyKey }) => {
- return propertyKey;
- });
- }
-
isGeoGridPrecisionAware() {
return true;
}
@@ -184,12 +161,6 @@ export class ESGeoGridSource extends AbstractESSource {
}));
}
- async getNumberFields() {
- return this.getMetricFields().map(({ propertyKey: name, propertyLabel: label }) => {
- return { label, name };
- });
- }
-
async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback) {
const indexPattern = await this._getIndexPattern();
const searchSource = await this._makeSearchSource(searchFilters, 0);
@@ -221,29 +192,8 @@ export class ESGeoGridSource extends AbstractESSource {
return true;
}
- _formatMetricKey(metric) {
- return metric.type !== METRIC_TYPE.COUNT ? `${metric.type}_of_${metric.field}` : COUNT_PROP_NAME;
- }
-
- _formatMetricLabel(metric) {
- return metric.type !== METRIC_TYPE.COUNT ? `${metric.type} of ${metric.field}` : COUNT_PROP_LABEL;
- }
-
_makeAggConfigs(precision) {
- const metricAggConfigs = this.getMetricFields().map(metric => {
- const metricAggConfig = {
- id: metric.propertyKey,
- enabled: true,
- type: metric.type,
- schema: 'metric',
- params: {}
- };
- if (metric.type !== METRIC_TYPE.COUNT) {
- metricAggConfig.params = { field: metric.field };
- }
- return metricAggConfig;
- });
-
+ const metricAggConfigs = this.createMetricAggConfigs();
return [
...metricAggConfigs,
{
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js
index 3debfdf1541f7..6cc6ab196f7d8 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js
@@ -8,45 +8,26 @@ import React from 'react';
import uuid from 'uuid/v4';
import { VECTOR_SHAPE_TYPES } from '../vector_feature_types';
-import { AbstractESSource } from '../es_source';
import { VectorLayer } from '../../vector_layer';
import { CreateSourceEditor } from './create_source_editor';
import { UpdateSourceEditor } from './update_source_editor';
-import { VectorStyle } from '../../styles/vector_style';
-import { vectorStyles } from '../../styles/vector_style_defaults';
+import { VectorStyle } from '../../styles/vector/vector_style';
+import { vectorStyles } from '../../styles/vector/vector_style_defaults';
import { i18n } from '@kbn/i18n';
-import { SOURCE_DATA_ID_ORIGIN, ES_PEW_PEW, METRIC_TYPE } from '../../../../common/constants';
+import { SOURCE_DATA_ID_ORIGIN, ES_PEW_PEW } from '../../../../common/constants';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
import { convertToLines } from './convert_to_lines';
import { Schemas } from 'ui/vis/editors/default/schemas';
import { AggConfigs } from 'ui/agg_types';
+import { AbstractESAggSource } from '../es_agg_source';
const COUNT_PROP_LABEL = 'count';
const COUNT_PROP_NAME = 'doc_count';
const MAX_GEOTILE_LEVEL = 29;
-const aggSchemas = new Schemas([
- {
- group: 'metrics',
- name: 'metric',
- title: 'Value',
- min: 1,
- max: Infinity,
- aggFilter: [
- METRIC_TYPE.AVG,
- METRIC_TYPE.COUNT,
- METRIC_TYPE.MAX,
- METRIC_TYPE.MIN,
- METRIC_TYPE.SUM,
- METRIC_TYPE.UNIQUE_COUNT
- ],
- defaults: [
- { schema: 'metric', type: METRIC_TYPE.COUNT }
- ]
- }
-]);
+const aggSchemas = new Schemas([AbstractESAggSource.METRIC_SCHEMA_CONFIG]);
-export class ESPewPewSource extends AbstractESSource {
+export class ESPewPewSource extends AbstractESAggSource {
static type = ES_PEW_PEW;
static title = i18n.translate('xpack.maps.source.pewPewTitle', {
@@ -103,12 +84,6 @@ export class ESPewPewSource extends AbstractESSource {
return true;
}
- async getNumberFields() {
- return this.getMetricFields().map(({ propertyKey: name, propertyLabel: label }) => {
- return { label, name };
- });
- }
-
async getSupportedShapeTypes() {
return [VECTOR_SHAPE_TYPES.LINE];
}
@@ -192,19 +167,7 @@ export class ESPewPewSource extends AbstractESSource {
async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback) {
const indexPattern = await this._getIndexPattern();
- const metricAggConfigs = this.getMetricFields().map(metric => {
- const metricAggConfig = {
- id: metric.propertyKey,
- enabled: true,
- type: metric.type,
- schema: 'metric',
- params: {}
- };
- if (metric.type !== METRIC_TYPE.COUNT) {
- metricAggConfig.params = { field: metric.field };
- }
- return metricAggConfig;
- });
+ const metricAggConfigs = this.createMetricAggConfigs();
const aggConfigs = new AggConfigs(indexPattern, metricAggConfigs, aggSchemas.all);
const searchSource = await this._makeSearchSource(searchFilters, 0);
@@ -258,14 +221,6 @@ export class ESPewPewSource extends AbstractESSource {
};
}
- _formatMetricKey(metric) {
- return metric.type !== METRIC_TYPE.COUNT ? `${metric.type}_of_${metric.field}` : COUNT_PROP_NAME;
- }
-
- _formatMetricLabel(metric) {
- return metric.type !== METRIC_TYPE.COUNT ? `${metric.type} of ${metric.field}` : COUNT_PROP_LABEL;
- }
-
async _getGeoField() {
const indexPattern = await this._getIndexPattern();
const geoField = indexPattern.fields.getByName(this._descriptor.destGeoField);
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
index 85c866479a6ba..cc53ee27af471 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
@@ -15,8 +15,6 @@ import { timefilter } from 'ui/timefilter';
import _ from 'lodash';
import { AggConfigs } from 'ui/agg_types';
import { i18n } from '@kbn/i18n';
-import { ESAggMetricTooltipProperty } from '../tooltips/es_aggmetric_tooltip_property';
-
import uuid from 'uuid/v4';
import { copyPersistentState } from '../../reducers/util';
import { ES_GEO_FIELD_TYPE, METRIC_TYPE } from '../../../common/constants';
@@ -57,80 +55,6 @@ export class AbstractESSource extends AbstractVectorSource {
return clonedDescriptor;
}
- _getValidMetrics() {
- const metrics = _.get(this._descriptor, 'metrics', []).filter(({ type, field }) => {
- if (type === METRIC_TYPE.COUNT) {
- return true;
- }
-
- if (field) {
- return true;
- }
- return false;
- });
- if (metrics.length === 0) {
- metrics.push({ type: METRIC_TYPE.COUNT });
- }
- return metrics;
- }
-
- _formatMetricKey() {
- throw new Error('should implement');
- }
-
- _formatMetricLabel() {
- throw new Error('should implement');
- }
-
- getMetricFields() {
- return this._getValidMetrics().map(metric => {
- const metricKey = this._formatMetricKey(metric);
- const metricLabel = metric.label ? metric.label : this._formatMetricLabel(metric);
- const metricCopy = { ...metric };
- delete metricCopy.label;
- return {
- ...metricCopy,
- propertyKey: metricKey,
- propertyLabel: metricLabel
- };
- });
- }
-
- async filterAndFormatPropertiesToHtmlForMetricFields(properties) {
- let indexPattern;
- try {
- indexPattern = await this._getIndexPattern();
- } catch(error) {
- console.warn(`Unable to find Index pattern ${this._descriptor.indexPatternId}, values are not formatted`);
- return properties;
- }
-
-
- const metricFields = this.getMetricFields();
- const tooltipProperties = [];
- metricFields.forEach((metricField) => {
- let value;
- for (const key in properties) {
- if (properties.hasOwnProperty(key) && metricField.propertyKey === key) {
- value = properties[key];
- break;
- }
- }
-
- const tooltipProperty = new ESAggMetricTooltipProperty(
- metricField.propertyKey,
- metricField.propertyLabel,
- value,
- indexPattern,
- metricField
- );
- tooltipProperties.push(tooltipProperty);
- });
-
- return tooltipProperties;
-
- }
-
async _runEsQuery(requestName, searchSource, registerCancelCallback, requestDescription) {
const abortController = new AbortController();
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js
index 1f5adc00cca6f..7d1ccf7373cf6 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js
@@ -6,34 +6,17 @@
import _ from 'lodash';
-import { AbstractESSource } from './es_source';
import { Schemas } from 'ui/vis/editors/default/schemas';
import { AggConfigs } from 'ui/agg_types';
import { i18n } from '@kbn/i18n';
import { ESTooltipProperty } from '../tooltips/es_tooltip_property';
import { ES_SIZE_LIMIT, METRIC_TYPE } from '../../../common/constants';
+import { AbstractESAggSource } from './es_agg_source';
const TERMS_AGG_NAME = 'join';
const aggSchemas = new Schemas([
- {
- group: 'metrics',
- name: 'metric',
- title: 'Value',
- min: 1,
- max: Infinity,
- aggFilter: [
- METRIC_TYPE.AVG,
- METRIC_TYPE.COUNT,
- METRIC_TYPE.MAX,
- METRIC_TYPE.MIN,
- METRIC_TYPE.SUM,
- METRIC_TYPE.UNIQUE_COUNT
- ],
- defaults: [
- { schema: 'metric', type: METRIC_TYPE.COUNT }
- ]
- },
+ AbstractESAggSource.METRIC_SCHEMA_CONFIG,
{
group: 'buckets',
name: 'segment',
@@ -61,7 +44,7 @@ export function extractPropertiesMap(rawEsData, propertyNames, countPropertyName
return propertiesMap;
}
-export class ESTermSource extends AbstractESSource {
+export class ESTermSource extends AbstractESAggSource {
static type = 'ES_TERM_SOURCE';
@@ -156,20 +139,7 @@ export class ESTermSource extends AbstractESSource {
}
_makeAggConfigs() {
- const metricAggConfigs = this.getMetricFields().map(metric => {
- const metricAggConfig = {
- id: metric.propertyKey,
- enabled: true,
- type: metric.type,
- schema: 'metric',
- params: {}
- };
- if (metric.type !== METRIC_TYPE.COUNT) {
- metricAggConfig.params = { field: metric.field };
- }
- return metricAggConfig;
- });
-
+ const metricAggConfigs = this.createMetricAggConfigs();
return [
...metricAggConfigs,
{
@@ -205,10 +175,4 @@ export class ESTermSource extends AbstractESSource {
return null;
}
}
-
- getFieldNames() {
- return this.getMetricFields().map(({ propertyKey }) => {
- return propertyKey;
- });
- }
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/source.js b/x-pack/legacy/plugins/maps/public/layers/sources/source.js
index f96fc42f02178..3bee49cff6d18 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/source.js
@@ -115,10 +115,6 @@ export class AbstractSource {
return AbstractSource.isIndexingSource;
}
- isInjectedData() {
- return false;
- }
-
supportsElasticsearchFilters() {
return false;
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js
index b3e8c1b019f28..8f67d7618049b 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js
@@ -7,7 +7,7 @@
import { VectorLayer } from '../vector_layer';
import { TooltipProperty } from '../tooltips/tooltip_property';
-import { VectorStyle } from '../styles/vector_style';
+import { VectorStyle } from '../styles/vector/vector_style';
import { AbstractSource } from './source';
import * as topojson from 'topojson-client';
import _ from 'lodash';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss b/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss
index 87c7bd1face64..bd517f81517c2 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss
@@ -1,3 +1,3 @@
@import './components/color_gradient';
@import './components/static_dynamic_style_row';
-@import './components/vector/color/color_stops';
+@import './vector/components/color/color_stops';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/static_dynamic_style_row.js b/x-pack/legacy/plugins/maps/public/layers/styles/components/static_dynamic_style_row.js
index cfe7a0741a194..5537bb90fa245 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/static_dynamic_style_row.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/components/static_dynamic_style_row.js
@@ -5,7 +5,7 @@
*/
import React from 'react';
-import { VectorStyle } from '../vector_style';
+import { VectorStyle } from '../vector/vector_style';
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/__snapshots__/heatmap_style_editor.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.js.snap
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/__snapshots__/heatmap_style_editor.test.js.snap
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.js.snap
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_constants.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_constants.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_constants.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_constants.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.js
similarity index 95%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.js
index 0aa20f29c341b..a0f86dcf5130b 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.js
@@ -8,7 +8,7 @@ import React from 'react';
import { EuiFormRow, EuiSuperSelect } from '@elastic/eui';
import { COLOR_GRADIENTS } from '../../color_utils';
-import { ColorGradient } from '../color_gradient';
+import { ColorGradient } from '../../components/color_gradient';
import {
DEFAULT_RGB_HEATMAP_COLOR_RAMP,
DEFAULT_HEATMAP_COLOR_RAMP_NAME,
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.test.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.test.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/legend/heatmap_legend.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/legend/heatmap_legend.js
similarity index 88%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/legend/heatmap_legend.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/legend/heatmap_legend.js
index 74fce11abf0a6..06709ba0ebf21 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/legend/heatmap_legend.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/legend/heatmap_legend.js
@@ -7,8 +7,8 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
-import { ColorGradient } from '../../color_gradient';
-import { StyleLegendRow } from '../../style_legend_row';
+import { ColorGradient } from '../../../components/color_gradient';
+import { StyleLegendRow } from '../../../components/style_legend_row';
import {
DEFAULT_RGB_HEATMAP_COLOR_RAMP,
DEFAULT_HEATMAP_COLOR_RAMP_NAME,
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/heatmap_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/heatmap_style.js
similarity index 90%
rename from x-pack/legacy/plugins/maps/public/layers/styles/heatmap_style.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/heatmap_style.js
index 5ccabe610a120..e537da8a3e2e4 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/heatmap_style.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/heatmap_style.js
@@ -5,12 +5,12 @@
*/
import React from 'react';
-import { GRID_RESOLUTION } from '../grid_resolution';
-import { AbstractStyle } from './abstract_style';
-import { HeatmapStyleEditor } from './components/heatmap/heatmap_style_editor';
-import { HeatmapLegend } from './components/heatmap/legend/heatmap_legend';
-import { DEFAULT_HEATMAP_COLOR_RAMP_NAME } from './components/heatmap/heatmap_constants';
-import { getColorRampStops } from './color_utils';
+import { GRID_RESOLUTION } from '../../grid_resolution';
+import { AbstractStyle } from '../abstract_style';
+import { HeatmapStyleEditor } from './components/heatmap_style_editor';
+import { HeatmapLegend } from './components/legend/heatmap_legend';
+import { DEFAULT_HEATMAP_COLOR_RAMP_NAME } from './components/heatmap_constants';
+import { getColorRampStops } from '../color_utils';
import { i18n } from '@kbn/i18n';
import { EuiIcon } from '@elastic/eui';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/__snapshots__/vector_style_symbol_editor.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/__snapshots__/vector_style_symbol_editor.test.js.snap
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/__snapshots__/vector_style_symbol_editor.test.js.snap
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/__snapshots__/vector_style_symbol_editor.test.js.snap
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/_color_stops.scss b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/_color_stops.scss
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_ramp_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_ramp_select.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_ramp_select.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_ramp_select.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops_utils.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops_utils.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops_utils.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/dynamic_color_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/dynamic_color_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/static_color_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/static_color_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/static_color_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/static_color_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/vector_style_color_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/vector_style_color_editor.js
similarity index 92%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/vector_style_color_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/vector_style_color_editor.js
index c8950ffe71a1e..a39db57dc4883 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/vector_style_color_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/vector_style_color_editor.js
@@ -6,7 +6,7 @@
import React from 'react';
-import { StaticDynamicStyleRow } from '../../static_dynamic_style_row';
+import { StaticDynamicStyleRow } from '../../../components/static_dynamic_style_row';
import { DynamicColorSelection } from './dynamic_color_selection';
import { StaticColorSelection } from './static_color_selection';
import { getVectorStyleLabel } from '../get_vector_style_label';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/field_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_select.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/field_select.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_select.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/get_vector_style_label.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/get_vector_style_label.js
similarity index 94%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/get_vector_style_label.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/get_vector_style_label.js
index a39fabf20bae4..b6cc215ec6ded 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/get_vector_style_label.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/get_vector_style_label.js
@@ -6,7 +6,7 @@
import { i18n } from '@kbn/i18n';
-import { vectorStyles } from '../../vector_style_defaults';
+import { vectorStyles } from '../vector_style_defaults';
export function getVectorStyleLabel(styleName) {
switch (styleName) {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/__snapshots__/vector_icon.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/__snapshots__/vector_icon.test.js.snap
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/__snapshots__/vector_icon.test.js.snap
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/__snapshots__/vector_icon.test.js.snap
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/circle_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/circle_icon.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/circle_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/circle_icon.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/line_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/line_icon.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/line_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/line_icon.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/polygon_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/polygon_icon.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/polygon_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/polygon_icon.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/style_property_legend_row.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/style_property_legend_row.js
similarity index 95%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/style_property_legend_row.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/style_property_legend_row.js
index 2f8a603c290ab..4d091389a360e 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/style_property_legend_row.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/style_property_legend_row.js
@@ -9,12 +9,12 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { styleOptionShapes, rangeShape } from '../style_option_shapes';
-import { VectorStyle } from '../../../vector_style';
-import { ColorGradient } from '../../color_gradient';
+import { VectorStyle } from '../../vector_style';
+import { ColorGradient } from '../../../components/color_gradient';
import { CircleIcon } from './circle_icon';
import { getVectorStyleLabel } from '../get_vector_style_label';
import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
-import { StyleLegendRow } from '../../style_legend_row';
+import { StyleLegendRow } from '../../../components/style_legend_row';
function getLineWidthIcons() {
const defaultStyle = {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/symbol_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/symbol_icon.js
similarity index 96%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/symbol_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/symbol_icon.js
index a2f8d44604a0a..d241226e577a8 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/symbol_icon.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/symbol_icon.js
@@ -7,7 +7,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import { getMakiSymbolSvg, styleSvg, buildSrcUrl } from '../../../symbol_utils';
+import { getMakiSymbolSvg, styleSvg, buildSrcUrl } from '../../symbol_utils';
export class SymbolIcon extends Component {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/vector_icon.js
similarity index 98%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/vector_icon.js
index 0f9e76c3e74d9..5b86b88572552 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/vector_icon.js
@@ -12,7 +12,7 @@ import { CircleIcon } from './circle_icon';
import { LineIcon } from './line_icon';
import { PolygonIcon } from './polygon_icon';
import { SymbolIcon } from './symbol_icon';
-import { VectorStyle } from '../../../vector_style';
+import { VectorStyle } from '../../vector_style';
import { getColorRampCenterColor } from '../../../color_utils';
export class VectorIcon extends Component {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/vector_icon.test.js
similarity index 98%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/vector_icon.test.js
index 221b6268c55df..1a16035fe6d33 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/vector_icon.test.js
@@ -8,7 +8,7 @@ import React from 'react';
import { shallow } from 'enzyme';
import { VectorIcon } from './vector_icon';
-import { VectorStyle } from '../../../vector_style';
+import { VectorStyle } from '../../vector_style';
let isPointsOnly = false;
let isLinesOnly = false;
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_style_legend.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/vector_style_legend.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_style_legend.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/legend/vector_style_legend.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/dynamic_orientation_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/dynamic_orientation_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/orientation_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/orientation_editor.js
similarity index 92%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/orientation_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/orientation_editor.js
index bfe712d13d3af..65efddae90933 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/orientation_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/orientation_editor.js
@@ -6,7 +6,7 @@
import React from 'react';
-import { StaticDynamicStyleRow } from '../../static_dynamic_style_row';
+import { StaticDynamicStyleRow } from '../../../components/static_dynamic_style_row';
import { DynamicOrientationSelection } from './dynamic_orientation_selection';
import { StaticOrientationSelection } from './static_orientation_selection';
import { i18n } from '@kbn/i18n';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/static_orientation_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/static_orientation_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/static_orientation_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/static_orientation_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/dynamic_size_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/dynamic_size_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/dynamic_size_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/dynamic_size_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/size_range_selector.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/size_range_selector.js
similarity index 93%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/size_range_selector.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/size_range_selector.js
index 31b9b4f5ad649..4279fbbe0fbb3 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/size_range_selector.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/size_range_selector.js
@@ -7,7 +7,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ValidatedDualRange } from 'ui/validated_range';
-import { DEFAULT_MIN_SIZE, DEFAULT_MAX_SIZE } from '../../../vector_style_defaults';
+import { DEFAULT_MIN_SIZE, DEFAULT_MAX_SIZE } from '../../vector_style_defaults';
import { i18n } from '@kbn/i18n';
export function SizeRangeSelector({ minSize, maxSize, onChange, ...rest }) {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/static_size_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/static_size_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/static_size_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/static_size_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/vector_style_size_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/vector_style_size_editor.js
similarity index 92%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/vector_style_size_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/vector_style_size_editor.js
index a03835f7a9501..ffaaace680a43 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/vector_style_size_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/vector_style_size_editor.js
@@ -6,7 +6,7 @@
import React from 'react';
-import { StaticDynamicStyleRow } from '../../static_dynamic_style_row';
+import { StaticDynamicStyleRow } from '../../../components/static_dynamic_style_row';
import { DynamicSizeSelection } from './dynamic_size_selection';
import { StaticSizeSelection } from './static_size_selection';
import { getVectorStyleLabel } from '../get_vector_style_label';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/style_option_shapes.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/style_option_shapes.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/style_option_shapes.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/style_option_shapes.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js
similarity index 98%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js
index 83d4ff7c11d66..f624f4e661a14 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js
@@ -16,12 +16,12 @@ import {
getDefaultDynamicProperties,
getDefaultStaticProperties,
vectorStyles,
-} from '../../vector_style_defaults';
+} from '../vector_style_defaults';
import { DEFAULT_FILL_COLORS, DEFAULT_LINE_COLORS } from '../../color_utils';
import { VECTOR_SHAPE_TYPES } from '../../../sources/vector_feature_types';
-import { SYMBOLIZE_AS_ICON } from '../../vector_constants';
+import { SYMBOLIZE_AS_ICON } from '../vector_constants';
import { i18n } from '@kbn/i18n';
-import { SYMBOL_OPTIONS } from '../../symbol_utils';
+import { SYMBOL_OPTIONS } from '../symbol_utils';
import { EuiSpacer, EuiButtonGroup } from '@elastic/eui';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_symbol_editor.js
similarity index 97%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_symbol_editor.js
index 268b1f39255b9..29be736b432f9 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_symbol_editor.js
@@ -16,7 +16,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from '../../vector_constants';
+import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from '../vector_constants';
import { SymbolIcon } from './legend/symbol_icon';
const SYMBOLIZE_AS_OPTIONS = [
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_symbol_editor.test.js
similarity index 93%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_symbol_editor.test.js
index 4a2c227d84535..44b864dea2e99 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_symbol_editor.test.js
@@ -7,7 +7,7 @@
import React from 'react';
import { shallow } from 'enzyme';
-import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from '../../vector_constants';
+import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from '../vector_constants';
import { VectorStyleSymbolEditor } from './vector_style_symbol_editor';
const symbolOptions = [
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js
new file mode 100644
index 0000000000000..5c2122dfc4566
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js
@@ -0,0 +1,105 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+import { DynamicStyleProperty } from './dynamic_style_property';
+import _ from 'lodash';
+import { getComputedFieldName } from '../style_util';
+import { getColorRampStops } from '../../color_utils';
+
+
+export class DynamicColorProperty extends DynamicStyleProperty {
+
+
+ syncCircleColorWithMb(mbLayerId, mbMap, alpha) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'circle-color', color);
+ mbMap.setPaintProperty(mbLayerId, 'circle-opacity', alpha);
+ }
+
+ syncIconColorWithMb(mbLayerId, mbMap) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'icon-color', color);
+ }
+
+ syncHaloBorderColorWithMb(mbLayerId, mbMap) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'icon-halo-color', color);
+ }
+
+ syncCircleStrokeWithMb(pointLayerId, mbMap, alpha) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', color);
+ mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha);
+ }
+
+ syncFillColorWithMb(mbLayerId, mbMap, alpha) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'fill-color', color);
+ mbMap.setPaintProperty(mbLayerId, 'fill-opacity', alpha);
+ }
+
+ syncLineColorWithMb(mbLayerId, mbMap, alpha) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'line-color', color);
+ mbMap.setPaintProperty(mbLayerId, 'line-opacity', alpha);
+ }
+
+ _getMbColor() {
+ const isDynamicConfigComplete = _.has(this._options, 'field.name') && _.has(this._options, 'color');
+ if (!isDynamicConfigComplete) {
+ return null;
+ }
+
+ if (this._options.useCustomColorRamp && (!this._options.customColorRamp || !this._options.customColorRamp.length)) {
+ return null;
+ }
+
+ return this._getMBDataDrivenColor({
+ targetName: getComputedFieldName(this._styleName, this._options.field.name),
+ colorStops: this._getMBColorStops(),
+ isSteps: this._options.useCustomColorRamp,
+ });
+ }
+
+ _getMBDataDrivenColor({ targetName, colorStops, isSteps }) {
+ if (isSteps) {
+ const firstStopValue = colorStops[0];
+ const lessThenFirstStopValue = firstStopValue - 1;
+ return [
+ 'step',
+ ['coalesce', ['feature-state', targetName], lessThenFirstStopValue],
+ 'rgba(0,0,0,0)', // MB will assign the base value to any features that is below the first stop value
+ ...colorStops
+ ];
+ }
+
+ return [
+ 'interpolate',
+ ['linear'],
+ ['coalesce', ['feature-state', targetName], -1],
+ -1, 'rgba(0,0,0,0)',
+ ...colorStops
+ ];
+ }
+
+
+ _getMBColorStops() {
+
+ if (this._options.useCustomColorRamp) {
+ return this._options.customColorRamp.reduce((accumulatedStops, nextStop) => {
+ return [...accumulatedStops, nextStop.stop, nextStop.color];
+ }, []);
+ }
+
+ return getColorRampStops(this._options.color);
+ }
+
+}
+
+
+
+
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js
new file mode 100644
index 0000000000000..2881ee422048b
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+import { DynamicStyleProperty } from './dynamic_style_property';
+import { getComputedFieldName } from '../style_util';
+import { vectorStyles } from '../vector_style_defaults';
+
+
+export class DynamicOrientationProperty extends DynamicStyleProperty {
+
+ syncIconRotationWithMb(symbolLayerId, mbMap) {
+ if (this._options.field && this._options.field.name) {
+ const targetName = getComputedFieldName(vectorStyles.ICON_ORIENTATION, this._options.field.name);
+ // Using property state instead of feature-state because layout properties do not support feature-state
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', ['coalesce', ['get', targetName], 0]);
+ } else {
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', 0);
+ }
+ }
+
+}
+
+
+
+
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js
new file mode 100644
index 0000000000000..2758a440f57c5
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js
@@ -0,0 +1,84 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+import { DynamicStyleProperty } from './dynamic_style_property';
+import { getComputedFieldName } from '../style_util';
+import { HALF_LARGE_MAKI_ICON_SIZE, LARGE_MAKI_ICON_SIZE, SMALL_MAKI_ICON_SIZE } from '../symbol_utils';
+import { vectorStyles } from '../vector_style_defaults';
+import _ from 'lodash';
+
+export class DynamicSizeProperty extends DynamicStyleProperty {
+
+ syncHaloWidthWithMb(mbLayerId, mbMap) {
+ const haloWidth = this._getMbSize();
+ mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', haloWidth);
+ }
+
+
+ syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId) {
+ if (this._isSizeDynamicConfigComplete(this._options)) {
+ const iconPixels = this._options.maxSize >= HALF_LARGE_MAKI_ICON_SIZE
+ ? LARGE_MAKI_ICON_SIZE
+ : SMALL_MAKI_ICON_SIZE;
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
+
+ const halfIconPixels = iconPixels / 2;
+ const targetName = getComputedFieldName(vectorStyles.ICON_SIZE, this._options.field.name);
+ // Using property state instead of feature-state because layout properties do not support feature-state
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-size', [
+ 'interpolate',
+ ['linear'],
+ ['coalesce', ['get', targetName], 0],
+ 0, this._options.minSize / halfIconPixels,
+ 1, this._options.maxSize / halfIconPixels
+ ]);
+ } else {
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-image', null);
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-size', null);
+ }
+ }
+
+ syncCircleStrokeWidthWithMb(mbLayerId, mbMap) {
+ const lineWidth = this._getMbSize();
+ mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', lineWidth);
+ }
+
+ syncCircleRadiusWithMb(mbLayerId, mbMap) {
+ const circleRadius = this._getMbSize();
+ mbMap.setPaintProperty(mbLayerId, 'circle-radius', circleRadius);
+ }
+
+ syncLineWidthWithMb(mbLayerId, mbMap) {
+ const lineWidth = this._getMbSize();
+ mbMap.setPaintProperty(mbLayerId, 'line-width', lineWidth);
+ }
+
+ _getMbSize() {
+ if (this._isSizeDynamicConfigComplete(this._options)) {
+ return this._getMbDataDrivenSize({
+ targetName: getComputedFieldName(this._styleName, this._options.field.name),
+ minSize: this._options.minSize,
+ maxSize: this._options.maxSize,
+ });
+ }
+ return null;
+ }
+
+ _getMbDataDrivenSize({ targetName, minSize, maxSize }) {
+ return [
+ 'interpolate',
+ ['linear'],
+ ['coalesce', ['feature-state', targetName], 0],
+ 0, minSize,
+ 1, maxSize
+ ];
+ }
+
+ _isSizeDynamicConfigComplete() {
+ return this._options.field && this._options.field.name && _.has(this._options, 'minSize') && _.has(this._options, 'maxSize');
+ }
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js
new file mode 100644
index 0000000000000..8200ede3e3523
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js
@@ -0,0 +1,12 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+import { AbstractStyleProperty } from './style_property';
+
+export class DynamicStyleProperty extends AbstractStyleProperty {
+ static type = 'DYNAMIC';
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js
new file mode 100644
index 0000000000000..d4c44fca1bd08
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+import { StaticStyleProperty } from './static_style_property';
+
+
+export class StaticColorProperty extends StaticStyleProperty {
+
+ syncCircleColorWithMb(mbLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(mbLayerId, 'circle-color', this._options.color);
+ mbMap.setPaintProperty(mbLayerId, 'circle-opacity', alpha);
+ }
+
+ syncFillColorWithMb(mbLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(mbLayerId, 'fill-color', this._options.color);
+ mbMap.setPaintProperty(mbLayerId, 'fill-opacity', alpha);
+ }
+
+ syncIconColorWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'icon-color', this._options.color);
+ }
+
+ syncHaloBorderColorWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'icon-halo-color', this._options.color);
+ }
+
+ syncLineColorWithMb(mbLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(mbLayerId, 'line-color', this._options.color);
+ mbMap.setPaintProperty(mbLayerId, 'line-opacity', alpha);
+ }
+
+ syncCircleStrokeWithMb(pointLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', this._options.color);
+ mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha);
+ }
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_orientation_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_orientation_property.js
new file mode 100644
index 0000000000000..48a7bbd3f79df
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_orientation_property.js
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+import { StaticStyleProperty } from './static_style_property';
+
+
+export class StaticOrientationProperty extends StaticStyleProperty {
+
+ constructor(options, styleName) {
+ if (typeof options.orientation !== 'number') {
+ super({ orientation: 0 }, styleName);
+ } else {
+ super(options, styleName);
+ }
+ }
+
+ syncIconRotationWithMb(symbolLayerId, mbMap) {
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', this._options.orientation);
+ }
+
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js
new file mode 100644
index 0000000000000..37162d8cb0a3c
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+import { StaticStyleProperty } from './static_style_property';
+import { HALF_LARGE_MAKI_ICON_SIZE, LARGE_MAKI_ICON_SIZE, SMALL_MAKI_ICON_SIZE } from '../symbol_utils';
+
+
+export class StaticSizeProperty extends StaticStyleProperty {
+
+ constructor(options, styleName) {
+ if (typeof options.size !== 'number') {
+ super({ size: 1 }, styleName);
+ } else {
+ super(options, styleName);
+ }
+ }
+
+ syncHaloWidthWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', this._options.size);
+ }
+
+ syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId) {
+ const iconPixels = this._size >= HALF_LARGE_MAKI_ICON_SIZE ? LARGE_MAKI_ICON_SIZE : SMALL_MAKI_ICON_SIZE;
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
+ const halfIconPixels = iconPixels / 2;
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-size', this._options.size / halfIconPixels);
+ }
+
+ syncCircleStrokeWidthWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', this._options.size);
+ }
+
+ syncCircleRadiusWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'circle-radius', this._options.size);
+ }
+
+ syncLineWidthWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'line-width', this._options.size);
+ }
+
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_style_property.js
new file mode 100644
index 0000000000000..448efc06899e5
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_style_property.js
@@ -0,0 +1,13 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+import { AbstractStyleProperty } from './style_property';
+
+export class StaticStyleProperty extends AbstractStyleProperty {
+ static type = 'STATIC';
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/util/injected_data.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js
similarity index 56%
rename from x-pack/legacy/plugins/maps/public/layers/util/injected_data.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js
index 8c18819e9f8b5..7e9e27f83722d 100644
--- a/x-pack/legacy/plugins/maps/public/layers/util/injected_data.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js
@@ -3,19 +3,11 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-export class InjectedData {
- constructor(data) {
- this._descriptor = { data };
- }
-
- getData() {
- return this._descriptor.data;
- }
+export class AbstractStyleProperty {
- hasData() {
- return !!this._descriptor.data;
+ constructor(options, styleName) {
+ this._options = options;
+ this._styleName = styleName;
}
-
}
-
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/style_util.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/style_util.js
new file mode 100644
index 0000000000000..69caaca080138
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/style_util.js
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+export function getComputedFieldName(styleName, fieldName) {
+ return `${getComputedFieldNamePrefix(fieldName)}__${styleName}`;
+}
+
+export function getComputedFieldNamePrefix(fieldName) {
+ return `__kbn__dynamic__${fieldName}`;
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js
similarity index 97%
rename from x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js
index 22e1a6aea6a72..967d0e0bbd096 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js
@@ -6,7 +6,7 @@
import maki from '@elastic/maki';
import xml2js from 'xml2js';
-import { parseXmlString } from '../../../common/parse_xml_string';
+import { parseXmlString } from '../../../../common/parse_xml_string';
export const LARGE_MAKI_ICON_SIZE = 15;
const LARGE_MAKI_ICON_SIZE_AS_STRING = LARGE_MAKI_ICON_SIZE.toString();
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.test.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.test.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector_constants.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_constants.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/vector_constants.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_constants.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js
similarity index 58%
rename from x-pack/legacy/plugins/maps/public/layers/styles/vector_style.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js
index f26f4df0b1753..70ebba7e8d177 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js
@@ -7,34 +7,36 @@
import _ from 'lodash';
import React from 'react';
import { i18n } from '@kbn/i18n';
-import { getColorRampStops } from './color_utils';
-import { VectorStyleEditor } from './components/vector/vector_style_editor';
+import { VectorStyleEditor } from './components/vector_style_editor';
import { getDefaultProperties, vectorStyles } from './vector_style_defaults';
-import { AbstractStyle } from './abstract_style';
-import { SOURCE_DATA_ID_ORIGIN, GEO_JSON_TYPE } from '../../../common/constants';
-import { VectorIcon } from './components/vector/legend/vector_icon';
-import { VectorStyleLegend } from './components/vector/legend/vector_style_legend';
-import { VECTOR_SHAPE_TYPES } from '../sources/vector_feature_types';
+import { AbstractStyle } from '../abstract_style';
+import { SOURCE_DATA_ID_ORIGIN, GEO_JSON_TYPE } from '../../../../common/constants';
+import { VectorIcon } from './components/legend/vector_icon';
+import { VectorStyleLegend } from './components/legend/vector_style_legend';
+import { VECTOR_SHAPE_TYPES } from '../../sources/vector_feature_types';
import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from './vector_constants';
-import {
- getMakiSymbolAnchor,
- LARGE_MAKI_ICON_SIZE,
- SMALL_MAKI_ICON_SIZE,
- HALF_LARGE_MAKI_ICON_SIZE
-} from './symbol_utils';
+import { getMakiSymbolAnchor } from './symbol_utils';
+import { getComputedFieldName, getComputedFieldNamePrefix } from './style_util';
+import { StaticStyleProperty } from './properties/static_style_property';
+import { DynamicStyleProperty } from './properties/dynamic_style_property';
+import { DynamicSizeProperty } from './properties/dynamic_size_property';
+import { StaticSizeProperty } from './properties/static_size_property';
+import { StaticColorProperty } from './properties/static_color_property';
+import { DynamicColorProperty } from './properties/dynamic_color_property';
+import { StaticOrientationProperty } from './properties/static_orientation_property';
+import { DynamicOrientationProperty } from './properties/dynamic_orientation_property';
+
+const POINTS = [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT];
+const LINES = [GEO_JSON_TYPE.LINE_STRING, GEO_JSON_TYPE.MULTI_LINE_STRING];
+const POLYGONS = [GEO_JSON_TYPE.POLYGON, GEO_JSON_TYPE.MULTI_POLYGON];
export class VectorStyle extends AbstractStyle {
static type = 'VECTOR';
- static STYLE_TYPE = { 'DYNAMIC': 'DYNAMIC', 'STATIC': 'STATIC' };
+ static STYLE_TYPE = { 'DYNAMIC': DynamicStyleProperty.type, 'STATIC': StaticStyleProperty.type };
- static getComputedFieldName(styleName, fieldName) {
- return `${VectorStyle.getComputedFieldNamePrefix(fieldName)}__${styleName}`;
- }
-
- static getComputedFieldNamePrefix(fieldName) {
- return `__kbn__dynamic__${fieldName}`;
- }
+ static getComputedFieldName = getComputedFieldName;
+ static getComputedFieldNamePrefix = getComputedFieldNamePrefix;
constructor(descriptor = {}, source) {
super();
@@ -43,6 +45,13 @@ export class VectorStyle extends AbstractStyle {
...descriptor,
...VectorStyle.createDescriptor(descriptor.properties),
};
+
+ this._lineColorStyleProperty = this._makeColorProperty(this._descriptor.properties[vectorStyles.LINE_COLOR], vectorStyles.LINE_COLOR);
+ this._fillColorStyleProperty = this._makeColorProperty(this._descriptor.properties[vectorStyles.FILL_COLOR], vectorStyles.FILL_COLOR);
+ this._lineWidthStyleProperty = this._makeSizeProperty(this._descriptor.properties[vectorStyles.LINE_WIDTH], vectorStyles.LINE_WIDTH);
+ this._iconSizeStyleProperty = this._makeSizeProperty(this._descriptor.properties[vectorStyles.ICON_SIZE], vectorStyles.ICON_SIZE);
+ // eslint-disable-next-line max-len
+ this._iconOrientationProperty = this._makeOrientationProperty(this._descriptor.properties[vectorStyles.ICON_ORIENTATION], vectorStyles.ICON_ORIENTATION);
}
static createDescriptor(properties = {}) {
@@ -168,13 +177,13 @@ export class VectorStyle extends AbstractStyle {
let hasPolygons = false;
for (let i = 0; i < features.length; i++) {
const feature = features[i];
- if (!hasPoints && [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT].includes(feature.geometry.type)) {
+ if (!hasPoints && POINTS.includes(feature.geometry.type)) {
hasPoints = true;
}
- if (!hasLines && [GEO_JSON_TYPE.LINE_STRING, GEO_JSON_TYPE.MULTI_LINE_STRING].includes(feature.geometry.type)) {
+ if (!hasLines && LINES.includes(feature.geometry.type)) {
hasLines = true;
}
- if (!hasPolygons && [GEO_JSON_TYPE.POLYGON, GEO_JSON_TYPE.MULTI_POLYGON].includes(feature.geometry.type)) {
+ if (!hasPolygons && POLYGONS.includes(feature.geometry.type)) {
hasPolygons = true;
}
@@ -430,210 +439,72 @@ export class VectorStyle extends AbstractStyle {
return hasGeoJsonProperties;
}
- _getMBDataDrivenColor({ targetName, colorStops, isSteps }) {
- if (isSteps) {
- const firstStopValue = colorStops[0];
- const lessThenFirstStopValue = firstStopValue - 1;
- return [
- 'step',
- ['coalesce', ['feature-state', targetName], lessThenFirstStopValue],
- 'rgba(0,0,0,0)', // MB will assign the base value to any features that is below the first stop value
- ...colorStops
- ];
- }
-
- return [
- 'interpolate',
- ['linear'],
- ['coalesce', ['feature-state', targetName], -1],
- -1, 'rgba(0,0,0,0)',
- ...colorStops
- ];
- }
-
- _getMbDataDrivenSize({ targetName, minSize, maxSize }) {
- return [
- 'interpolate',
- ['linear'],
- ['coalesce', ['feature-state', targetName], 0],
- 0, minSize,
- 1, maxSize
- ];
+ arePointsSymbolizedAsCircles() {
+ return this._descriptor.properties.symbol.options.symbolizeAs === SYMBOLIZE_AS_CIRCLE;
}
- _getMBColor(styleName, styleDescriptor) {
- const isStatic = styleDescriptor.type === VectorStyle.STYLE_TYPE.STATIC;
- if (isStatic) {
- return _.get(styleDescriptor, 'options.color', null);
- }
-
- const isDynamicConfigComplete = _.has(styleDescriptor, 'options.field.name')
- && _.has(styleDescriptor, 'options.color');
- if (!isDynamicConfigComplete) {
- return null;
- }
-
- if (styleDescriptor.options.useCustomColorRamp &&
- (!styleDescriptor.options.customColorRamp ||
- !styleDescriptor.options.customColorRamp.length)) {
- return null;
- }
-
- return this._getMBDataDrivenColor({
- targetName: VectorStyle.getComputedFieldName(styleName, styleDescriptor.options.field.name),
- colorStops: this._getMBColorStops(styleDescriptor),
- isSteps: styleDescriptor.options.useCustomColorRamp,
- });
+ setMBPaintProperties({ alpha, mbMap, fillLayerId, lineLayerId }) {
+ this._fillColorStyleProperty.syncFillColorWithMb(fillLayerId, mbMap, alpha);
+ this._lineColorStyleProperty.syncLineColorWithMb(lineLayerId, mbMap, alpha);
+ this._lineWidthStyleProperty.syncLineWidthWithMb(lineLayerId, mbMap);
}
- _getMBColorStops(styleDescriptor) {
- if (styleDescriptor.options.useCustomColorRamp) {
- return styleDescriptor.options.customColorRamp.reduce((accumulatedStops, nextStop) => {
- return [...accumulatedStops, nextStop.stop, nextStop.color];
- }, []);
- }
-
- return getColorRampStops(styleDescriptor.options.color);
+ setMBPaintPropertiesForPoints({ alpha, mbMap, pointLayerId }) {
+ this._fillColorStyleProperty.syncCircleColorWithMb(pointLayerId, mbMap, alpha);
+ this._lineColorStyleProperty.syncCircleStrokeWithMb(pointLayerId, mbMap, alpha);
+ this._lineWidthStyleProperty.syncCircleStrokeWidthWithMb(pointLayerId, mbMap);
+ this._iconSizeStyleProperty.syncCircleRadiusWithMb(pointLayerId, mbMap);
}
- _isSizeDynamicConfigComplete(styleDescriptor) {
- return _.has(styleDescriptor, 'options.field.name')
- && _.has(styleDescriptor, 'options.minSize')
- && _.has(styleDescriptor, 'options.maxSize');
- }
+ setMBSymbolPropertiesForPoints({ mbMap, symbolLayerId, alpha }) {
- _getMbSize(styleName, styleDescriptor) {
- if (styleDescriptor.type === VectorStyle.STYLE_TYPE.STATIC) {
- return styleDescriptor.options.size;
- }
+ const symbolId = this._descriptor.properties.symbol.options.symbolId;
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-ignore-placement', true);
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-anchor', getMakiSymbolAnchor(symbolId));
+ mbMap.setPaintProperty(symbolLayerId, 'icon-opacity', alpha);
- if (this._isSizeDynamicConfigComplete(styleDescriptor)) {
- return this._getMbDataDrivenSize({
- targetName: VectorStyle.getComputedFieldName(styleName, styleDescriptor.options.field.name),
- minSize: styleDescriptor.options.minSize,
- maxSize: styleDescriptor.options.maxSize,
- });
- }
+ // icon-color is only supported on SDF icons.
+ this._fillColorStyleProperty.syncIconColorWithMb(symbolLayerId, mbMap);
+ this._lineColorStyleProperty.syncHaloBorderColorWithMb(symbolLayerId, mbMap);
+ this._lineWidthStyleProperty.syncHaloWidthWithMb(symbolLayerId, mbMap);
+ this._iconSizeStyleProperty.syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId);
+ this._iconOrientationProperty.syncIconRotationWithMb(symbolLayerId, mbMap);
- return null;
}
- setMBPaintProperties({ alpha, mbMap, fillLayerId, lineLayerId }) {
- if (this._descriptor.properties.fillColor) {
- const color = this._getMBColor(vectorStyles.FILL_COLOR, this._descriptor.properties.fillColor);
- mbMap.setPaintProperty(fillLayerId, 'fill-color', color);
- mbMap.setPaintProperty(fillLayerId, 'fill-opacity', alpha);
- } else {
- mbMap.setPaintProperty(fillLayerId, 'fill-color', null);
- mbMap.setPaintProperty(fillLayerId, 'fill-opacity', 0);
- }
-
- if (this._descriptor.properties.lineColor) {
- const color = this._getMBColor(vectorStyles.LINE_COLOR, this._descriptor.properties.lineColor);
- mbMap.setPaintProperty(lineLayerId, 'line-color', color);
- mbMap.setPaintProperty(lineLayerId, 'line-opacity', alpha);
-
- } else {
- mbMap.setPaintProperty(lineLayerId, 'line-color', null);
- mbMap.setPaintProperty(lineLayerId, 'line-opacity', 0);
- }
-
- if (this._descriptor.properties.lineWidth) {
- const lineWidth = this._getMbSize(vectorStyles.LINE_WIDTH, this._descriptor.properties.lineWidth);
- mbMap.setPaintProperty(lineLayerId, 'line-width', lineWidth);
+ _makeSizeProperty(descriptor, styleName) {
+ if (!descriptor || !descriptor.options) {
+ return new StaticSizeProperty({ size: 0 }, styleName);
+ } else if (descriptor.type === StaticStyleProperty.type) {
+ return new StaticSizeProperty(descriptor.options, styleName);
+ } else if (descriptor.type === DynamicStyleProperty.type) {
+ return new DynamicSizeProperty(descriptor.options, styleName);
} else {
- mbMap.setPaintProperty(lineLayerId, 'line-width', 0);
+ throw new Error(`${descriptor} not implemented`);
}
}
- setMBPaintPropertiesForPoints({ alpha, mbMap, pointLayerId }) {
- if (this._descriptor.properties.fillColor) {
- const color = this._getMBColor(vectorStyles.FILL_COLOR, this._descriptor.properties.fillColor);
- mbMap.setPaintProperty(pointLayerId, 'circle-color', color);
- mbMap.setPaintProperty(pointLayerId, 'circle-opacity', alpha);
- } else {
- mbMap.setPaintProperty(pointLayerId, 'circle-color', null);
- mbMap.setPaintProperty(pointLayerId, 'circle-opacity', 0);
- }
- if (this._descriptor.properties.lineColor) {
- const color = this._getMBColor(vectorStyles.LINE_COLOR, this._descriptor.properties.lineColor);
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', color);
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha);
-
- } else {
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', null);
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', 0);
- }
- if (this._descriptor.properties.lineWidth) {
- const lineWidth = this._getMbSize(vectorStyles.LINE_WIDTH, this._descriptor.properties.lineWidth);
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-width', lineWidth);
- } else {
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-width', 0);
- }
- if (this._descriptor.properties.iconSize) {
- const iconSize = this._getMbSize(vectorStyles.ICON_SIZE, this._descriptor.properties.iconSize);
- mbMap.setPaintProperty(pointLayerId, 'circle-radius', iconSize);
+ _makeColorProperty(descriptor, styleName) {
+ if (!descriptor || !descriptor.options) {
+ return new StaticColorProperty({ color: null }, styleName);
+ } else if (descriptor.type === StaticStyleProperty.type) {
+ return new StaticColorProperty(descriptor.options, styleName);
+ } else if (descriptor.type === DynamicStyleProperty.type) {
+ return new DynamicColorProperty(descriptor.options, styleName);
} else {
- mbMap.setPaintProperty(pointLayerId, 'circle-radius', 0);
+ throw new Error(`${descriptor} not implemented`);
}
}
- async setMBSymbolPropertiesForPoints({ mbMap, symbolLayerId, alpha }) {
- mbMap.setLayoutProperty(symbolLayerId, 'icon-ignore-placement', true);
-
- const symbolId = this._descriptor.properties.symbol.options.symbolId;
- mbMap.setLayoutProperty(symbolLayerId, 'icon-anchor', getMakiSymbolAnchor(symbolId));
- const color = this._getMBColor(vectorStyles.FILL_COLOR, this._descriptor.properties.fillColor);
- const haloColor = this._getMBColor(vectorStyles.LINE_COLOR, this._descriptor.properties.lineColor);
- const haloWidth = this._getMbSize(vectorStyles.LINE_WIDTH, this._descriptor.properties.lineWidth);
- // icon-color is only supported on SDF icons.
- mbMap.setPaintProperty(symbolLayerId, 'icon-color', color);
- mbMap.setPaintProperty(symbolLayerId, 'icon-halo-color', haloColor);
- mbMap.setPaintProperty(symbolLayerId, 'icon-halo-width', haloWidth);
- mbMap.setPaintProperty(symbolLayerId, 'icon-opacity', alpha);
-
- // circle sizing is by radius
- // to make icons be similiar in size to circles then have to deal with icon in half width measurements
- const iconSize = this._descriptor.properties.iconSize;
- if (iconSize.type === VectorStyle.STYLE_TYPE.STATIC) {
- const iconPixels = iconSize.options.size >= HALF_LARGE_MAKI_ICON_SIZE
- ? LARGE_MAKI_ICON_SIZE
- : SMALL_MAKI_ICON_SIZE;
- mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
-
- const halfIconPixels = iconPixels / 2;
- mbMap.setLayoutProperty(symbolLayerId, 'icon-size', iconSize.options.size / halfIconPixels);
- } else if (this._isSizeDynamicConfigComplete(iconSize)) {
- const iconPixels = iconSize.options.maxSize >= HALF_LARGE_MAKI_ICON_SIZE
- ? LARGE_MAKI_ICON_SIZE
- : SMALL_MAKI_ICON_SIZE;
- mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
-
- const halfIconPixels = iconPixels / 2;
- const targetName = VectorStyle.getComputedFieldName(vectorStyles.ICON_SIZE, iconSize.options.field.name);
- // Using property state instead of feature-state because layout properties do not support feature-state
- mbMap.setLayoutProperty(symbolLayerId, 'icon-size', [
- 'interpolate',
- ['linear'],
- ['coalesce', ['get', targetName], 0],
- 0, iconSize.options.minSize / halfIconPixels,
- 1, iconSize.options.maxSize / halfIconPixels
- ]);
- }
-
- const iconOrientation = this._descriptor.properties.iconOrientation;
- if (iconOrientation.type === VectorStyle.STYLE_TYPE.STATIC) {
- mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', iconOrientation.options.orientation);
- } else if (_.has(iconOrientation, 'options.field.name')) {
- const targetName = VectorStyle.getComputedFieldName(vectorStyles.ICON_ORIENTATION, iconOrientation.options.field.name);
- // Using property state instead of feature-state because layout properties do not support feature-state
- mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', [
- 'coalesce', ['get', targetName], 0
- ]);
+ _makeOrientationProperty(descriptor, styleName) {
+ if (!descriptor || !descriptor.options) {
+ return new StaticOrientationProperty({ orientation: 0 }, styleName);
+ } else if (descriptor.type === StaticStyleProperty.type) {
+ return new StaticOrientationProperty(descriptor.options, styleName);
+ } else if (descriptor.type === DynamicStyleProperty.type) {
+ return new DynamicOrientationProperty(descriptor.options, styleName);
+ } else {
+ throw new Error(`${descriptor} not implemented`);
}
}
-
- arePointsSymbolizedAsCircles() {
- return this._descriptor.properties.symbol.options.symbolizeAs === SYMBOLIZE_AS_CIRCLE;
- }
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js
similarity index 98%
rename from x-pack/legacy/plugins/maps/public/layers/styles/vector_style.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js
index 7c993564018aa..c0d76fadc01a5 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js
@@ -5,8 +5,8 @@
*/
import { VectorStyle } from './vector_style';
-import { DataRequest } from '../util/data_request';
-import { VECTOR_SHAPE_TYPES } from '../sources/vector_feature_types';
+import { DataRequest } from '../../util/data_request';
+import { VECTOR_SHAPE_TYPES } from '../../sources/vector_feature_types';
describe('getDescriptorWithMissingStylePropsRemoved', () => {
const fieldName = 'doIStillExist';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style_defaults.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js
similarity index 99%
rename from x-pack/legacy/plugins/maps/public/layers/styles/vector_style_defaults.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js
index dfd0c1ca1b86b..ea4228430d13d 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style_defaults.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js
@@ -10,7 +10,7 @@ import {
COLOR_GRADIENTS,
DEFAULT_FILL_COLORS,
DEFAULT_LINE_COLORS
-} from './color_utils';
+} from '../color_utils';
const DEFAULT_ICON = 'airfield';
diff --git a/x-pack/legacy/plugins/maps/public/layers/tooltips/es_tooltip_property.js b/x-pack/legacy/plugins/maps/public/layers/tooltips/es_tooltip_property.js
index dae56d5526b0a..446978a151d64 100644
--- a/x-pack/legacy/plugins/maps/public/layers/tooltips/es_tooltip_property.js
+++ b/x-pack/legacy/plugins/maps/public/layers/tooltips/es_tooltip_property.js
@@ -4,10 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { buildPhraseFilter } from '@kbn/es-query';
import { TooltipProperty } from './tooltip_property';
import _ from 'lodash';
-
+import { esFilters } from '../../../../../../../src/plugins/data/public';
export class ESTooltipProperty extends TooltipProperty {
constructor(propertyKey, propertyName, rawValue, indexPattern) {
@@ -36,7 +35,7 @@ export class ESTooltipProperty extends TooltipProperty {
async getESFilters() {
return [
- buildPhraseFilter(
+ esFilters.buildPhraseFilter(
this._indexPattern.fields.getByName(this._propertyName),
this._rawValue,
this._indexPattern)
diff --git a/x-pack/legacy/plugins/maps/public/layers/util/is_refresh_only_query.js b/x-pack/legacy/plugins/maps/public/layers/util/is_refresh_only_query.js
index a8c6341863517..bf6f2bcf6f08b 100644
--- a/x-pack/legacy/plugins/maps/public/layers/util/is_refresh_only_query.js
+++ b/x-pack/legacy/plugins/maps/public/layers/util/is_refresh_only_query.js
@@ -7,6 +7,9 @@
// Refresh only query is query where timestamps are different but query is the same.
// Triggered by clicking "Refresh" button in QueryBar
export function isRefreshOnlyQuery(prevQuery, newQuery) {
+ if (!prevQuery || !newQuery) {
+ return false;
+ }
return prevQuery.queryLastTriggeredAt !== newQuery.queryLastTriggeredAt
&& prevQuery.language === newQuery.language
&& prevQuery.query === newQuery.query;
diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
index 81f4f3b388d56..b2f45cb6206c6 100644
--- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
+++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
@@ -7,7 +7,7 @@
import turf from 'turf';
import React from 'react';
import { AbstractLayer } from './layer';
-import { VectorStyle } from './styles/vector_style';
+import { VectorStyle } from './styles/vector/vector_style';
import { InnerJoin } from './joins/inner_join';
import {
GEO_JSON_TYPE,
@@ -132,18 +132,6 @@ export class VectorLayer extends AbstractLayer {
return true;
}
- getInjectedData() {
- const featureCollection = super.getInjectedData();
- if (!featureCollection) {
- return null;
- }
- // Set default visible property on data
- featureCollection.features.forEach(
- feature => _.set(feature, `properties.${FEATURE_VISIBLE_PROPERTY_NAME}`, true)
- );
- return featureCollection;
- }
-
getCustomIconAndTooltipContent() {
const featureCollection = this._getSourceFeatureCollection();
@@ -510,16 +498,7 @@ export class VectorLayer extends AbstractLayer {
startLoading, stopLoading, onLoadError, registerCancelCallback, dataFilters
}) {
- if (this._source.isInjectedData()) {
- const featureCollection = this.getInjectedData();
- return {
- refreshed: false,
- featureCollection
- };
- }
-
const requestToken = Symbol(`layer-source-refresh:${ this.getId()} - source`);
-
const searchFilters = this._getSearchFilters(dataFilters);
const canSkip = await this._canSkipSourceUpdate(this._source, SOURCE_DATA_ID_ORIGIN, searchFilters);
if (canSkip) {
@@ -594,12 +573,8 @@ export class VectorLayer extends AbstractLayer {
}
_getSourceFeatureCollection() {
- if (this._source.isInjectedData()) {
- return this.getInjectedData();
- } else {
- const sourceDataRequest = this.getSourceDataRequest();
- return sourceDataRequest ? sourceDataRequest.getData() : null;
- }
+ const sourceDataRequest = this.getSourceDataRequest();
+ return sourceDataRequest ? sourceDataRequest.getData() : null;
}
_syncFeatureCollectionWithMb(mbMap) {
diff --git a/x-pack/legacy/plugins/maps/public/reducers/non_serializable_instances.js b/x-pack/legacy/plugins/maps/public/reducers/non_serializable_instances.js
index 5fb09b8c87006..a76330f4d1764 100644
--- a/x-pack/legacy/plugins/maps/public/reducers/non_serializable_instances.js
+++ b/x-pack/legacy/plugins/maps/public/reducers/non_serializable_instances.js
@@ -10,6 +10,7 @@ import { MapAdapter } from '../inspector/adapters/map_adapter';
const REGISTER_CANCEL_CALLBACK = 'REGISTER_CANCEL_CALLBACK';
const UNREGISTER_CANCEL_CALLBACK = 'UNREGISTER_CANCEL_CALLBACK';
+const SET_EVENT_HANDLERS = 'SET_EVENT_HANDLERS';
function createInspectorAdapters() {
const inspectorAdapters = {
@@ -27,6 +28,7 @@ export function nonSerializableInstances(state, action = {}) {
return {
inspectorAdapters: createInspectorAdapters(),
cancelRequestCallbacks: new Map(), // key is request token, value is cancel callback
+ eventHandlers: {},
};
}
@@ -41,6 +43,12 @@ export function nonSerializableInstances(state, action = {}) {
return {
...state,
};
+ case SET_EVENT_HANDLERS: {
+ return {
+ ...state,
+ eventHandlers: action.eventHandlers
+ };
+ }
default:
return state;
@@ -57,6 +65,10 @@ export const getCancelRequestCallbacks = ({ nonSerializableInstances }) => {
return nonSerializableInstances.cancelRequestCallbacks;
};
+export const getEventHandlers = ({ nonSerializableInstances }) => {
+ return nonSerializableInstances.eventHandlers;
+};
+
// Actions
export const registerCancelCallback = (requestToken, callback) => {
return {
@@ -86,3 +98,10 @@ export const cancelRequest = (requestToken) => {
}
};
};
+
+export const setEventHandlers = (eventHandlers = {}) => {
+ return {
+ type: SET_EVENT_HANDLERS,
+ eventHandlers,
+ };
+};
diff --git a/x-pack/legacy/plugins/maps/public/register_vis_type_alias.js b/x-pack/legacy/plugins/maps/public/register_vis_type_alias.js
index 001bc5ca64fbd..009cff317fcaf 100644
--- a/x-pack/legacy/plugins/maps/public/register_vis_type_alias.js
+++ b/x-pack/legacy/plugins/maps/public/register_vis_type_alias.js
@@ -4,21 +4,35 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import chrome from 'ui/chrome';
import { setup as visualizationsSetup } from '../../../../../src/legacy/core_plugins/visualizations/public/np_ready/public/legacy';
import { i18n } from '@kbn/i18n';
import { APP_ID, APP_ICON, MAP_BASE_URL } from '../common/constants';
+const showMapVisualizationTypes = chrome.getInjected('showMapVisualizationTypes', false);
+
+const description = i18n.translate('xpack.maps.visTypeAlias.description', {
+ defaultMessage: 'Create and style maps with multiple layers and indices.',
+});
+
+const legacyMapVisualizationWarning = i18n.translate('xpack.maps.visTypeAlias.legacyMapVizWarning', {
+ defaultMessage: `Use the Maps app instead of Coordinate Map and Region Map.
+The Maps app offers more functionality and is easier to use.`,
+});
+
visualizationsSetup.types.registerAlias({
aliasUrl: MAP_BASE_URL,
name: APP_ID,
title: i18n.translate('xpack.maps.visTypeAlias.title', {
defaultMessage: 'Maps',
}),
- description: i18n.translate('xpack.maps.visTypeAlias.description', {
- defaultMessage: `Create and style maps with multiple layers and indices.
-Use the Maps app instead of Coordinate Map and Region Map.
-The Maps app offers more functionality and is easier to use.`,
- }),
+ description: showMapVisualizationTypes
+ ? `${description} ${legacyMapVisualizationWarning}`
+ : description,
icon: APP_ICON,
stage: 'production',
});
+
+if (!showMapVisualizationTypes) {
+ visualizationsSetup.types.hideTypes(['region_map', 'tile_map']);
+}
diff --git a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
index efcac8a9175ca..4f561c9391d4d 100644
--- a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
+++ b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
@@ -11,8 +11,8 @@ import { VectorTileLayer } from '../layers/vector_tile_layer';
import { VectorLayer } from '../layers/vector_layer';
import { HeatmapLayer } from '../layers/heatmap_layer';
import { ALL_SOURCES } from '../layers/sources/all_sources';
-import { VectorStyle } from '../layers/styles/vector_style';
-import { HeatmapStyle } from '../layers/styles/heatmap_style';
+import { VectorStyle } from '../layers/styles/vector/vector_style';
+import { HeatmapStyle } from '../layers/styles/heatmap/heatmap_style';
import { timefilter } from 'ui/timefilter';
import { getInspectorAdapters } from '../reducers/non_serializable_instances';
import { copyPersistentState, TRACKED_LAYER_DESCRIPTOR } from '../reducers/util';
diff --git a/x-pack/legacy/plugins/ml/common/types/modules.ts b/x-pack/legacy/plugins/ml/common/types/modules.ts
index 18879304d7c7f..9eb77d2140323 100644
--- a/x-pack/legacy/plugins/ml/common/types/modules.ts
+++ b/x-pack/legacy/plugins/ml/common/types/modules.ts
@@ -80,3 +80,5 @@ export interface DataRecognizerConfigResponse {
dashboard: KibanaObjectResponse;
};
}
+
+export type JobOverride = Partial;
diff --git a/x-pack/legacy/plugins/ml/public/components/anomalies_table/severity_cell/severity_cell.tsx b/x-pack/legacy/plugins/ml/public/components/anomalies_table/severity_cell/severity_cell.tsx
index c2d60f94e144d..e74d1a73b3332 100644
--- a/x-pack/legacy/plugins/ml/public/components/anomalies_table/severity_cell/severity_cell.tsx
+++ b/x-pack/legacy/plugins/ml/public/components/anomalies_table/severity_cell/severity_cell.tsx
@@ -36,7 +36,7 @@ export const SeverityCell: FC = memo(({ score, multiBucketImp
+ />
{severity}
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/analytics.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/analytics.ts
index f99f9661f12ef..385d50215cd21 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/analytics.ts
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/analytics.ts
@@ -29,6 +29,15 @@ interface RegressionAnalysis {
};
}
+export const SEARCH_SIZE = 1000;
+
+export enum INDEX_STATUS {
+ UNUSED,
+ LOADING,
+ LOADED,
+ ERROR,
+}
+
export interface Eval {
meanSquaredError: number | '';
rSquared: number | '';
@@ -91,6 +100,16 @@ export const getPredictionFieldName = (analysis: AnalysisConfig) => {
return predictionFieldName;
};
+export const getPredictedFieldName = (resultsField: string, analysis: AnalysisConfig) => {
+ // default is 'ml'
+ const predictionFieldName = getPredictionFieldName(analysis);
+ const defaultPredictionField = `${getDependentVar(analysis)}_prediction`;
+ const predictedField = `${resultsField}.${
+ predictionFieldName ? predictionFieldName : defaultPredictionField
+ }`;
+ return predictedField;
+};
+
export const isOutlierAnalysis = (arg: any): arg is OutlierAnalysis => {
const keys = Object.keys(arg);
return keys.length === 1 && keys[0] === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION;
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/fields.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/fields.ts
index 4ae3e8513e5b4..5621d77f66469 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/fields.ts
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/fields.ts
@@ -5,6 +5,7 @@
*/
import { getNestedProperty } from '../../util/object_utils';
+import { DataFrameAnalyticsConfig, getPredictedFieldName, getDependentVar } from './analytics';
export type EsId = string;
export type EsDocSource = Record;
@@ -16,6 +17,7 @@ export interface EsDoc extends Record {
}
export const MAX_COLUMNS = 20;
+export const DEFAULT_REGRESSION_COLUMNS = 8;
const ML__ID_COPY = 'ml__id_copy';
@@ -68,6 +70,104 @@ export const sortColumns = (obj: EsDocSource, resultsField: string) => (a: strin
return a.localeCompare(b);
};
+export const sortRegressionResultsFields = (
+ a: string,
+ b: string,
+ jobConfig: DataFrameAnalyticsConfig
+) => {
+ const dependentVariable = getDependentVar(jobConfig.analysis);
+ const resultsField = jobConfig.dest.results_field;
+ const predictedField = getPredictedFieldName(resultsField, jobConfig.analysis);
+ if (a === `${resultsField}.is_training`) {
+ return -1;
+ }
+ if (b === `${resultsField}.is_training`) {
+ return 1;
+ }
+ if (a === predictedField) {
+ return -1;
+ }
+ if (b === predictedField) {
+ return 1;
+ }
+ if (a === dependentVariable) {
+ return -1;
+ }
+ if (b === dependentVariable) {
+ return 1;
+ }
+ return a.localeCompare(b);
+};
+
+// Used to sort columns:
+// Anchor on the left ml.is_training, ,
+export const sortRegressionResultsColumns = (
+ obj: EsDocSource,
+ jobConfig: DataFrameAnalyticsConfig
+) => (a: string, b: string) => {
+ const dependentVariable = getDependentVar(jobConfig.analysis);
+ const resultsField = jobConfig.dest.results_field;
+ const predictedField = getPredictedFieldName(resultsField, jobConfig.analysis);
+
+ const typeofA = typeof obj[a];
+ const typeofB = typeof obj[b];
+
+ if (a === `${resultsField}.is_training`) {
+ return -1;
+ }
+
+ if (b === `${resultsField}.is_training`) {
+ return 1;
+ }
+
+ if (a === predictedField) {
+ return -1;
+ }
+
+ if (b === predictedField) {
+ return 1;
+ }
+
+ if (a === dependentVariable) {
+ return -1;
+ }
+
+ if (b === dependentVariable) {
+ return 1;
+ }
+
+ if (typeofA !== 'string' && typeofB === 'string') {
+ return 1;
+ }
+ if (typeofA === 'string' && typeofB !== 'string') {
+ return -1;
+ }
+ if (typeofA === 'string' && typeofB === 'string') {
+ return a.localeCompare(b);
+ }
+
+ const tokensA = a.split('.');
+ const prefixA = tokensA[0];
+ const tokensB = b.split('.');
+ const prefixB = tokensB[0];
+
+ if (prefixA === resultsField && tokensA.length > 1 && prefixB !== resultsField) {
+ tokensA.shift();
+ tokensA.shift();
+ if (tokensA.join('.') === b) return 1;
+ return tokensA.join('.').localeCompare(b);
+ }
+
+ if (prefixB === resultsField && tokensB.length > 1 && prefixA !== resultsField) {
+ tokensB.shift();
+ tokensB.shift();
+ if (tokensB.join('.') === a) return -1;
+ return a.localeCompare(tokensB.join('.'));
+ }
+
+ return a.localeCompare(b);
+};
+
export function getFlattenedFields(obj: EsDocSource, resultsField: string): EsFieldName[] {
const flatDocFields: EsFieldName[] = [];
const newDocFields = Object.keys(obj);
@@ -84,6 +184,39 @@ export function getFlattenedFields(obj: EsDocSource, resultsField: string): EsFi
return flatDocFields.filter(f => f !== ML__ID_COPY);
}
+export const getDefaultRegressionFields = (
+ docs: EsDoc[],
+ jobConfig: DataFrameAnalyticsConfig
+): EsFieldName[] => {
+ const resultsField = jobConfig.dest.results_field;
+ if (docs.length === 0) {
+ return [];
+ }
+
+ const newDocFields = getFlattenedFields(docs[0]._source, resultsField);
+ return newDocFields
+ .filter(k => {
+ if (k === `${resultsField}.is_training`) {
+ return true;
+ }
+ // predicted value of dependent variable
+ if (k === getPredictedFieldName(resultsField, jobConfig.analysis)) {
+ return true;
+ }
+ // actual value of dependent variable
+ if (k === getDependentVar(jobConfig.analysis)) {
+ return true;
+ }
+ if (k.split('.')[0] === resultsField) {
+ return false;
+ }
+
+ return docs.some(row => row._source[k] !== null);
+ })
+ .sort((a, b) => sortRegressionResultsFields(a, b, jobConfig))
+ .slice(0, DEFAULT_REGRESSION_COLUMNS);
+};
+
export const getDefaultSelectableFields = (docs: EsDoc[], resultsField: string): EsFieldName[] => {
if (docs.length === 0) {
return [];
@@ -99,14 +232,7 @@ export const getDefaultSelectableFields = (docs: EsDoc[], resultsField: string):
return false;
}
- let value = false;
- docs.forEach(row => {
- const source = row._source;
- if (source[k] !== null) {
- value = true;
- }
- });
- return value;
+ return docs.some(row => row._source[k] !== null);
})
.slice(0, MAX_COLUMNS);
};
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/index.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/index.ts
index 774db35f2a52b..112f828f9897e 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/index.ts
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/common/index.ts
@@ -21,12 +21,18 @@ export {
getValuesFromResponse,
loadEvalData,
Eval,
+ getPredictedFieldName,
+ INDEX_STATUS,
+ SEARCH_SIZE,
} from './analytics';
export {
getDefaultSelectableFields,
+ getDefaultRegressionFields,
getFlattenedFields,
sortColumns,
+ sortRegressionResultsColumns,
+ sortRegressionResultsFields,
toggleSelectedField,
EsId,
EsDoc,
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx
index ce39cecb5b5e6..92f438459128e 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx
@@ -6,6 +6,7 @@
import { shallow } from 'enzyme';
import React from 'react';
+import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
jest.mock('../../../../../contexts/ui/use_ui_chrome_context');
jest.mock('ui/new_platform');
@@ -20,7 +21,9 @@ jest.mock('react', () => {
describe('Data Frame Analytics: ', () => {
test('Minimal initialization', () => {
- const wrapper = shallow( );
+ const wrapper = shallow(
+
+ );
// Without the jobConfig being loaded, the component will just return empty.
expect(wrapper.text()).toMatch('');
// TODO Once React 16.9 is available we can write tests covering asynchronous hooks.
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx
index 95ec334667547..11bb62dec1624 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx
@@ -50,10 +50,13 @@ import {
EsFieldName,
EsDoc,
MAX_COLUMNS,
+ INDEX_STATUS,
} from '../../../../common';
import { getOutlierScoreFieldName } from './common';
-import { INDEX_STATUS, useExploreData } from './use_explore_data';
+import { useExploreData } from './use_explore_data';
+import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
+import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns';
const customColorScaleFactory = (n: number) => (t: number) => {
if (t < 1 / n) {
@@ -78,7 +81,7 @@ const ExplorationTitle: React.SFC<{ jobId: string }> = ({ jobId }) => (
{i18n.translate('xpack.ml.dataframe.analytics.exploration.jobIdTitle', {
- defaultMessage: 'Job ID {jobId}',
+ defaultMessage: 'Outlier detection job ID {jobId}',
values: { jobId },
})}
@@ -87,9 +90,10 @@ const ExplorationTitle: React.SFC<{ jobId: string }> = ({ jobId }) => (
interface Props {
jobId: string;
+ jobStatus: DATA_FRAME_TASK_STATE;
}
-export const Exploration: FC = React.memo(({ jobId }) => {
+export const Exploration: FC = React.memo(({ jobId, jobStatus }) => {
const [jobConfig, setJobConfig] = useState(undefined);
const [pageIndex, setPageIndex] = useState(0);
@@ -378,7 +382,14 @@ export const Exploration: FC = React.memo(({ jobId }) => {
if (status === INDEX_STATUS.LOADED && tableItems.length === 0) {
return (
-
+
+
+
+
+
+ {getTaskStateBadge(jobStatus)}
+
+
= React.memo(({ jobId }) => {
-
+
+
+
+
+
+ {getTaskStateBadge(jobStatus)}
+
+
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts
index ee86156c50d4d..2a07bc1251a31 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts
@@ -18,19 +18,12 @@ import {
getFlattenedFields,
DataFrameAnalyticsConfig,
EsFieldName,
+ INDEX_STATUS,
+ SEARCH_SIZE,
} from '../../../../common';
import { getOutlierScoreFieldName } from './common';
-const SEARCH_SIZE = 1000;
-
-export enum INDEX_STATUS {
- UNUSED,
- LOADING,
- LOADED,
- ERROR,
-}
-
type TableItem = Record;
interface LoadExploreDataArg {
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx
index c7ea3421ac5de..20ab6678da820 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx
@@ -8,12 +8,20 @@ import React, { FC, Fragment, useEffect, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiStat, EuiTitle } from '@elastic/eui';
import { ErrorCallout } from './error_callout';
-import { getValuesFromResponse, loadEvalData, Eval } from '../../../../common';
+import {
+ getValuesFromResponse,
+ getDependentVar,
+ getPredictionFieldName,
+ loadEvalData,
+ Eval,
+ DataFrameAnalyticsConfig,
+} from '../../../../common';
+import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns';
+import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
interface Props {
- jobId: string;
- index: string;
- dependentVariable: string;
+ jobConfig: DataFrameAnalyticsConfig;
+ jobStatus: DATA_FRAME_TASK_STATE;
}
const meanSquaredErrorText = i18n.translate(
@@ -30,23 +38,28 @@ const rSquaredText = i18n.translate(
);
const defaultEval: Eval = { meanSquaredError: '', rSquared: '', error: null };
-export const EvaluatePanel: FC = ({ jobId, index, dependentVariable }) => {
+export const EvaluatePanel: FC = ({ jobConfig, jobStatus }) => {
const [trainingEval, setTrainingEval] = useState(defaultEval);
const [generalizationEval, setGeneralizationEval] = useState(defaultEval);
const [isLoadingTraining, setIsLoadingTraining] = useState(false);
const [isLoadingGeneralization, setIsLoadingGeneralization] = useState(false);
+ const index = jobConfig.dest.index;
+ const dependentVariable = getDependentVar(jobConfig.analysis);
+ const predictionFieldName = getPredictionFieldName(jobConfig.analysis);
+ // default is 'ml'
+ const resultsField = jobConfig.dest.results_field;
+
const loadData = async () => {
setIsLoadingGeneralization(true);
setIsLoadingTraining(true);
- // TODO: resultsField and predictionFieldName will need to be properly passed to this function
- // once the results view is in use.
+
const genErrorEval = await loadEvalData({
isTraining: false,
index,
dependentVariable,
- resultsField: 'ml',
- predictionFieldName: undefined,
+ resultsField,
+ predictionFieldName,
});
if (genErrorEval.success === true && genErrorEval.eval) {
@@ -65,14 +78,13 @@ export const EvaluatePanel: FC = ({ jobId, index, dependentVariable }) =>
error: genErrorEval.error,
});
}
- // TODO: resultsField and predictionFieldName will need to be properly passed to this function
- // once the results view is in use.
+
const trainingErrorEval = await loadEvalData({
isTraining: true,
index,
dependentVariable,
- resultsField: 'ml',
- predictionFieldName: undefined,
+ resultsField,
+ predictionFieldName,
});
if (trainingErrorEval.success === true && trainingErrorEval.eval) {
@@ -99,14 +111,21 @@ export const EvaluatePanel: FC = ({ jobId, index, dependentVariable }) =>
return (
-
-
- {i18n.translate('xpack.ml.dataframe.analytics.regressionExploration.jobIdTitle', {
- defaultMessage: 'Job ID {jobId}',
- values: { jobId },
- })}
-
-
+
+
+
+
+ {i18n.translate('xpack.ml.dataframe.analytics.regressionExploration.jobIdTitle', {
+ defaultMessage: 'Regression job ID {jobId}',
+ values: { jobId: jobConfig.id },
+ })}
+
+
+
+
+ {getTaskStateBadge(jobStatus)}
+
+
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx
index f6cb010c3f040..7beea07f9502d 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx
@@ -4,25 +4,107 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { FC, Fragment } from 'react';
-// import { i18n } from '@kbn/i18n';
-import { EuiSpacer } from '@elastic/eui';
-
+import React, { FC, Fragment, useState, useEffect } from 'react';
+import { EuiCallOut, EuiLoadingSpinner, EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { ml } from '../../../../../services/ml_api_service';
+import { DataFrameAnalyticsConfig } from '../../../../common';
import { EvaluatePanel } from './evaluate_panel';
-// import { ResultsTable } from './results_table';
+import { ResultsTable } from './results_table';
+import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
+
+interface GetDataFrameAnalyticsResponse {
+ count: number;
+ data_frame_analytics: DataFrameAnalyticsConfig[];
+}
+
+const LoadingPanel: FC = () => (
+
+
+
+);
+
+export const ExplorationTitle: React.SFC<{ jobId: string }> = ({ jobId }) => (
+
+
+ {i18n.translate('xpack.ml.dataframe.analytics.regressionExploration.jobIdTitle', {
+ defaultMessage: 'Regression job ID {jobId}',
+ values: { jobId },
+ })}
+
+
+);
interface Props {
jobId: string;
- destIndex: string;
- dependentVariable: string;
+ jobStatus: DATA_FRAME_TASK_STATE;
}
-export const RegressionExploration: FC = ({ jobId, destIndex, dependentVariable }) => {
+export const RegressionExploration: FC = ({ jobId, jobStatus }) => {
+ const [jobConfig, setJobConfig] = useState(undefined);
+ const [isLoadingJobConfig, setIsLoadingJobConfig] = useState(false);
+ const [jobConfigErrorMessage, setJobConfigErrorMessage] = useState(undefined);
+
+ const loadJobConfig = async () => {
+ setIsLoadingJobConfig(true);
+ try {
+ const analyticsConfigs: GetDataFrameAnalyticsResponse = await ml.dataFrameAnalytics.getDataFrameAnalytics(
+ jobId
+ );
+ if (
+ Array.isArray(analyticsConfigs.data_frame_analytics) &&
+ analyticsConfigs.data_frame_analytics.length > 0
+ ) {
+ setJobConfig(analyticsConfigs.data_frame_analytics[0]);
+ setIsLoadingJobConfig(false);
+ }
+ } catch (e) {
+ if (e.message !== undefined) {
+ setJobConfigErrorMessage(e.message);
+ } else {
+ setJobConfigErrorMessage(JSON.stringify(e));
+ }
+ setIsLoadingJobConfig(false);
+ }
+ };
+
+ useEffect(() => {
+ loadJobConfig();
+ }, []);
+
+ if (jobConfigErrorMessage !== undefined) {
+ return (
+
+
+
+
+ {jobConfigErrorMessage}
+
+
+ );
+ }
+
return (
-
+ {isLoadingJobConfig === true && jobConfig === undefined && }
+ {isLoadingJobConfig === false && jobConfig !== undefined && (
+
+ )}
- {/* */}
+ {isLoadingJobConfig === true && jobConfig === undefined && }
+ {isLoadingJobConfig === false && jobConfig !== undefined && (
+
+ )}
);
};
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx
new file mode 100644
index 0000000000000..5ba3b8ed45939
--- /dev/null
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx
@@ -0,0 +1,467 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { Fragment, FC, useEffect, useState } from 'react';
+import moment from 'moment-timezone';
+
+import { i18n } from '@kbn/i18n';
+import {
+ EuiBadge,
+ EuiButtonIcon,
+ EuiCallOut,
+ EuiCheckbox,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiFormRow,
+ EuiPanel,
+ EuiPopover,
+ EuiPopoverTitle,
+ EuiProgress,
+ EuiSpacer,
+ EuiText,
+ EuiToolTip,
+ Query,
+} from '@elastic/eui';
+
+import { Query as QueryType } from '../../../analytics_management/components/analytics_list/common';
+
+import {
+ ColumnType,
+ MlInMemoryTableBasic,
+ OnTableChangeArg,
+ SortingPropType,
+ SORT_DIRECTION,
+} from '../../../../../components/ml_in_memory_table';
+
+import { formatHumanReadableDateTimeSeconds } from '../../../../../util/date_utils';
+import { SavedSearchQuery } from '../../../../../contexts/kibana';
+
+import {
+ sortRegressionResultsColumns,
+ sortRegressionResultsFields,
+ toggleSelectedField,
+ DataFrameAnalyticsConfig,
+ EsFieldName,
+ EsDoc,
+ MAX_COLUMNS,
+ getPredictedFieldName,
+ INDEX_STATUS,
+ SEARCH_SIZE,
+} from '../../../../common';
+import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns';
+import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
+
+import { useExploreData, defaultSearchQuery } from './use_explore_data';
+import { ExplorationTitle } from './regression_exploration';
+
+const PAGE_SIZE_OPTIONS = [5, 10, 25, 50];
+
+interface Props {
+ jobConfig: DataFrameAnalyticsConfig;
+ jobStatus: DATA_FRAME_TASK_STATE;
+}
+
+export const ResultsTable: FC = React.memo(({ jobConfig, jobStatus }) => {
+ const [pageIndex, setPageIndex] = useState(0);
+ const [pageSize, setPageSize] = useState(25);
+ const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]);
+ const [isColumnsPopoverVisible, setColumnsPopoverVisible] = useState(false);
+ const [searchQuery, setSearchQuery] = useState(defaultSearchQuery);
+ const [searchError, setSearchError] = useState(undefined);
+ const [searchString, setSearchString] = useState(undefined);
+
+ function toggleColumnsPopover() {
+ setColumnsPopoverVisible(!isColumnsPopoverVisible);
+ }
+
+ function closeColumnsPopover() {
+ setColumnsPopoverVisible(false);
+ }
+
+ function toggleColumn(column: EsFieldName) {
+ if (tableItems.length > 0 && jobConfig !== undefined) {
+ // spread to a new array otherwise the component wouldn't re-render
+ setSelectedFields([...toggleSelectedField(selectedFields, column)]);
+ }
+ }
+
+ const {
+ errorMessage,
+ loadExploreData,
+ sortField,
+ sortDirection,
+ status,
+ tableItems,
+ } = useExploreData(jobConfig, selectedFields, setSelectedFields);
+
+ let docFields: EsFieldName[] = [];
+ let docFieldsCount = 0;
+ if (tableItems.length > 0) {
+ docFields = Object.keys(tableItems[0]);
+ docFields.sort((a, b) => sortRegressionResultsFields(a, b, jobConfig));
+ docFieldsCount = docFields.length;
+ }
+
+ const columns: ColumnType[] = [];
+
+ if (jobConfig !== undefined && selectedFields.length > 0 && tableItems.length > 0) {
+ columns.push(
+ ...selectedFields.sort(sortRegressionResultsColumns(tableItems[0], jobConfig)).map(k => {
+ const column: ColumnType = {
+ field: k,
+ name: k,
+ sortable: true,
+ truncateText: true,
+ };
+
+ const render = (d: any, fullItem: EsDoc) => {
+ if (Array.isArray(d) && d.every(item => typeof item === 'string')) {
+ // If the cells data is an array of strings, return as a comma separated list.
+ // The list will get limited to 5 items with `…` at the end if there's more in the original array.
+ return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`;
+ } else if (Array.isArray(d)) {
+ // If the cells data is an array of e.g. objects, display a 'array' badge with a
+ // tooltip that explains that this type of field is not supported in this table.
+ return (
+
+
+ {i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.indexArrayBadgeContent',
+ {
+ defaultMessage: 'array',
+ }
+ )}
+
+
+ );
+ } else if (typeof d === 'object' && d !== null) {
+ // If the cells data is an object, display a 'object' badge with a
+ // tooltip that explains that this type of field is not supported in this table.
+ return (
+
+
+ {i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.indexObjectBadgeContent',
+ {
+ defaultMessage: 'object',
+ }
+ )}
+
+
+ );
+ }
+
+ return d;
+ };
+
+ let columnType;
+
+ if (tableItems.length > 0) {
+ columnType = typeof tableItems[0][k];
+ }
+
+ if (typeof columnType !== 'undefined') {
+ switch (columnType) {
+ case 'boolean':
+ column.dataType = 'boolean';
+ break;
+ case 'Date':
+ column.align = 'right';
+ column.render = (d: any) =>
+ formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000);
+ break;
+ case 'number':
+ column.dataType = 'number';
+ column.render = render;
+ break;
+ default:
+ column.render = render;
+ break;
+ }
+ } else {
+ column.render = render;
+ }
+
+ return column;
+ })
+ );
+ }
+
+ useEffect(() => {
+ if (jobConfig !== undefined) {
+ const predictedFieldName = getPredictedFieldName(
+ jobConfig.dest.results_field,
+ jobConfig.analysis
+ );
+ const predictedFieldSelected = selectedFields.includes(predictedFieldName);
+
+ const field = predictedFieldSelected ? predictedFieldName : selectedFields[0];
+ const direction = predictedFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
+ loadExploreData({ field, direction, searchQuery });
+ }
+ }, [JSON.stringify(searchQuery)]);
+
+ useEffect(() => {
+ // by default set the sorting to descending on the prediction field (`_prediction`).
+ // if that's not available sort ascending on the first column.
+ // also check if the current sorting field is still available.
+ if (jobConfig !== undefined && columns.length > 0 && !selectedFields.includes(sortField)) {
+ const predictedFieldName = getPredictedFieldName(
+ jobConfig.dest.results_field,
+ jobConfig.analysis
+ );
+ const predictedFieldSelected = selectedFields.includes(predictedFieldName);
+
+ const field = predictedFieldSelected ? predictedFieldName : selectedFields[0];
+ const direction = predictedFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
+ loadExploreData({ field, direction, searchQuery });
+ }
+ }, [jobConfig, columns.length, sortField, sortDirection, tableItems.length]);
+
+ let sorting: SortingPropType = false;
+ let onTableChange;
+
+ if (columns.length > 0 && sortField !== '' && sortField !== undefined) {
+ sorting = {
+ sort: {
+ field: sortField,
+ direction: sortDirection,
+ },
+ };
+
+ onTableChange = ({
+ page = { index: 0, size: 10 },
+ sort = { field: sortField, direction: sortDirection },
+ }: OnTableChangeArg) => {
+ const { index, size } = page;
+ setPageIndex(index);
+ setPageSize(size);
+
+ if (sort.field !== sortField || sort.direction !== sortDirection) {
+ loadExploreData({ ...sort, searchQuery });
+ }
+ };
+ }
+
+ const pagination = {
+ initialPageIndex: pageIndex,
+ initialPageSize: pageSize,
+ totalItemCount: tableItems.length,
+ pageSizeOptions: PAGE_SIZE_OPTIONS,
+ hidePerPageOptions: false,
+ };
+
+ const onQueryChange = ({ query, error }: { query: QueryType; error: any }) => {
+ if (error) {
+ setSearchError(error.message);
+ } else {
+ try {
+ const esQueryDsl = Query.toESQuery(query);
+ setSearchQuery(esQueryDsl);
+ setSearchString(query.text);
+ setSearchError(undefined);
+ } catch (e) {
+ setSearchError(e.toString());
+ }
+ }
+ };
+
+ const search = {
+ onChange: onQueryChange,
+ defaultQuery: searchString,
+ box: {
+ incremental: false,
+ placeholder: i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.searchBoxPlaceholder',
+ {
+ defaultMessage: 'E.g. avg>0.5',
+ }
+ ),
+ },
+ filters: [
+ {
+ type: 'field_value_toggle_group',
+ field: `${jobConfig.dest.results_field}.is_training`,
+ items: [
+ {
+ value: false,
+ name: i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.isTestingLabel',
+ {
+ defaultMessage: 'Testing',
+ }
+ ),
+ },
+ {
+ value: true,
+ name: i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.isTrainingLabel',
+ {
+ defaultMessage: 'Training',
+ }
+ ),
+ },
+ ],
+ },
+ ],
+ };
+
+ if (jobConfig === undefined) {
+ return null;
+ }
+
+ if (status === INDEX_STATUS.ERROR) {
+ return (
+
+
+
+
+
+
+ {getTaskStateBadge(jobStatus)}
+
+
+
+ {errorMessage}
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ {getTaskStateBadge(jobStatus)}
+
+
+
+
+
+
+ {docFieldsCount > MAX_COLUMNS && (
+
+ {i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.fieldSelection',
+ {
+ defaultMessage:
+ '{selectedFieldsLength, number} of {docFieldsCount, number} {docFieldsCount, plural, one {field} other {fields}} selected',
+ values: { selectedFieldsLength: selectedFields.length, docFieldsCount },
+ }
+ )}
+
+ )}
+
+
+
+
+ }
+ isOpen={isColumnsPopoverVisible}
+ closePopover={closeColumnsPopover}
+ ownFocus
+ >
+
+ {i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.selectFieldsPopoverTitle',
+ {
+ defaultMessage: 'Select fields',
+ }
+ )}
+
+
+ {docFields.map(d => (
+ toggleColumn(d)}
+ disabled={selectedFields.includes(d) && selectedFields.length === 1}
+ />
+ ))}
+
+
+
+
+
+
+
+ {status === INDEX_STATUS.LOADING && }
+ {status !== INDEX_STATUS.LOADING && (
+
+ )}
+ {(columns.length > 0 || searchQuery !== defaultSearchQuery) && (
+
+
+
+
+
+
+
+ )}
+
+ );
+});
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts
new file mode 100644
index 0000000000000..3e7266eb89474
--- /dev/null
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts
@@ -0,0 +1,163 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useEffect, useState } from 'react';
+
+import { SearchResponse } from 'elasticsearch';
+
+import { SortDirection, SORT_DIRECTION } from '../../../../../components/ml_in_memory_table';
+
+import { ml } from '../../../../../services/ml_api_service';
+import { getNestedProperty } from '../../../../../util/object_utils';
+import { SavedSearchQuery } from '../../../../../contexts/kibana';
+
+import {
+ getDefaultRegressionFields,
+ getFlattenedFields,
+ DataFrameAnalyticsConfig,
+ EsFieldName,
+ getPredictedFieldName,
+ INDEX_STATUS,
+ SEARCH_SIZE,
+} from '../../../../common';
+
+export const defaultSearchQuery = {
+ match_all: {},
+};
+
+type TableItem = Record;
+
+interface LoadExploreDataArg {
+ field: string;
+ direction: SortDirection;
+ searchQuery: SavedSearchQuery;
+}
+export interface UseExploreDataReturnType {
+ errorMessage: string;
+ loadExploreData: (arg: LoadExploreDataArg) => void;
+ sortField: EsFieldName;
+ sortDirection: SortDirection;
+ status: INDEX_STATUS;
+ tableItems: TableItem[];
+}
+
+interface SearchQuery {
+ query: SavedSearchQuery;
+ sort?: any;
+}
+
+export const useExploreData = (
+ jobConfig: DataFrameAnalyticsConfig | undefined,
+ selectedFields: EsFieldName[],
+ setSelectedFields: React.Dispatch>
+): UseExploreDataReturnType => {
+ const [errorMessage, setErrorMessage] = useState('');
+ const [status, setStatus] = useState(INDEX_STATUS.UNUSED);
+ const [tableItems, setTableItems] = useState([]);
+ const [sortField, setSortField] = useState('');
+ const [sortDirection, setSortDirection] = useState(SORT_DIRECTION.ASC);
+
+ const loadExploreData = async ({ field, direction, searchQuery }: LoadExploreDataArg) => {
+ if (jobConfig !== undefined) {
+ setErrorMessage('');
+ setStatus(INDEX_STATUS.LOADING);
+
+ try {
+ const resultsField = jobConfig.dest.results_field;
+ const body: SearchQuery = {
+ query: searchQuery,
+ };
+
+ if (field !== undefined) {
+ body.sort = [
+ {
+ [field]: {
+ order: direction,
+ },
+ },
+ ];
+ }
+
+ const resp: SearchResponse = await ml.esSearch({
+ index: jobConfig.dest.index,
+ size: SEARCH_SIZE,
+ body,
+ });
+
+ setSortField(field);
+ setSortDirection(direction);
+
+ const docs = resp.hits.hits;
+
+ if (docs.length === 0) {
+ setTableItems([]);
+ setStatus(INDEX_STATUS.LOADED);
+ return;
+ }
+
+ if (selectedFields.length === 0) {
+ const newSelectedFields = getDefaultRegressionFields(docs, jobConfig);
+ setSelectedFields(newSelectedFields);
+ }
+
+ // Create a version of the doc's source with flattened field names.
+ // This avoids confusion later on if a field name has dots in its name
+ // or is a nested fields when displaying it via EuiInMemoryTable.
+ const flattenedFields = getFlattenedFields(docs[0]._source, resultsField);
+ const transformedTableItems = docs.map(doc => {
+ const item: TableItem = {};
+ flattenedFields.forEach(ff => {
+ item[ff] = getNestedProperty(doc._source, ff);
+ if (item[ff] === undefined) {
+ // If the attribute is undefined, it means it was not a nested property
+ // but had dots in its actual name. This selects the property by its
+ // full name and assigns it to `item[ff]`.
+ item[ff] = doc._source[`"${ff}"`];
+ }
+ if (item[ff] === undefined) {
+ const parts = ff.split('.');
+ if (parts[0] === resultsField && parts.length >= 2) {
+ parts.shift();
+ if (doc._source[resultsField] !== undefined) {
+ item[ff] = doc._source[resultsField][parts.join('.')];
+ }
+ }
+ }
+ });
+ return item;
+ });
+
+ setTableItems(transformedTableItems);
+ setStatus(INDEX_STATUS.LOADED);
+ } catch (e) {
+ if (e.message !== undefined) {
+ setErrorMessage(e.message);
+ } else {
+ setErrorMessage(JSON.stringify(e));
+ }
+ setTableItems([]);
+ setStatus(INDEX_STATUS.ERROR);
+ }
+ }
+ };
+
+ useEffect(() => {
+ if (jobConfig !== undefined) {
+ loadExploreData({
+ field: getPredictedFieldName(jobConfig.dest.results_field, jobConfig.analysis),
+ direction: SORT_DIRECTION.DESC,
+ searchQuery: defaultSearchQuery,
+ });
+ }
+ }, [jobConfig && jobConfig.id]);
+
+ return { errorMessage, loadExploreData, sortField, sortDirection, status, tableItems };
+};
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/directive.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/directive.tsx
index ca448aaa7b938..4a28e0b0b881e 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/directive.tsx
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/directive.tsx
@@ -53,8 +53,7 @@ module.directive('mlDataFrameAnalyticsExploration', ($injector: InjectorService)
,
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/page.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/page.tsx
index 0bbc313704174..b3d13db0a3550 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/page.tsx
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_exploration/page.tsx
@@ -26,13 +26,13 @@ import { Exploration } from './components/exploration';
import { RegressionExploration } from './components/regression_exploration';
import { ANALYSIS_CONFIG_TYPE } from '../../common/analytics';
+import { DATA_FRAME_TASK_STATE } from '../analytics_management/components/analytics_list/common';
export const Page: FC<{
jobId: string;
- analysisType: string;
- destIndex: string;
- depVar: string;
-}> = ({ jobId, analysisType, destIndex, depVar }) => (
+ analysisType: ANALYSIS_CONFIG_TYPE;
+ jobStatus: DATA_FRAME_TASK_STATE;
+}> = ({ jobId, analysisType, jobStatus }) => (
@@ -66,9 +66,11 @@ export const Page: FC<{
- {analysisType === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION && }
+ {analysisType === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION && (
+
+ )}
{analysisType === ANALYSIS_CONFIG_TYPE.REGRESSION && (
-
+
)}
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx
index 7ad86c5d380ca..5e5283f9e6c49 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx
@@ -13,7 +13,7 @@ import {
createPermissionFailureMessage,
} from '../../../../../privilege/check_privilege';
-import { isOutlierAnalysis, getAnalysisType, getDependentVar } from '../../../../common/analytics';
+import { getAnalysisType } from '../../../../common/analytics';
import { getResultsUrl, isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } from './common';
import { stopAnalytics } from '../../services/analytics_service';
@@ -25,14 +25,11 @@ export const AnalyticsViewAction = {
isPrimary: true,
render: (item: DataFrameAnalyticsListRow) => {
const analysisType = getAnalysisType(item.config.analysis);
- const destIndex = item.config.dest.index;
- const dependentVariable = getDependentVar(item.config.analysis);
+ const jobStatus = item.stats.state;
- const url = getResultsUrl(item.id, analysisType, destIndex, dependentVariable);
- // Disable 'View' link for regression until results view is complete
+ const url = getResultsUrl(item.id, analysisType, jobStatus);
return (
(window.location.href = url)}
size="xs"
color="text"
diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/common.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/common.ts
index 99d1889b265ed..098c239e4f6ba 100644
--- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/common.ts
+++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/common.ts
@@ -5,7 +5,6 @@
*/
import { DataFrameAnalyticsId, DataFrameAnalyticsConfig } from '../../../../common';
-import { ANALYSIS_CONFIG_TYPE } from '../../../../common/analytics';
export enum DATA_FRAME_TASK_STATE {
ANALYZING = 'analyzing',
@@ -118,17 +117,6 @@ export function isCompletedAnalyticsJob(stats: DataFrameAnalyticsStats) {
return stats.state === DATA_FRAME_TASK_STATE.STOPPED && progress === 100;
}
-export function getResultsUrl(
- jobId: string,
- analysisType: string,
- destIndex: string = '',
- dependentVariable: string = ''
-) {
- const destIndexParam = `,destIndex:${destIndex}`;
- const depVarParam = `,depVar:${dependentVariable}`;
- const isRegression = analysisType === ANALYSIS_CONFIG_TYPE.REGRESSION;
-
- return `ml#/data_frame_analytics/exploration?_g=(ml:(jobId:${jobId},analysisType:${analysisType}${
- isRegression && destIndex !== '' ? destIndexParam : ''
- }${isRegression && dependentVariable !== '' ? depVarParam : ''}))`;
+export function getResultsUrl(jobId: string, analysisType: string, status: DATA_FRAME_TASK_STATE) {
+ return `ml#/data_frame_analytics/exploration?_g=(ml:(jobId:${jobId},analysisType:${analysisType},jobStatus:${status}))`;
}
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/file_based/components/about_panel/welcome_content.js b/x-pack/legacy/plugins/ml/public/datavisualizer/file_based/components/about_panel/welcome_content.js
index 28c616d3e74a6..5e9cd19ab388a 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/file_based/components/about_panel/welcome_content.js
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/file_based/components/about_panel/welcome_content.js
@@ -133,7 +133,7 @@ export function WelcomeContent() {
values={{
githubLink: (
GitHub
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/actions_panel/actions_panel.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/actions_panel/actions_panel.tsx
index c8295a1e3d8db..fca2508cb5d14 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/actions_panel/actions_panel.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/actions_panel/actions_panel.tsx
@@ -64,7 +64,7 @@ export const ActionsPanel: FC = ({ indexPattern }) => {
-
+
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/boolean_content.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/boolean_content.tsx
index ea5b1e81b8bf5..d1edf8950d812 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/boolean_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/boolean_content.tsx
@@ -28,9 +28,6 @@ function getPercentLabel(valueCount: number, totalCount: number): string {
export const BooleanContent: FC = ({ config }) => {
const { stats } = config;
- if (stats === undefined) {
- return null;
- }
const { count, sampleCount, trueCount, falseCount } = stats;
const docsPercent = roundToDecimalPlace((count / sampleCount) * 100);
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/date_content.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/date_content.tsx
index 24dbb4167c77a..7e20df0444841 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/date_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/date_content.tsx
@@ -19,9 +19,6 @@ const TIME_FORMAT = 'MMM D YYYY, HH:mm:ss.SSS';
export const DateContent: FC = ({ config }) => {
const { stats } = config;
- if (stats === undefined) {
- return null;
- }
const { count, sampleCount, earliest, latest } = stats;
const docsPercent = roundToDecimalPlace((count / sampleCount) * 100);
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/document_count_content.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/document_count_content.tsx
index a50f49df2fcd6..e9297796c97c1 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/document_count_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/document_count_content.tsx
@@ -17,9 +17,6 @@ const CHART_HEIGHT = 350;
export const DocumentCountContent: FC = ({ config }) => {
const { stats } = config;
- if (stats === undefined) {
- return null;
- }
const { documentCounts, timeRangeEarliest, timeRangeLatest } = stats;
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/geo_point_content.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/geo_point_content.tsx
index faf39d2e42373..df8c0a2f09ebb 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/geo_point_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/geo_point_content.tsx
@@ -36,9 +36,6 @@ export const GeoPointContent: FC = ({ config }) => {
// }
const { stats } = config;
- if (stats === undefined) {
- return null;
- }
const { count, sampleCount, cardinality, examples } = stats;
const docsPercent = roundToDecimalPlace((count / sampleCount) * 100);
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/ip_content.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/ip_content.tsx
index eeffd1e87153c..e27808ceb9a27 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/ip_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/ip_content.tsx
@@ -18,9 +18,6 @@ import { TopValues } from '../top_values';
export const IpContent: FC = ({ config }) => {
const { stats, fieldFormat } = config;
- if (stats === undefined) {
- return null;
- }
const { count, sampleCount, cardinality } = stats;
const docsPercent = roundToDecimalPlace((count / sampleCount) * 100);
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/keyword_content.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/keyword_content.tsx
index 92b3848a92511..2fde41cf5d018 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/keyword_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/keyword_content.tsx
@@ -18,9 +18,6 @@ import { TopValues } from '../top_values';
export const KeywordContent: FC = ({ config }) => {
const { stats, fieldFormat } = config;
- if (stats === undefined) {
- return null;
- }
const { count, sampleCount, cardinality } = stats;
const docsPercent = roundToDecimalPlace((count / sampleCount) * 100);
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/number_content.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/number_content.tsx
index b756818c775a4..8fdf826de25f4 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/number_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/number_content.tsx
@@ -34,9 +34,6 @@ const DEFAULT_TOP_VALUES_THRESHOLD = 100;
export const NumberContent: FC = ({ config }) => {
const { stats, fieldFormat } = config;
- if (stats === undefined) {
- return null;
- }
useEffect(() => {
const chartData = buildChartDataFromStats(stats, METRIC_DISTRIBUTION_CHART_WIDTH);
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/other_content.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/other_content.tsx
index b2728168425e8..92f389ff88a73 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/other_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/other_content.tsx
@@ -16,9 +16,6 @@ import { ExamplesList } from '../examples_list';
export const OtherContent: FC = ({ config }) => {
const { stats, type, aggregatable } = config;
- if (stats === undefined) {
- return null;
- }
const { count, sampleCount, cardinality, examples } = stats;
const docsPercent = roundToDecimalPlace((count / sampleCount) * 100);
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/text_content.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/text_content.tsx
index 81fff60960a8d..e0e3ea3ff4888 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/text_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/content_types/text_content.tsx
@@ -15,9 +15,6 @@ import { ExamplesList } from '../examples_list';
export const TextContent: FC = ({ config }) => {
const { stats } = config;
- if (stats === undefined) {
- return null;
- }
const { examples } = stats;
const numExamples = examples.length;
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/field_data_card.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/field_data_card.tsx
index a3641a143faa0..d162d166e8f6b 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/field_data_card.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/field_data_card/field_data_card.tsx
@@ -30,7 +30,11 @@ export interface FieldDataCardProps {
}
export const FieldDataCard: FC = ({ config }) => {
- const { fieldName, loading, type, existsInDocs } = config;
+ const { fieldName, loading, type, existsInDocs, stats } = config;
+
+ if (stats === undefined) {
+ return null;
+ }
function getCardContent() {
if (existsInDocs === false) {
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/data_loader/data_loader.ts b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/data_loader/data_loader.ts
index 464be8a9157ae..f0bb998a27614 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/data_loader/data_loader.ts
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/data_loader/data_loader.ts
@@ -4,8 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-// @ts-ignore
-import { decorateQuery, luceneStringToDsl } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import { toastNotifications } from 'ui/notify';
diff --git a/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js b/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js
index 133adea7cff6e..0c356959cd2af 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js
+++ b/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js
@@ -136,6 +136,7 @@ export class StartDatafeedModal extends Component {
onClose={this.closeModal}
style={{ width: '850px' }}
maxWidth={false}
+ data-test-subj="mlStartDatafeedModal"
>
@@ -178,6 +179,7 @@ export class StartDatafeedModal extends Component {
- switchFunc(item.index)}>{item.label}
+ switchFunc(item.index)} onKeyUp={() => {}} >{item.label}
{(item.body !== undefined) &&
{item.body}
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/datafeed.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/datafeed.tsx
index 7490f05e433cf..7e895ca206849 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/datafeed.tsx
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/datafeed.tsx
@@ -37,7 +37,7 @@ export const DatafeedStep: FC
= ({ setCurrentStep, isCurrentStep }) =
{isCurrentStep && (
-
+
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/job_details_step/components/additional_section/additional_section.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/job_details_step/components/additional_section/additional_section.tsx
index 4efac7b9ebf1a..ac2d57ea7c8a9 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/job_details_step/components/additional_section/additional_section.tsx
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/job_details_step/components/additional_section/additional_section.tsx
@@ -31,7 +31,7 @@ export const AdditionalSection: FC = ({ additionalExpanded, setAdditional
-
+
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx
index b9e9df77d35e3..5f93361982ea0 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx
@@ -213,7 +213,7 @@ export const AdvancedDetectorModal: FC = ({
-
+
= ({
/>
-
+
= ({
-
+
= ({
/>
-
+
= ({
/>
-
+
= ({
/>
-
+
= ({
placeholder={descriptionPlaceholder}
value={descriptionOption}
onChange={e => setDescriptionOption(e.target.value)}
+ data-test-subj="mlAdvancedDetectorDescriptionInput"
/>
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/modal_wrapper.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/modal_wrapper.tsx
index 8b85c658fcadf..d1ee8a6be557a 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/modal_wrapper.tsx
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/modal_wrapper.tsx
@@ -28,7 +28,11 @@ interface Props {
export const ModalWrapper: FC = ({ onCreateClick, closeModal, saveEnabled, children }) => {
return (
-
+
= ({ onCreateClick, closeModal, saveEnabled
{children}
-
+
-
+
= ({ isActive, onEditJob, onDeleteJob }) =>
defaultMessage: 'Edit',
}
)}
+ data-test-subj="mlAdvancedDetectorEditButton"
/>
@@ -75,6 +77,7 @@ export const DetectorList: FC = ({ isActive, onEditJob, onDeleteJob }) =>
defaultMessage: 'Delete',
}
)}
+ data-test-subj="mlAdvancedDetectorDeleteButton"
/>
@@ -98,14 +101,16 @@ export const DetectorList: FC = ({ isActive, onEditJob, onDeleteJob }) =>
{detectors.map((d, i) => (
-
+
{d.detector_description !== undefined ? (
- {d.detector_description}
+
+ {d.detector_description}
+
) : (
- detectorToString(d)
+
)}
{isActive && (
@@ -117,7 +122,7 @@ export const DetectorList: FC = ({ isActive, onEditJob, onDeleteJob }) =>
{d.detector_description !== undefined && (
- {detectorToString(d)}
+
)}
@@ -142,6 +147,7 @@ const NoDetectorsWarning: FC<{ show: boolean }> = ({ show }) => {
defaultMessage: 'No detectors',
})}
iconType="alert"
+ data-test-subj="mlAdvancedNoDetectorsMessage"
>
= ({ validation
);
};
+
+const StringifiedDetector: FC<{ detector: Detector }> = ({ detector }) => {
+ return {detectorToString(detector)}
;
+};
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/metric_selector.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/metric_selector.tsx
index fd597875f2716..5bc38ca934165 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/metric_selector.tsx
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/metric_selector.tsx
@@ -35,7 +35,7 @@ export const MetricSelector: FC = ({
-
+
= ({ setIsValid }) => {
-
+
);
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/validation_step/validation.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/validation_step/validation.tsx
index b60e225cdff4d..a543dbaaf3c5d 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/validation_step/validation.tsx
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/validation_step/validation.tsx
@@ -78,7 +78,7 @@ export const ValidationStep: FC = ({ setCurrentStep, isCurrentStep })
/>
)}
- {isCurrentStep === false && }
+ {isCurrentStep === false && }
);
};
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/edit_job.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/edit_job.tsx
new file mode 100644
index 0000000000000..7ec8cddfe3ed5
--- /dev/null
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/edit_job.tsx
@@ -0,0 +1,136 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { FC, useEffect, useState } from 'react';
+import {
+ EuiButton,
+ EuiButtonEmpty,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiFlyout,
+ EuiFlyoutBody,
+ EuiFlyoutFooter,
+ EuiFlyoutHeader,
+ EuiForm,
+ EuiFormRow,
+ EuiSpacer,
+ EuiTitle,
+} from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { ModuleJobUI } from '../page';
+import { usePartialState } from '../../../../components/custom_hooks';
+import { composeValidators, maxLengthValidator } from '../../../../../common/util/validators';
+import { isJobIdValid } from '../../../../../common/util/job_utils';
+import { JOB_ID_MAX_LENGTH } from '../../../../../common/constants/validation';
+import { JobGroupsInput } from '../../common/components';
+import { JobOverride } from '../../../../../common/types/modules';
+
+interface EditJobProps {
+ job: ModuleJobUI;
+ jobOverride: JobOverride | undefined;
+ existingGroupIds: string[];
+ onClose: (job: JobOverride | null) => void;
+}
+
+/**
+ * Edit job flyout for overriding job configuration.
+ */
+export const EditJob: FC = ({ job, jobOverride, existingGroupIds, onClose }) => {
+ const [formState, setFormState] = usePartialState({
+ jobGroups: (jobOverride && jobOverride.groups) || job.config.groups,
+ });
+ const [validationResult, setValidationResult] = useState>({});
+
+ const groupValidator = composeValidators(
+ (value: string) => (isJobIdValid(value) ? null : { pattern: true }),
+ maxLengthValidator(JOB_ID_MAX_LENGTH)
+ );
+
+ const handleValidation = () => {
+ const jobGroupsValidationResult = formState.jobGroups
+ .map(group => groupValidator(group))
+ .filter(result => result !== null);
+
+ setValidationResult({
+ jobGroups: jobGroupsValidationResult,
+ formValid: jobGroupsValidationResult.length === 0,
+ });
+ };
+
+ useEffect(() => {
+ handleValidation();
+ }, [formState.jobGroups]);
+
+ const onSave = () => {
+ const result: JobOverride = {
+ job_id: job.id,
+ groups: formState.jobGroups,
+ };
+ onClose(result);
+ };
+
+ return (
+ onClose(null)}>
+
+
+
+
+
+
+
+
+
+
+
+ {
+ setFormState({
+ jobGroups: value,
+ });
+ }}
+ validation={{
+ valid: !validationResult.jobGroups || validationResult.jobGroups.length === 0,
+ message: (
+
+ ),
+ }}
+ />
+
+
+
+
+
+
+
+ onClose(null)} flush="left">
+
+
+
+
+ onSave()} fill disabled={!validationResult.formValid}>
+
+
+
+
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/job_item.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/job_item.tsx
new file mode 100644
index 0000000000000..ace8409734b74
--- /dev/null
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/job_item.tsx
@@ -0,0 +1,172 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { FC, memo } from 'react';
+import {
+ EuiBadge,
+ EuiButtonIcon,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiIcon,
+ EuiLoadingSpinner,
+ EuiText,
+ EuiToolTip,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { ModuleJobUI } from '../page';
+import { SETUP_RESULTS_WIDTH } from './module_jobs';
+import { tabColor } from '../../../../../common/util/group_color_utils';
+import { JobOverride } from '../../../../../common/types/modules';
+
+interface JobItemProps {
+ job: ModuleJobUI;
+ jobPrefix: string;
+ jobOverride: JobOverride | undefined;
+ isSaving: boolean;
+ onEditRequest: (job: ModuleJobUI) => void;
+}
+
+export const JobItem: FC = memo(
+ ({ job, jobOverride, isSaving, jobPrefix, onEditRequest }) => {
+ const {
+ id,
+ config: { description, groups },
+ datafeedResult,
+ setupResult,
+ } = job;
+
+ const jobGroups = (jobOverride && jobOverride.groups) || groups;
+
+ return (
+
+
+
+
+
+ {jobPrefix}
+ {id}
+
+
+
+
+ }
+ >
+ onEditRequest(job)}
+ />
+
+
+
+
+
+ {description}
+
+
+
+ {jobGroups.map(group => (
+
+ {group}
+
+ ))}
+
+
+ {setupResult && setupResult.error && (
+
+ {setupResult.error.msg}
+
+ )}
+
+ {datafeedResult && datafeedResult.error && (
+
+ {datafeedResult.error.msg}
+
+ )}
+
+
+ {isSaving && }
+ {setupResult && datafeedResult && (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+ );
+ }
+);
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/job_settings_form.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/job_settings_form.tsx
index 617f6b31e7e53..bab45a7d77a3d 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/job_settings_form.tsx
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/components/job_settings_form.tsx
@@ -27,9 +27,8 @@ import {
patternValidator,
} from '../../../../../common/util/validators';
import { JOB_ID_MAX_LENGTH } from '../../../../../common/constants/validation';
-import { isJobIdValid } from '../../../../../common/util/job_utils';
import { usePartialState } from '../../../../components/custom_hooks';
-import { JobGroupsInput, TimeRangePicker, TimeRange } from '../../common/components';
+import { TimeRange, TimeRangePicker } from '../../common/components';
export interface JobSettingsFormValues {
jobPrefix: string;
@@ -37,15 +36,12 @@ export interface JobSettingsFormValues {
useFullIndexData: boolean;
timeRange: TimeRange;
useDedicatedIndex: boolean;
- jobGroups: string[];
}
interface JobSettingsFormProps {
saveState: SAVE_STATE;
onSubmit: (values: JobSettingsFormValues) => any;
onChange: (values: JobSettingsFormValues) => any;
- jobGroups: string[];
- existingGroupIds: string[];
jobs: ModuleJobUI[];
}
@@ -53,9 +49,7 @@ export const JobSettingsForm: FC = ({
onSubmit,
onChange,
saveState,
- existingGroupIds,
jobs,
- jobGroups,
}) => {
const { from, to } = getTimeFilterRange();
const { currentIndexPattern: indexPattern } = useKibanaContext();
@@ -64,10 +58,6 @@ export const JobSettingsForm: FC = ({
patternValidator(/^([a-z0-9]+[a-z0-9\-_]*)?$/),
maxLengthValidator(JOB_ID_MAX_LENGTH - Math.max(...jobs.map(({ id }) => id.length)))
);
- const groupValidator = composeValidators(
- (value: string) => (isJobIdValid(value) ? null : { pattern: true }),
- maxLengthValidator(JOB_ID_MAX_LENGTH)
- );
const [formState, setFormState] = usePartialState({
jobPrefix: '',
@@ -78,7 +68,6 @@ export const JobSettingsForm: FC = ({
end: to,
},
useDedicatedIndex: false,
- jobGroups: [] as string[],
});
const [validationResult, setValidationResult] = useState>({});
@@ -90,29 +79,21 @@ export const JobSettingsForm: FC = ({
const handleValidation = () => {
const jobPrefixValidationResult = jobPrefixValidator(formState.jobPrefix);
- const jobGroupsValidationResult = formState.jobGroups
- .map(group => groupValidator(group))
- .filter(result => result !== null);
setValidationResult({
jobPrefix: jobPrefixValidationResult,
- jobGroups: jobGroupsValidationResult,
- formValid: !jobPrefixValidationResult && jobGroupsValidationResult.length === 0,
+ formValid: !jobPrefixValidationResult,
});
};
useEffect(() => {
handleValidation();
- }, [formState.jobPrefix, formState.jobGroups]);
+ }, [formState.jobPrefix]);
useEffect(() => {
onChange(formState);
}, [formState]);
- useEffect(() => {
- setFormState({ jobGroups });
- }, [jobGroups]);
-
return (
<>
@@ -174,24 +155,6 @@ export const JobSettingsForm: FC = ({
/>
- {
- setFormState({
- jobGroups: value,
- });
- }}
- validation={{
- valid: !validationResult.jobGroups || validationResult.jobGroups.length === 0,
- message: (
-
- ),
- }}
- />
void;
}
-const SETUP_RESULTS_WIDTH = '200px';
+export const SETUP_RESULTS_WIDTH = '200px';
-export const ModuleJobs: FC = ({ jobs, jobPrefix, saveState }) => {
+export const ModuleJobs: FC = ({
+ jobs,
+ jobPrefix,
+ jobOverrides,
+ saveState,
+ existingGroupIds,
+ onJobOverridesChange,
+}) => {
const isSaving = saveState === SAVE_STATE.SAVING;
+
+ const [jobToEdit, setJobToEdit] = useState(null);
+
+ const onFlyoutClose = (result: JobOverride | null) => {
+ setJobToEdit(null);
+
+ if (result === null) {
+ return;
+ }
+
+ onJobOverridesChange(result);
+ };
+
+ const getJobOverride = (job: ModuleJobUI): JobOverride | undefined => {
+ return jobOverrides[job.id];
+ };
+
+ const editJobFlyout =
+ jobToEdit !== null ? (
+
+ ) : null;
+
return (
<>
@@ -70,109 +107,26 @@ export const ModuleJobs: FC = ({ jobs, jobPrefix, saveState })
)}
- {jobs.map(({ id, config: { description }, setupResult, datafeedResult }, i) => (
-
-
+ {jobs.map((job, i) => (
+
+
-
- {jobPrefix}
- {id}
-
-
-
- {description}
-
-
- {setupResult && setupResult.error && (
-
- {setupResult.error.msg}
-
- )}
-
- {datafeedResult && datafeedResult.error && (
-
- {datafeedResult.error.msg}
-
- )}
-
-
- {isSaving && }
- {setupResult && datafeedResult && (
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
+ setJobToEdit(job)}
+ />
+
{i < jobs.length - 1 && }
))}
+
+ {editJobFlyout}
>
);
};
diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/page.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/page.tsx
index 2c7600dcb99b2..f9a5230ef17d9 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/page.tsx
+++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/recognize/page.tsx
@@ -21,12 +21,13 @@ import {
EuiPanel,
} from '@elastic/eui';
import { toastNotifications } from 'ui/notify';
-import { merge, flatten } from 'lodash';
+import { merge } from 'lodash';
import { ml } from '../../../services/ml_api_service';
import { useKibanaContext } from '../../../contexts/kibana';
import {
DatafeedResponse,
DataRecognizerConfigResponse,
+ JobOverride,
JobResponse,
KibanaObject,
KibanaObjectResponse,
@@ -40,6 +41,7 @@ import { ModuleJobs } from './components/module_jobs';
import { checkForSavedObjects } from './resolvers';
import { JobSettingsForm, JobSettingsFormValues } from './components/job_settings_form';
import { TimeRange } from '../common/components';
+import { JobId } from '../common/job_creator/configs';
export interface ModuleJobUI extends ModuleJob {
datafeedResult?: DatafeedResponse;
@@ -57,6 +59,8 @@ interface PageProps {
existingGroupIds: string[];
}
+export type JobOverrides = Record;
+
export enum SAVE_STATE {
NOT_SAVED,
SAVING,
@@ -69,7 +73,7 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => {
// #region State
const [jobPrefix, setJobPrefix] = useState('');
const [jobs, setJobs] = useState([]);
- const [jobGroups, setJobGroups] = useState([]);
+ const [jobOverrides, setJobOverrides] = useState({});
const [kibanaObjects, setKibanaObjects] = useState({});
const [saveState, setSaveState] = useState(SAVE_STATE.NOT_SAVED);
const [resultsUrl, setResultsUrl] = useState('');
@@ -93,6 +97,9 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => {
const displayQueryWarning = savedSearch.id !== undefined;
const tempQuery = savedSearch.id === undefined ? undefined : combinedQuery;
+ /**
+ * Loads recognizer module configuration.
+ */
const loadModule = async () => {
try {
const response: Module = await ml.getDataRecognizerModule({ moduleId });
@@ -101,9 +108,6 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => {
const kibanaObjectsResult = await checkForSavedObjects(response.kibana as KibanaObjects);
setKibanaObjects(kibanaObjectsResult);
- setJobGroups([
- ...new Set(flatten(response.jobs.map(({ config: { groups = [] } }) => groups))),
- ]);
setSaveState(SAVE_STATE.NOT_SAVED);
} catch (e) {
// eslint-disable-next-line no-console
@@ -134,11 +138,13 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => {
loadModule();
}, []);
+ /**
+ * Sets up recognizer module configuration.
+ */
const save = async (formValues: JobSettingsFormValues) => {
setSaveState(SAVE_STATE.SAVING);
const {
jobPrefix: resultJobPrefix,
- jobGroups: resultJobGroups,
startDatafeedAfterSave,
useDedicatedIndex,
useFullIndexData,
@@ -148,14 +154,17 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => {
const resultTimeRange = await getTimeRange(useFullIndexData, timeRange);
try {
+ let jobOverridesPayload: JobOverride[] | null = Object.values(jobOverrides);
+ jobOverridesPayload = jobOverridesPayload.length > 0 ? jobOverridesPayload : null;
+
const response: DataRecognizerConfigResponse = await ml.setupDataRecognizerConfig({
moduleId,
prefix: resultJobPrefix,
- groups: resultJobGroups,
query: tempQuery,
indexPatternName: indexPattern.title,
useDedicatedIndex,
startDatafeed: startDatafeedAfterSave,
+ ...(jobOverridesPayload !== null ? { jobOverrides: jobOverridesPayload } : {}),
...resultTimeRange,
});
const { datafeeds: datafeedsResponse, jobs: jobsResponse, kibana: kibanaResponse } = response;
@@ -208,6 +217,13 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => {
}
};
+ const onJobOverridesChange = (job: JobOverride) => {
+ setJobOverrides({
+ ...jobOverrides,
+ [job.job_id as string]: job,
+ });
+ };
+
const isFormVisible = [SAVE_STATE.NOT_SAVED, SAVE_STATE.SAVING].includes(saveState);
return (
@@ -271,10 +287,8 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => {
onChange={formValues => {
setJobPrefix(formValues.jobPrefix);
}}
- existingGroupIds={existingGroupIds}
saveState={saveState}
jobs={jobs}
- jobGroups={jobGroups}
/>
)}
= ({ moduleId, existingGroupIds }) => {
-
+
{Object.keys(kibanaObjects).length > 0 && (
<>
diff --git a/x-pack/legacy/plugins/ml/public/services/ml_api_service/index.js b/x-pack/legacy/plugins/ml/public/services/ml_api_service/index.js
index c6a60a9eff7da..94c79fe470236 100644
--- a/x-pack/legacy/plugins/ml/public/services/ml_api_service/index.js
+++ b/x-pack/legacy/plugins/ml/public/services/ml_api_service/index.js
@@ -292,7 +292,8 @@ export const ml = {
'useDedicatedIndex',
'startDatafeed',
'start',
- 'end'
+ 'end',
+ 'jobOverrides',
]);
return http({
diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/__tests__/data_recognizer.js b/x-pack/legacy/plugins/ml/server/models/data_recognizer/__tests__/data_recognizer.js
index 2ed0f9b2db734..af5039fafdc60 100644
--- a/x-pack/legacy/plugins/ml/server/models/data_recognizer/__tests__/data_recognizer.js
+++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/__tests__/data_recognizer.js
@@ -4,8 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-
-
import expect from '@kbn/expect';
import { DataRecognizer } from '../data_recognizer';
@@ -36,10 +34,68 @@ describe('ML - data recognizer', () => {
expect(ids.join()).to.equal(moduleIds.join());
});
-
it('getModule - load a single module', async () => {
const module = await dr.getModule(moduleIds[0]);
expect(module.id).to.equal(moduleIds[0]);
});
+ describe('jobOverrides', () => {
+ it('should apply job overrides correctly', () => {
+ // arrange
+ const prefix = 'pre-';
+ const testJobId = 'test-job';
+ const moduleConfig = {
+ jobs: [
+ {
+ id: `${prefix}${testJobId}`,
+ config: {
+ groups: ['nginx'],
+ analysis_config: {
+ bucket_span: '1h'
+ },
+ analysis_limits: {
+ model_memory_limit: '256mb',
+ influencers: [
+ 'region'
+ ]
+ },
+ calendars: ['calendar-1'],
+ }
+ },
+ ],
+ };
+ const jobOverrides = [
+ {
+ analysis_limits: {
+ model_memory_limit: '512mb',
+ influencers: [],
+ }
+ },
+ {
+ job_id: testJobId,
+ groups: [],
+ },
+ ];
+ // act
+ dr.applyJobConfigOverrides(moduleConfig, jobOverrides, prefix);
+ // assert
+ expect(moduleConfig.jobs).to.eql([
+ {
+ config: {
+ analysis_config: {
+ bucket_span: '1h'
+ },
+ analysis_limits: {
+ model_memory_limit: '512mb',
+ influencers: [],
+ },
+ groups: [],
+ calendars: ['calendar-1'],
+ },
+ id: 'pre-test-job'
+ }
+ ]);
+ });
+ });
});
+
diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.js b/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.js
index 0b0d2c5adfea0..b5c897a5a3cc9 100644
--- a/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.js
+++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.js
@@ -811,45 +811,78 @@ export class DataRecognizer {
}
applyJobConfigOverrides(moduleConfig, jobOverrides, jobPrefix = '') {
- if(jobOverrides !== undefined && jobOverrides !== null) {
- if (typeof jobOverrides !== 'object') {
- throw Boom.badRequest(
- `Incompatible jobOverrides type (${typeof jobOverrides}). It needs to be an object or array of objects.`
- );
+ if (jobOverrides === undefined || jobOverrides === null) {
+ return;
+ }
+
+ if (typeof jobOverrides !== 'object') {
+ throw Boom.badRequest(
+ `Incompatible jobOverrides type (${typeof jobOverrides}). It needs to be an object or array of objects.`
+ );
+ }
+
+ // jobOverrides could be a single object or an array of objects.
+ // if single, convert to an array
+ const overrides = Array.isArray(jobOverrides) ? jobOverrides : [jobOverrides];
+ const { jobs } = moduleConfig;
+
+ // separate all the overrides.
+ // the overrides which don't contain a job id will be applied to all jobs in the module
+ const generalOverrides = [];
+ const jobSpecificOverrides = [];
+
+ overrides.forEach(override => {
+ if (override.job_id === undefined) {
+ generalOverrides.push(override);
+ } else {
+ jobSpecificOverrides.push(override);
}
+ });
- // jobOverrides could be a single object or an array of objects.
- // if single, convert to an array
- const overrides = Array.isArray(jobOverrides) ? jobOverrides : [jobOverrides];
- const { jobs } = moduleConfig;
+ function processArrayValues(source, update) {
+ if (typeof source !== 'object' || typeof update !== 'object') {
+ return;
+ }
- // separate all the overrides.
- // the overrides which don't contain a job id will be applied to all jobs in the module
- const generalOverrides = [];
- const jobSpecificOverrides = [];
- overrides.forEach(o => {
- if (o.job_id === undefined) {
- generalOverrides.push(o);
+ Object.keys(source).forEach(key => {
+ const sourceValue = source[key];
+ const updateValue = update[key];
+
+ if (
+ typeof sourceValue !== 'object' ||
+ sourceValue === null ||
+ typeof updateValue !== 'object' ||
+ updateValue === null
+ ) {
+ return;
+ }
+
+ if (Array.isArray(sourceValue) && Array.isArray(updateValue)) {
+ source[key] = updateValue;
} else {
- jobSpecificOverrides.push(o);
+ processArrayValues(sourceValue, updateValue);
}
});
+ }
- generalOverrides.forEach(o => {
- jobs.forEach(({ config }) => merge(config, o));
+ generalOverrides.forEach(generalOverride => {
+ jobs.forEach(job => {
+ merge(job.config, generalOverride);
+ processArrayValues(job.config, generalOverride);
});
+ });
- jobSpecificOverrides.forEach(o => {
- // for each override, find the relevant job.
- // note, the job id already has the prefix prepended to it
- const job = jobs.find(j => j.id === `${jobPrefix}${o.job_id}`);
- if (job !== undefined) {
- // delete the job_id in the override as this shouldn't be overridden
- delete o.job_id;
- merge(job.config, o);
- }
- });
- }
+ jobSpecificOverrides.forEach(jobSpecificOverride => {
+ // for each override, find the relevant job.
+ // note, the job id already has the prefix prepended to it
+ const job = jobs.find(j => j.id === `${jobPrefix}${jobSpecificOverride.job_id}`);
+ if (job !== undefined) {
+ // delete the job_id in the override as this shouldn't be overridden
+ delete jobSpecificOverride.job_id;
+ merge(job.config, jobSpecificOverride);
+ processArrayValues(job.config, jobSpecificOverride);
+ }
+ });
}
applyDatafeedConfigOverrides(moduleConfig, datafeedOverrides, jobPrefix = '') {
diff --git a/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.js b/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.js
index 9d5ebd274ea9e..5443d6cbee6b5 100644
--- a/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.js
+++ b/x-pack/legacy/plugins/monitoring/public/components/chart/chart_target.js
@@ -35,6 +35,7 @@ export class ChartTarget extends React.Component {
componentWillUnmount() {
this.shutdownChart();
window.removeEventListener('resize', this._handleResize);
+ this.componentUnmounted = true;
}
filterByShow(seriesToShow) {
@@ -62,7 +63,6 @@ export class ChartTarget extends React.Component {
componentDidMount() {
this.renderChart();
- window.addEventListener('resize', this._handleResize, false);
}
componentDidUpdate() {
@@ -94,6 +94,9 @@ export class ChartTarget extends React.Component {
const data = this.filterData(series, this.props.seriesToShow);
this.plot = $.plot(target, data, await this.getOptions());
+ if (this.componentUnmounted || !this.plot) {
+ return;
+ }
this._handleResize = () => {
if (!this.plot) { return; }
@@ -110,6 +113,8 @@ export class ChartTarget extends React.Component {
}
};
+ window.addEventListener('resize', this._handleResize, false);
+
this.handleMouseLeave = () => {
eventBus.trigger('thorPlotLeave', []);
};
diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap
index cda5a9ffe657c..ea5ff3876245c 100644
--- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap
+++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap
@@ -1298,7 +1298,7 @@ exports[`Flyout kibana part two should show instructions to migrate to metricbea
"link":
-
- setUseInternalCollection(false)}>
-
-
-
-
+ { !props.isOnCloud ? (
+
+
+ setUseInternalCollection(false)}>
+
+
+
+
+
+ ) : null }
diff --git a/x-pack/legacy/plugins/monitoring/public/lib/setup_mode.js b/x-pack/legacy/plugins/monitoring/public/lib/setup_mode.js
index 3e7d182f1514c..7da419719e70c 100644
--- a/x-pack/legacy/plugins/monitoring/public/lib/setup_mode.js
+++ b/x-pack/legacy/plugins/monitoring/public/lib/setup_mode.js
@@ -7,6 +7,7 @@
import { ajaxErrorHandlersProvider } from './ajax_error_handler';
import { get, contains } from 'lodash';
import chrome from 'ui/chrome';
+import { i18n } from '@kbn/i18n';
function isOnPage(hash) {
return contains(window.location.hash, hash);
@@ -80,7 +81,7 @@ export const updateSetupModeData = async (uuid, fetchWithoutClusterUuid = false)
const oldData = setupModeState.data;
const data = await fetchCollectionData(uuid, fetchWithoutClusterUuid);
setupModeState.data = data;
- if (get(data, '_meta.isOnCloud', false)) {
+ if (chrome.getInjected('isOnCloud')) {
return toggleSetupMode(false); // eslint-disable-line no-use-before-define
}
notifySetupModeDataChange(oldData);
@@ -139,15 +140,17 @@ export const setSetupModeMenuItem = () => {
}
const globalState = angularState.injector.get('globalState');
- const navItems = globalState.inSetupMode
- ? []
- : [{
+ const navItems = [];
+ if (!globalState.inSetupMode && !chrome.getInjected('isOnCloud')) {
+ navItems.push({
id: 'enter',
- label: 'Enter Setup Mode',
- description: 'Enter setup',
+ label: i18n.translate('xpack.monitoring.setupMode.enter', {
+ defaultMessage: 'Enter Setup Mode'
+ }),
run: () => toggleSetupMode(true),
testId: 'enterSetupMode'
- }];
+ });
+ }
angularState.scope.topNavMenu = [...navItems];
// LOL angular
diff --git a/x-pack/legacy/plugins/monitoring/public/lib/setup_mode.test.js b/x-pack/legacy/plugins/monitoring/public/lib/setup_mode.test.js
index b5878c7ec5181..4e3a8045048ae 100644
--- a/x-pack/legacy/plugins/monitoring/public/lib/setup_mode.test.js
+++ b/x-pack/legacy/plugins/monitoring/public/lib/setup_mode.test.js
@@ -4,13 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- toggleSetupMode,
- initSetupModeState,
- getSetupModeState,
- updateSetupModeData,
- setSetupModeMenuItem
-} from './setup_mode';
+let toggleSetupMode;
+let initSetupModeState;
+let getSetupModeState;
+let updateSetupModeData;
+let setSetupModeMenuItem;
jest.mock('./ajax_error_handler', () => ({
ajaxErrorHandlersProvider: err => {
@@ -52,16 +50,31 @@ function waitForSetupModeData(action) {
process.nextTick(action);
}
+function setModules() {
+ jest.resetModules();
+ injectorModulesMock.globalState.inSetupMode = false;
+
+ const setupMode = require('./setup_mode');
+ toggleSetupMode = setupMode.toggleSetupMode;
+ initSetupModeState = setupMode.initSetupModeState;
+ getSetupModeState = setupMode.getSetupModeState;
+ updateSetupModeData = setupMode.updateSetupModeData;
+ setSetupModeMenuItem = setupMode.setSetupModeMenuItem;
+}
+
describe('setup_mode', () => {
- describe('setup', () => {
- afterEach(async () => {
- try {
- toggleSetupMode(false);
- } catch (err) {
- // Do nothing...
+ beforeEach(async () => {
+ jest.doMock('ui/chrome', () => ({
+ getInjected: (key) => {
+ if (key === 'isOnCloud') {
+ return false;
+ }
}
- });
+ }));
+ setModules();
+ });
+ describe('setup', () => {
it('should require angular state', async () => {
let error;
try {
@@ -99,21 +112,25 @@ describe('setup_mode', () => {
describe('in setup mode', () => {
afterEach(async () => {
data = {};
- toggleSetupMode(false);
});
it('should enable it through clicking top nav item', async () => {
initSetupModeState(angularStateMock.scope, angularStateMock.injector);
+ setSetupModeMenuItem();
+ expect(injectorModulesMock.globalState.inSetupMode).toBe(false);
await angularStateMock.scope.topNavMenu[0].run();
expect(injectorModulesMock.globalState.inSetupMode).toBe(true);
});
it('should not fetch data if on cloud', async (done) => {
- data = {
- _meta: {
- isOnCloud: true
+ jest.doMock('ui/chrome', () => ({
+ getInjected: (key) => {
+ if (key === 'isOnCloud') {
+ return true;
+ }
}
- };
+ }));
+ setModules();
initSetupModeState(angularStateMock.scope, angularStateMock.injector);
await toggleSetupMode(true);
waitForSetupModeData(() => {
diff --git a/x-pack/legacy/plugins/monitoring/public/monitoring.js b/x-pack/legacy/plugins/monitoring/public/monitoring.js
index e0b504780c838..ff47d6ecf7b7f 100644
--- a/x-pack/legacy/plugins/monitoring/public/monitoring.js
+++ b/x-pack/legacy/plugins/monitoring/public/monitoring.js
@@ -7,6 +7,7 @@
import uiRoutes from 'ui/routes';
import chrome from 'ui/chrome';
import 'ui/kbn_top_nav';
+import 'ui/directives/storage';
import 'ui/autoload/all';
import 'plugins/monitoring/filters';
import 'plugins/monitoring/services/clusters';
diff --git a/x-pack/legacy/plugins/monitoring/public/views/no_data/controller.js b/x-pack/legacy/plugins/monitoring/public/views/no_data/controller.js
index 0ecd6c83265ff..f364b70fd934f 100644
--- a/x-pack/legacy/plugins/monitoring/public/views/no_data/controller.js
+++ b/x-pack/legacy/plugins/monitoring/public/views/no_data/controller.js
@@ -5,6 +5,7 @@
*/
import React from 'react';
+import chrome from 'ui/chrome';
import {
ClusterSettingsChecker,
NodeSettingsChecker,
@@ -99,7 +100,12 @@ export class NoDataController extends MonitoringViewBaseController {
this.renderReact(
-
+
);
}
diff --git a/x-pack/legacy/plugins/monitoring/server/lib/setup/collection/get_collection_status.js b/x-pack/legacy/plugins/monitoring/server/lib/setup/collection/get_collection_status.js
index a49da8ba60200..cd5781ccf5344 100644
--- a/x-pack/legacy/plugins/monitoring/server/lib/setup/collection/get_collection_status.js
+++ b/x-pack/legacy/plugins/monitoring/server/lib/setup/collection/get_collection_status.js
@@ -547,7 +547,6 @@ export const getCollectionStatus = async (req, indexPatterns, clusterUuid, nodeU
status._meta = {
secondsAgo: NUMBER_OF_SECONDS_AGO_TO_LOOK,
liveClusterUuid,
- isOnCloud: get(req.server.plugins, 'cloud.config.isCloudEnabled', false)
};
return status;
diff --git a/x-pack/legacy/plugins/monitoring/ui_exports.js b/x-pack/legacy/plugins/monitoring/ui_exports.js
index a10b83086f738..0976292be576b 100644
--- a/x-pack/legacy/plugins/monitoring/ui_exports.js
+++ b/x-pack/legacy/plugins/monitoring/ui_exports.js
@@ -5,6 +5,7 @@
*/
import { i18n } from '@kbn/i18n';
+import { get } from 'lodash';
import { resolve } from 'path';
/**
@@ -28,7 +29,8 @@ export const getUiExports = () => ({
injectDefaultVars(server) {
const config = server.config();
return {
- monitoringUiEnabled: config.get('xpack.monitoring.ui.enabled')
+ monitoringUiEnabled: config.get('xpack.monitoring.ui.enabled'),
+ isOnCloud: get(server.plugins, 'cloud.config.isCloudEnabled', false)
};
},
hacks: [ 'plugins/monitoring/hacks/toggle_app_link_in_nav' ],
diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts
index 0c63def67bd04..30bbac61b0248 100644
--- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts
+++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts
@@ -26,9 +26,8 @@ import { getElementPositionAndAttributes } from './get_element_position_data';
import { getScreenshots } from './get_screenshots';
import { skipTelemetry } from './skip_telemetry';
-// NOTE: Typescript does not throw an error if this interface has errors!
interface ScreenshotResults {
- timeRang: TimeRange;
+ timeRange: TimeRange;
screenshots: Screenshot[];
}
@@ -49,6 +48,7 @@ export function screenshotsObservableFactory(server: ServerFacade) {
browserTimezone,
});
+ // @ts-ignore this needs to be refactored to use less random type declaration and instead rely on structures that work with inference
return create$.pipe(
mergeMap(({ driver$, exit$ }) => {
const screenshot$ = driver$.pipe(
diff --git a/x-pack/legacy/plugins/reporting/public/components/__snapshots__/report_info_button.test.tsx.snap b/x-pack/legacy/plugins/reporting/public/components/__snapshots__/report_info_button.test.tsx.snap
index a34d0388a5e3f..54489f18a93d2 100644
--- a/x-pack/legacy/plugins/reporting/public/components/__snapshots__/report_info_button.test.tsx.snap
+++ b/x-pack/legacy/plugins/reporting/public/components/__snapshots__/report_info_button.test.tsx.snap
@@ -87,7 +87,11 @@ Array [
as="div"
autoFocus={true}
disabled={false}
- lockProps={Object {}}
+ lockProps={
+ Object {
+ "style": undefined,
+ }
+ }
noFocusGuards={false}
persistentFocus={false}
returnFocus={true}
@@ -496,7 +500,11 @@ Array [
as="div"
autoFocus={true}
disabled={false}
- lockProps={Object {}}
+ lockProps={
+ Object {
+ "style": undefined,
+ }
+ }
noFocusGuards={false}
persistentFocus={false}
returnFocus={true}
diff --git a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts
index f16485537f53a..ca26f7d41c12a 100644
--- a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts
+++ b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts
@@ -174,8 +174,8 @@ export class HeadlessChromiumDriverFactory {
}
getBrowserLogger(page: Page): Rx.Observable {
- return Rx.fromEvent(page as NodeJS.EventEmitter, 'console').pipe(
- tap((line: ConsoleMessage) => {
+ return Rx.fromEvent(page, 'console').pipe(
+ tap(line => {
if (line.type() === 'error') {
this.logger.error(line.text(), ['headless-browser-console']);
} else {
@@ -185,14 +185,14 @@ export class HeadlessChromiumDriverFactory {
);
}
- getProcessLogger(browser: Browser): Rx.Observable {
+ getProcessLogger(browser: Browser) {
const childProcess = browser.process();
// NOTE: The browser driver can not observe stdout and stderr of the child process
// Puppeteer doesn't give a handle to the original ChildProcess object
// See https://github.com/GoogleChrome/puppeteer/issues/1292#issuecomment-521470627
// just log closing of the process
- const processClose$: Rx.Observable = Rx.fromEvent(childProcess, 'close').pipe(
+ const processClose$ = Rx.fromEvent(childProcess, 'close').pipe(
tap(() => {
this.logger.debug('child process closed', ['headless-browser-process']);
})
@@ -201,17 +201,15 @@ export class HeadlessChromiumDriverFactory {
return processClose$; // ideally, this would also merge with observers for stdout and stderr
}
- getPageExit(browser: Browser, page: Page): Rx.Observable {
- const pageError$: Rx.Observable = Rx.fromEvent(page, 'error').pipe(
- mergeMap((err: Error) => Rx.throwError(err))
- );
+ getPageExit(browser: Browser, page: Page) {
+ const pageError$ = Rx.fromEvent(page, 'error').pipe(mergeMap(err => Rx.throwError(err)));
- const uncaughtExceptionPageError$: Rx.Observable = Rx.fromEvent(page, 'pageerror').pipe(
- mergeMap((err: Error) => Rx.throwError(err))
+ const uncaughtExceptionPageError$ = Rx.fromEvent(page, 'pageerror').pipe(
+ mergeMap(err => Rx.throwError(err))
);
- const pageRequestFailed$: Rx.Observable = Rx.fromEvent(page, 'requestfailed').pipe(
- mergeMap((req: PuppeteerRequest) => {
+ const pageRequestFailed$ = Rx.fromEvent(page, 'requestfailed').pipe(
+ mergeMap(req => {
const failure = req.failure && req.failure();
if (failure) {
return Rx.throwError(
diff --git a/x-pack/legacy/plugins/searchprofiler/index.js b/x-pack/legacy/plugins/searchprofiler/index.js
deleted file mode 100644
index 107edeb1f408d..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/index.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { resolve } from 'path';
-import { profileRoute } from './server/routes/profile';
-
-// License
-import Boom from 'boom';
-import { checkLicense } from './server/lib/check_license';
-import { mirrorPluginStatus } from '../../server/lib/mirror_plugin_status';
-
-
-export const searchprofiler = (kibana) => {
- return new kibana.Plugin({
- require: ['elasticsearch', 'xpack_main'],
- id: 'searchprofiler',
- configPrefix: 'xpack.searchprofiler',
- publicDir: resolve(__dirname, 'public'),
-
- uiExports: {
- devTools: ['plugins/searchprofiler/app'],
- hacks: ['plugins/searchprofiler/register'],
- home: ['plugins/searchprofiler/register_feature'],
- styleSheetPaths: resolve(__dirname, 'public/index.scss'),
- },
- init: function (server) {
- const thisPlugin = this;
- const xpackMainPlugin = server.plugins.xpack_main;
- mirrorPluginStatus(xpackMainPlugin, thisPlugin);
- xpackMainPlugin.status.once('green', () => {
- // Register a function that is called whenever the xpack info changes,
- // to re-compute the license check results for this plugin
- xpackMainPlugin.info.feature(thisPlugin.id).registerLicenseCheckResultsGenerator(checkLicense);
- });
-
- // Add server routes and initialize the plugin here
- const commonRouteConfig = {
- pre: [
- function forbidApiAccess() {
- const licenseCheckResults = xpackMainPlugin.info.feature(thisPlugin.id).getLicenseCheckResults();
- if (licenseCheckResults.showAppLink && licenseCheckResults.enableAppLink) {
- return null;
- } else {
- throw Boom.forbidden(licenseCheckResults.message);
- }
- }
- ]
- };
- profileRoute(server, commonRouteConfig);
- }
-
- });
-};
diff --git a/x-pack/legacy/plugins/searchprofiler/index.ts b/x-pack/legacy/plugins/searchprofiler/index.ts
new file mode 100644
index 0000000000000..5de6ba710235b
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/index.ts
@@ -0,0 +1,65 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { resolve } from 'path';
+import Boom from 'boom';
+
+import { CoreSetup } from 'src/core/server';
+import { Server } from 'src/legacy/server/kbn_server';
+import { LegacySetup } from './server/np_ready/types';
+import { plugin } from './server/np_ready';
+
+export const searchprofiler = (kibana: any) => {
+ const publicSrc = resolve(__dirname, 'public');
+
+ return new kibana.Plugin({
+ require: ['elasticsearch', 'xpack_main'],
+ id: 'searchprofiler',
+ configPrefix: 'xpack.searchprofiler',
+ publicDir: publicSrc,
+
+ uiExports: {
+ // NP Ready
+ devTools: [`${publicSrc}/legacy`],
+ styleSheetPaths: `${publicSrc}/np_ready/application/index.scss`,
+ // Legacy
+ hacks: ['plugins/searchprofiler/register'],
+ home: ['plugins/searchprofiler/register_feature'],
+ },
+ init(server: Server) {
+ const serverPlugin = plugin();
+ const thisPlugin = this;
+
+ const commonRouteConfig = {
+ pre: [
+ function forbidApiAccess() {
+ const licenseCheckResults = server.plugins.xpack_main.info
+ .feature(thisPlugin.id)
+ .getLicenseCheckResults();
+ if (licenseCheckResults.showAppLink && licenseCheckResults.enableAppLink) {
+ return null;
+ } else {
+ throw Boom.forbidden(licenseCheckResults.message);
+ }
+ },
+ ],
+ };
+
+ const legacySetup: LegacySetup = {
+ route: (args: Parameters[0]) => server.route(args),
+ plugins: {
+ __LEGACY: {
+ thisPlugin,
+ xpackMain: server.plugins.xpack_main,
+ elasticsearch: server.plugins.elasticsearch,
+ commonRouteConfig,
+ },
+ },
+ };
+ serverPlugin.setup({} as CoreSetup, legacySetup);
+ },
+ });
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/app.js b/x-pack/legacy/plugins/searchprofiler/public/app.js
deleted file mode 100644
index 1c7598ab982bc..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/app.js
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-
-// K5 imports
-import { uiModules } from 'ui/modules';
-import { i18n } from '@kbn/i18n';
-import uiRoutes from 'ui/routes';
-import 'ui/capabilities/route_setup';
-import { toastNotifications } from 'ui/notify';
-import { formatAngularHttpError } from 'ui/notify/lib';
-
-// License
-import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
-
-// Our imports
-import $ from 'jquery';
-import _ from 'lodash';
-import 'ace';
-import 'angular-ui-ace';
-import 'plugins/searchprofiler/directives';
-import './components/searchprofiler_tabs_directive';
-import { Range } from './range';
-import { nsToPretty } from 'plugins/searchprofiler/filters/ns_to_pretty';
-import { msToPretty } from 'plugins/searchprofiler/filters/ms_to_pretty';
-import { checkForParseErrors } from 'plugins/searchprofiler/app_util.js';
-import { initializeEditor } from 'plugins/searchprofiler/editor';
-
-// Styles and templates
-import 'ui/autoload/all';
-import template from './templates/index.html';
-import { defaultQuery } from './templates/default_query';
-
-uiRoutes.when('/dev_tools/searchprofiler', {
- template: template,
- requireUICapability: 'dev_tools.show',
- controller: $scope => {
- $scope.registerLicenseLinkLabel = i18n.translate('xpack.searchProfiler.registerLicenseLinkLabel',
- { defaultMessage: 'register a license' });
- $scope.trialLicense = i18n.translate('xpack.searchProfiler.trialLicenseTitle',
- { defaultMessage: 'Trial' });
- $scope.basicLicense = i18n.translate('xpack.searchProfiler.basicLicenseTitle',
- { defaultMessage: 'Basic' });
- $scope.goldLicense = i18n.translate('xpack.searchProfiler.goldLicenseTitle',
- { defaultMessage: 'Gold' });
- $scope.platinumLicense = i18n.translate('xpack.searchProfiler.platinumLicenseTitle',
- { defaultMessage: 'Platinum' });
- },
-});
-
-uiModules
- .get('app/searchprofiler', ['ui.ace'])
- .controller('profileViz', profileVizController)
- .filter('nsToPretty', () => nsToPretty)
- .filter('msToPretty', () => msToPretty)
- .factory('HighlightService', () => {
- const service = {
- details: null
- };
- return service;
- });
-
-function profileVizController($scope, $timeout, $http, HighlightService) {
- $scope.title = 'Search Profile';
- $scope.description = 'Search profiling and visualization';
- $scope.profileResponse = [];
- $scope.highlight = HighlightService;
- $scope.index = '_all';
- $scope.query = '';
-
- // TODO this map controls which tab is active, but due to how
- // the tab directive works, we cannot use a single variable to hold the state.
- // Instead we have to map the tab name to true/false, and make sure only one
- // state is active. This should be refactored if possible, as it could be trappy!
- $scope.activeTab = {
- search: true
- };
- $scope.markers = [];
- $scope.licenseEnabled = xpackInfo.get('features.searchprofiler.enableAppLink');
-
-
- const editor = initializeEditor({
- el: $('#SearchProfilerInput')[0],
- licenseEnabled: $scope.licenseEnabled,
- });
-
- editor.on('change', () => {
- // Do a safe apply/trigger digest
- $timeout(() => {
- $scope.query = editor.getValue();
- });
- });
-
- editor.setValue(defaultQuery, 1);
-
- $scope.hasQuery = () => Boolean($scope.query);
-
- $scope.profile = () => {
- const { query } = $scope;
- if (!$scope.licenseEnabled) {
- return;
- }
- // Reset right detail panel
- $scope.resetHighlightPanel();
- let json = checkForParseErrors(query);
- if (json.status === false) {
- toastNotifications.addError(json.error, {
- title: i18n.translate('xpack.searchProfiler.errorToastTitle', {
- defaultMessage: 'JSON parse error',
- }),
- });
- return;
- }
- json = json.parsed;
-
- // If we can find the start of a profile JSON output, just try to render it
- // without executing
- if (json.profile && json.profile.shards) {
- $scope.renderProfile(json.profile.shards);
- } else {
- // Otherwise it's (probably) a regular search, execute remotely
- const requestBody = { query };
- if ($scope.index == null || $scope.index === '') {
- requestBody.index = '_all';
- } else {
- requestBody.index = $scope.index;
- }
- if (!$scope.type === '') {
- requestBody.type = $scope.type;
- }
- $scope.executeRemoteQuery(requestBody);
- }
- };
-
- $scope.executeRemoteQuery = requestBody => {
- $http.post('../api/searchprofiler/profile', requestBody).then(resp => {
- if (!resp.data.ok) {
- toastNotifications.addDanger(resp.data.err.msg);
-
- try {
- const regex = /line=([0-9]+) col=([0-9]+)/g;
- const [ , row, column ] = regex.exec(resp.data.err.msg);
-
- $scope.markers.push($scope.ace.session.addMarker(
- new Range(row - 1, 0, row - 1, column), 'errorMarker', 'fullLine'));
- } catch (e) {
- // Best attempt, not a big deal if we can't highlight the line
- }
-
- return;
- }
-
- $scope.renderProfile(resp.data.resp.profile.shards);
- }).catch(reason => toastNotifications.addDanger(formatAngularHttpError(reason)));
- };
-
- $scope.renderProfile = data => {
- for (const shard of data) {
- shard.id = shard.id.match(/\[([^\]\[]*?)\]/g);
- shard.id = _.map(shard.id, id => {
- return id.replace('[', '').replace(']', '');
- });
- }
- $scope.profileResponse = data;
-
- const hasAggregations = data[0].aggregations != null && data[0].aggregations.length > 0;
- if (!hasAggregations) {
- // No aggs, reset back to search panel
- $scope.activateTab('search');
- }
- };
-
- $scope.activateTab = tab => {
- // Reset right detail panel
- $scope.resetHighlightPanel();
- // Reset active tab map
- $scope.activeTab = {};
- if (tab === 'aggregations') {
- $scope.activeTab.aggregations = true;
- } else {
- // Everything has a search, so default to this
- $scope.activeTab.search = true;
- }
- };
-
- $scope.resetHighlightPanel = () => {
- $scope.highlight.details = null;
- };
-
-}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/components/searchprofiler_tabs.js b/x-pack/legacy/plugins/searchprofiler/public/components/searchprofiler_tabs.js
deleted file mode 100644
index 5394e56cef70a..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/components/searchprofiler_tabs.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-
-import _ from 'lodash';
-import PropTypes from 'prop-types';
-import React from 'react';
-
-import {
- EuiTabs,
- EuiTab
-} from '@elastic/eui';
-
-import { FormattedMessage } from '@kbn/i18n/react';
-
-function hasSearch(profileResponse) {
- const aggs = _.get(profileResponse, '[0].searches', []);
- return aggs.length > 0;
-}
-
-function hasAggregations(profileResponse) {
- const aggs = _.get(profileResponse, '[0].aggregations', []);
- return aggs.length > 0;
-}
-
-
-function handleClick(activateTab, tabName) {
- activateTab(tabName);
-}
-
-export function SearchProfilerTabs(props) {
- return (
-
- handleClick(props.activateTab, 'search')}
- >
-
-
- handleClick(props.activateTab, 'aggregations')}
- >
-
-
-
- );
-}
-
-SearchProfilerTabs.propTypes = {
- activeTab: PropTypes.any.isRequired,
- activateTab: PropTypes.func.isRequired,
- profileResponse: PropTypes.array.isRequired,
-};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/components/searchprofiler_tabs_directive.js b/x-pack/legacy/plugins/searchprofiler/public/components/searchprofiler_tabs_directive.js
deleted file mode 100644
index 6cfeb97f05ebd..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/components/searchprofiler_tabs_directive.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import 'ngreact';
-
-import { wrapInI18nContext } from 'ui/i18n';
-import { uiModules } from 'ui/modules';
-const module = uiModules.get('apps/searchprofiler', ['react']);
-
-import { SearchProfilerTabs } from './searchprofiler_tabs';
-
-module.directive('searchProfilerTabs', function (reactDirective) {
- return reactDirective(
- wrapInI18nContext(SearchProfilerTabs),
- undefined,
- { restrict: 'E' }
- );
-});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/_directives.scss b/x-pack/legacy/plugins/searchprofiler/public/directives/_directives.scss
deleted file mode 100644
index 7f4f44748aa93..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/_directives.scss
+++ /dev/null
@@ -1,135 +0,0 @@
-.prfDevTool__panel {
- border-bottom: $euiBorderThin;
-}
-
-.prfDevTool__panelBody {
- margin-top: $euiSizeS;
- margin-left: $euiSizeL;
-}
-
-// Profile details treeview
-.prfDevTool__shardDetailsWrapper {
- display: flex;
- flex-direction: row-reverse;
- justify-content: space-between;
- align-items: center;
-}
-
-.prfDevTool__shardDetails--dim small {
- color: $euiColorDarkShade;
-}
-
-.prfDevTool__shardBody {
- margin-top: $euiSize;
-}
-
-.prfDevTool__shardDetails {
- line-height: 1;
- overflow-wrap: break-word;
-
- &:disabled {
- text-decoration: none !important;
- cursor: default;
- }
-}
-
-.prfDevTool__shard {
- border: none;
-}
-
-.prfDevTool__index {
- width: 100%;
- padding: $euiSize $euiSizeS;
-}
-
-.prfDevTool__tvRow--last {
- cursor: pointer;
-}
-
-.prfDevTool__tvRow,
-.prfDevTool__tvHeader {
- display: table;
- width: 100%;
- table-layout: fixed;
-}
-
-.prfDevTool__tvHeader {
- @include euiFontSizeXS;
- color: $euiColorDarkShade;
-}
-
-.prfDevTool__cell {
- display: table-cell;
- vertical-align: middle;
- text-align: center;
- padding: $euiSizeXS;
-
- &:first-of-type {
- padding-left: 0;
- }
-
- &:last-of-type {
- padding-right: 0;
- }
-}
-
-.prfDevTool__detail {
- font-size: $euiFontSizeS;
- padding-left: $euiSizeL - 3px; // Alignment is weird
- margin-bottom: $euiSizeS;
- display: flex;
- justify-content: space-between;
-
- .euiLink {
- flex-shrink: 0;
- }
-}
-
-.prfDevTool__description {
- text-align: left;
-}
-
-.prfDevTool__time,
-.prfDevTool__totalTime,
-.prfDevTool__percentage {
- width: $euiSize * 5.5;
-}
-
-// BADGES (and those used for progress)
-
-.prfDevTool__badge {
- border: none;
- display: block;
- // Force text to always be dark on top of white -> pink color
- color: lightOrDarkTheme($euiColorDarkestShade, $euiColorLightestShade);
-}
-
-.prfDevTool__progress--percent {
- @include prfDevToolProgress;
- width: $euiSize * 4;
-}
-
-.prfDevTool__progress--time {
- @include prfDevToolProgress(#FFAFAF);
- background-color: #F5F5F5; // Must be light at all times
- width: $euiSize * 15.5;
- // Force text to always be dark on top of white -> pink color
- color: lightOrDarkTheme($euiColorDarkestShade, $euiColorLightestShade);
-}
-
-// Breakdown table
-.prfDevTool__breakdown {
- width:100%;
-}
-
-.prfDevTool__flyoutSubtitle {
- margin-bottom: $euiSizeS;
- display: inline-block;
-}
-
-@include euiBreakpoint('xs', 's') {
- .prfDevTool__shardDetailsWrapper {
- flex-direction: column;
- align-items: flex-start;
- }
-}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/_index.scss b/x-pack/legacy/plugins/searchprofiler/public/directives/_index.scss
deleted file mode 100644
index 69a53dbafe289..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/_index.scss
+++ /dev/null
@@ -1,2 +0,0 @@
-@import 'mixins';
-@import 'directives';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/highlight_details/index.html b/x-pack/legacy/plugins/searchprofiler/public/directives/highlight_details/index.html
deleted file mode 100644
index f58515390ded2..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/highlight_details/index.html
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
-
-
- {{detailRow.query_type}}
-
- {{detailRow.lucene}}
-
-
-
- {{detailRow.time | msToPretty:3 }}
-
-
-
- {{detailRow.selfTime | msToPretty:3 }}
-
-
-
-
-
-
-
-
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/highlight_details/index.js b/x-pack/legacy/plugins/searchprofiler/public/directives/highlight_details/index.js
deleted file mode 100644
index 717778ed3f4a4..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/highlight_details/index.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import _ from 'lodash';
-import template from 'plugins/searchprofiler/directives/highlight_details/index.html';
-import { uiModules } from 'ui/modules';
-
-const uiModule = uiModules.get('app/searchprofiler/directives', []);
-uiModule.directive('highlightdetails', HighlightService => {
- return {
- restrict: 'E',
- scope: {
- data: '@'
- },
- template: template,
- link: $scope => {
-
- function render(data) {
- if (!data) {
- return;
- }
- data.breakdown = _.filter(data.breakdown, o => o.key.indexOf('_count') === -1);
- $scope.detailRow = data;
- }
-
- $scope.$watch(() => {
- return HighlightService.details;
- }, render);
-
- }
- };
-});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/breakdown.js b/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/breakdown.js
deleted file mode 100644
index 1d88310dafbfd..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/breakdown.js
+++ /dev/null
@@ -1,76 +0,0 @@
-export const breakdown = {
- advance:0,
- advance_count:0,
- build_scorer:6273,
- build_scorer_count:2,
- create_weight:1852,
- create_weight_count:1,
- match:0,
- match_count:0,
- next_doc:2593093,
- next_doc_count:27958,
- score:2525502,
- score_count:27948
-};
-
-export const normalized = [ { key: 'next_doc',
- time: 2593093,
- relative: '50.6',
- color: '#fad2d2',
- tip: 'The time taken to advance the iterator to the next matching document.' },
- { key: 'score',
- time: 2525502,
- relative: '49.3',
- color: '#fad2d2',
- tip: 'The time taken in actually scoring the document against the query.' },
- { key: 'next_doc_count',
- time: 27958,
- relative: 0,
- color: '#f5f5f5',
- tip: '' },
- { key: 'score_count',
- time: 27948,
- relative: 0,
- color: '#f5f5f5',
- tip: '' },
- { key: 'build_scorer',
- time: 6273,
- relative: '0.1',
- color: '#f5f5f5',
- tip: 'The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc.' },
- { key: 'create_weight',
- time: 1852,
- relative: '0.0',
- color: '#f5f5f5',
- tip: 'The time taken to create the Weight object, which holds temporary information during scoring.' },
- { key: 'build_scorer_count',
- time: 2,
- relative: 0,
- color: '#f5f5f5',
- tip: '' },
- { key: 'create_weight_count',
- time: 1,
- relative: 0,
- color: '#f5f5f5',
- tip: '' },
- { key: 'advance',
- time: 0,
- relative: '0.0',
- color: '#f5f5f5',
- tip: 'The time taken to advance the iterator to the next document.' },
- { key: 'advance_count',
- time: 0,
- relative: 0,
- color: '#f5f5f5',
- tip: '' },
- { key: 'match',
- time: 0,
- relative: '0.0',
- color: '#f5f5f5',
- tip: 'The time taken to execute a secondary, more precise scoring phase (used by phrase queries).' },
- { key: 'match_count',
- time: 0,
- relative: 0,
- color: '#f5f5f5',
- tip: '' },
- ];
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/flatten_times.js b/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/flatten_times.js
deleted file mode 100644
index c2017f472bc0b..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/flatten_times.js
+++ /dev/null
@@ -1,405 +0,0 @@
-/* eslint quotes: 0 */
-export const flatTimes = [
- {
- id:"f1e689b1-dafe-4c2b-9a4d-9bd8f1a53803",
- childrenIds:[
- "3339dca6-c34a-49f3-a534-27e46f238bcd",
- "9b75ecdd-a1da-45eb-8d13-5bc5f472dba3",
- "ddf5aa3e-4b22-4332-9d5e-79a6ae0cc9cb"
- ],
- lucene:"hour:1 hour:2 #MatchNoDocsQuery[\"User requested \"match_none\" query.\"]",
- time:0.447365,
- selfTime:0.057085,
- timePercentage:"100.00",
- query_type:"BooleanQuery",
- absoluteColor:"#ffafaf",
- depth:0,
- hasChildren:true,
- breakdown:[
- {
- key:"create_weight",
- time:401690,
- relative:"89.8",
- color:"#feb6b6",
- tip:"The time taken to create the Weight object, which holds temporary information during scoring."
- },
- {
- key:"build_scorer",
- time:45672,
- relative:"10.2",
- color:"#f6eeee",
- tip:"The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc."
- },
- {
- key:"build_scorer_count",
- time:2,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"create_weight_count",
- time:1,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"next_doc",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to advance the iterator to the next matching document."
- },
- {
- key:"match",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to execute a secondary, more precise scoring phase (used by phrase queries)."
- },
- {
- key:"match_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"next_doc_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"score_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"score",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken in actually scoring the document against the query."
- },
- {
- key:"advance",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to advance the iterator to the next document."
- },
- {
- key:"advance_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- }
- ]
- },
- {
- id:"3339dca6-c34a-49f3-a534-27e46f238bcd",
- parentId:"f1e689b1-dafe-4c2b-9a4d-9bd8f1a53803",
- childrenIds:[
-
- ],
- lucene:"hour:1",
- time:0.192502,
- selfTime:0.192502,
- timePercentage:"43.03",
- query_type:"TermQuery",
- absoluteColor:"#f9d7d7",
- depth:1,
- breakdown:[
- {
- key:"create_weight",
- time:190989,
- relative:"99.2",
- color:"#ffb0b0",
- tip:"The time taken to create the Weight object, which holds temporary information during scoring."
- },
- {
- key:"build_scorer",
- time:1510,
- relative:"0.8",
- color:"#f5f4f4",
- tip:"The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc."
- },
- {
- key:"build_scorer_count",
- time:2,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"create_weight_count",
- time:1,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"next_doc",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to advance the iterator to the next matching document."
- },
- {
- key:"match",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to execute a secondary, more precise scoring phase (used by phrase queries)."
- },
- {
- key:"match_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"next_doc_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"score_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"score",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken in actually scoring the document against the query."
- },
- {
- key:"advance",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to advance the iterator to the next document."
- },
- {
- key:"advance_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- }
- ]
- },
- {
- id:"9b75ecdd-a1da-45eb-8d13-5bc5f472dba3",
- parentId:"f1e689b1-dafe-4c2b-9a4d-9bd8f1a53803",
- childrenIds:[
-
- ],
- lucene:"hour:2",
- time:0.162608,
- selfTime:0.162608,
- timePercentage:"36.35",
- query_type:"TermQuery",
- absoluteColor:"#f9dcdc",
- depth:1,
- breakdown:[
- {
- key:"create_weight",
- time:162016,
- relative:"99.6",
- color:"#ffafaf",
- tip:"The time taken to create the Weight object, which holds temporary information during scoring."
- },
- {
- key:"build_scorer",
- time:589,
- relative:"0.4",
- color:"#f5f5f5",
- tip:"The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc."
- },
- {
- key:"build_scorer_count",
- time:2,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"create_weight_count",
- time:1,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"next_doc",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to advance the iterator to the next matching document."
- },
- {
- key:"match",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to execute a secondary, more precise scoring phase (used by phrase queries)."
- },
- {
- key:"match_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"next_doc_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"score_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"score",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken in actually scoring the document against the query."
- },
- {
- key:"advance",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to advance the iterator to the next document."
- },
- {
- key:"advance_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- }
- ]
- },
- {
- id:"ddf5aa3e-4b22-4332-9d5e-79a6ae0cc9cb",
- parentId:"f1e689b1-dafe-4c2b-9a4d-9bd8f1a53803",
- childrenIds:[
-
- ],
- lucene:"MatchNoDocsQuery[\"User requested \"match_none\" query.\"]",
- time:0.03517,
- selfTime:0.03517,
- timePercentage:"7.86",
- query_type:"MatchNoDocsQuery",
- absoluteColor:"#f6efef",
- depth:1,
- breakdown:[
- {
- key:"build_scorer",
- time:32522,
- relative:"92.5",
- color:"#feb4b4",
- tip:"The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc."
- },
- {
- key:"create_weight",
- time:2645,
- relative:"7.5",
- color:"#f6f0f0",
- tip:"The time taken to create the Weight object, which holds temporary information during scoring."
- },
- {
- key:"build_scorer_count",
- time:2,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"create_weight_count",
- time:1,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"next_doc",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to advance the iterator to the next matching document."
- },
- {
- key:"match",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to execute a secondary, more precise scoring phase (used by phrase queries)."
- },
- {
- key:"match_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"next_doc_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"score_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- },
- {
- key:"score",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken in actually scoring the document against the query."
- },
- {
- key:"advance",
- time:0,
- relative:"0.0",
- color:"#f5f5f5",
- tip:"The time taken to advance the iterator to the next document."
- },
- {
- key:"advance_count",
- time:0,
- relative:0,
- color:"#f5f5f5",
- tip:""
- }
- ]
- }
-];
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/normalize_indices.js b/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/normalize_indices.js
deleted file mode 100644
index fee12c17e7d58..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/normalize_indices.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*eslint-disable */
-export const inputIndices = JSON.parse('{"test":{"shards":[{"id":["F-R7QxH4S42fMnPfmFUKMQ","test","0"],"searches":[{"query":null,"rewrite_time":2656,"collector":[{"name":"MultiCollector","reason":"search_multi","time":"0.1815780000ms","children":[{"name":"SimpleTopScoreDocCollector","reason":"search_top_hits","time":"0.02393700000ms"},{"name":"ProfilingAggregator: [org.elasticsearch.search.profile.aggregation.ProfilingAggregator@43c8a536]","reason":"aggregation","time":"0.1140000000ms"}]}],"flat":[{"id":"af697413-f76b-458e-b265-f4930dbdee2a","childrenIds":[],"lucene":"name:george","time":0.219343,"selfTime":0.219343,"timePercentage":"100.00","query_type":"TermQuery","absoluteColor":"#ffafaf","depth":0,"breakdown":[{"key":"create_weight","time":160673,"relative":"73.3","color":"#fcc2c2","tip":"The time taken to create the Weight object, which holds temporary information during scoring."},{"key":"build_scorer","time":50157,"relative":"22.9","color":"#f7e5e5","tip":"The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc."},{"key":"score","time":5783,"relative":"2.6","color":"#f5f3f3","tip":"The time taken in actually scoring the document against the query."},{"key":"next_doc","time":2718,"relative":"1.2","color":"#f5f4f4","tip":"The time taken to advance the iterator to the next matching document."},{"key":"build_scorer_count","time":5,"relative":0,"color":"#f5f5f5","tip":""},{"key":"next_doc_count","time":4,"relative":0,"color":"#f5f5f5","tip":""},{"key":"score_count","time":2,"relative":0,"color":"#f5f5f5","tip":""},{"key":"create_weight_count","time":1,"relative":0,"color":"#f5f5f5","tip":""},{"key":"match","time":0,"relative":"0.0","color":"#f5f5f5","tip":"The time taken to execute a secondary, more precise scoring phase (used by phrase queries)."},{"key":"match_count","time":0,"relative":0,"color":"#f5f5f5","tip":""},{"key":"advance","time":0,"relative":"0.0","color":"#f5f5f5","tip":"The time taken to advance the iterator to the next document."},{"key":"advance_count","time":0,"relative":0,"color":"#f5f5f5","tip":""}]}]}],"aggregations":[{"type":"org.elasticsearch.search.aggregations.metrics.stats.StatsAggregator","description":"stats","time":"0.03053500000ms","breakdown":{"reduce":0,"build_aggregation":9447,"build_aggregation_count":1,"initialize":5589,"initialize_count":1,"reduce_count":0,"collect":15495,"collect_count":2}}],"time":{"searches":0.219343,"aggregations":0},"color":{"searches":0,"aggregations":0},"relative":{"searches":0,"aggregations":0},"rewrite_time":2656}],"time":{"searches":0.219343,"aggregations":0},"name":"test"}}');
-
-export const normalizedIndices = JSON.parse('[{"shards":[{"id":["F-R7QxH4S42fMnPfmFUKMQ","test","0"],"searches":[{"query":null,"rewrite_time":2656,"collector":[{"name":"MultiCollector","reason":"search_multi","time":"0.1815780000ms","children":[{"name":"SimpleTopScoreDocCollector","reason":"search_top_hits","time":"0.02393700000ms"},{"name":"ProfilingAggregator: [org.elasticsearch.search.profile.aggregation.ProfilingAggregator@43c8a536]","reason":"aggregation","time":"0.1140000000ms"}]}],"flat":[{"id":"af697413-f76b-458e-b265-f4930dbdee2a","childrenIds":[],"lucene":"name:george","time":0.219343,"selfTime":0.219343,"timePercentage":"100.00","query_type":"TermQuery","absoluteColor":"#ffafaf","depth":0,"breakdown":[{"key":"create_weight","time":160673,"relative":"73.3","color":"#fcc2c2","tip":"The time taken to create the Weight object, which holds temporary information during scoring."},{"key":"build_scorer","time":50157,"relative":"22.9","color":"#f7e5e5","tip":"The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc."},{"key":"score","time":5783,"relative":"2.6","color":"#f5f3f3","tip":"The time taken in actually scoring the document against the query."},{"key":"next_doc","time":2718,"relative":"1.2","color":"#f5f4f4","tip":"The time taken to advance the iterator to the next matching document."},{"key":"build_scorer_count","time":5,"relative":0,"color":"#f5f5f5","tip":""},{"key":"next_doc_count","time":4,"relative":0,"color":"#f5f5f5","tip":""},{"key":"score_count","time":2,"relative":0,"color":"#f5f5f5","tip":""},{"key":"create_weight_count","time":1,"relative":0,"color":"#f5f5f5","tip":""},{"key":"match","time":0,"relative":"0.0","color":"#f5f5f5","tip":"The time taken to execute a secondary, more precise scoring phase (used by phrase queries)."},{"key":"match_count","time":0,"relative":0,"color":"#f5f5f5","tip":""},{"key":"advance","time":0,"relative":"0.0","color":"#f5f5f5","tip":"The time taken to advance the iterator to the next document."},{"key":"advance_count","time":0,"relative":0,"color":"#f5f5f5","tip":""}]}]}],"aggregations":[{"type":"org.elasticsearch.search.aggregations.metrics.stats.StatsAggregator","description":"stats","time":"0.03053500000ms","breakdown":{"reduce":0,"build_aggregation":9447,"build_aggregation_count":1,"initialize":5589,"initialize_count":1,"reduce_count":0,"collect":15495,"collect_count":2}}],"time":{"searches":0.219343,"aggregations":0},"color":{"searches":"#ffafaf","aggregations":0},"relative":{"searches":"100.00","aggregations":0},"rewrite_time":2656}],"time":{"searches":0.219343,"aggregations":0},"name":"test"}]');
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/index.html b/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/index.html
deleted file mode 100644
index e6994a07aa6d1..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/index.html
+++ /dev/null
@@ -1,115 +0,0 @@
-
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/index.js b/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/index.js
deleted file mode 100644
index b212439e98394..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/index.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import template from 'plugins/searchprofiler/directives/profile_tree/index.html';
-import {
- closeNode,
- normalizeIndices,
- calcTimes,
- normalizeTimes,
- flattenResults
-} from 'plugins/searchprofiler/directives/profile_tree/util';
-import { uiModules } from 'ui/modules';
-
-const uiModule = uiModules.get('app/searchprofiler/directives', []);
-uiModule.directive('profiletree', HighlightService => {
- return {
- restrict: 'E',
- scope: {
- data: '=',
- target: '@'
- },
- template: template,
- link: $scope => {
- $scope.visible = {
- 'foo': {}
- };
- $scope.indexVisibility = {};
- $scope.highlightedRow = null;
-
- $scope.updateDetail = (row, indexName, shardID, shardNumber) => {
- HighlightService.details = row;
- HighlightService.details.indexName = indexName;
- HighlightService.details.shardID = shardID;
- HighlightService.details.shardNumber = shardNumber;
- HighlightService.details.highlightedRow = row.id;
- };
-
- $scope.getHighlightedRow = () => {
- if (HighlightService.details) {
- return HighlightService.details.highlightedRow;
- }
- return null;
- };
-
- $scope.toggle = id => {
- // If the branch is open and toggled close, we need to
- // also close the children
- if ($scope.visible[id].visible === true) {
- closeNode($scope.visible, id);
- } else {
- // Otherwise just toggle on
- $scope.visible[id].visible = true;
- }
- };
-
- function render(data) {
- if (data.length === 0) {
- return;
- }
-
- $scope.visible = {};
- let indices = {};
-
- for (const shard of data) {
- initShardTargets(shard);
-
- if ($scope.target === 'searches') {
- shard.time[$scope.target] = collectSearchTimes(shard);
- } else if ($scope.target === 'aggregations') {
- shard.time[$scope.target] = collectAggTimes(shard);
- }
- if (!indices[shard.id[1]]) {
- indices[shard.id[1]] = {
- shards: [],
- time: {
- searches: 0,
- aggregations: 0
- },
- name: shard.id[1]
- };
- }
- indices[shard.id[1]].shards.push(shard);
- indices[shard.id[1]].time[$scope.target] += shard.time[$scope.target];
- }
- data = null;
- const finalIndices = normalizeIndices(indices, $scope.indexVisibility, $scope.target);
- indices = null;
-
- $scope.profileResponse = finalIndices;
- }
-
- function collectSearchTimes(shard) {
- if (shard.searches == null) {
- return 0;
- }
- shard.rewrite_time = 0;
-
- let shardTime = 0;
- for (const search of shard.searches) {
- shard.rewrite_time += search.rewrite_time;
- const totalTime = calcTimes(search.query);
- shardTime += totalTime;
- normalizeTimes(search.query, totalTime, 0);
-
- const flat = [];
- flattenResults(search.query, flat, 0, $scope.visible);
- search.flat = flat;
- search.query = null;
- }
- return shardTime;
- }
-
- function collectAggTimes(shard) {
- if (shard.aggregations == null) {
- return 0;
- }
- let shardTime = 0;
- for (const agg of shard.aggregations) {
- const totalTime = calcTimes([agg]);
- shardTime += totalTime;
- }
- for (const agg of shard.aggregations) {
- normalizeTimes([agg], shardTime, 0);
-
- const flat = [];
- flattenResults([agg], flat, 0, $scope.visible);
- agg.flat = flat;
- }
- return shardTime;
- }
-
- // TODO the addition of aggregation profiling made the mutability of
- // `shards` a liability. Previously we set things directly on the shards
- // tree because it was the only source of data. Now we have agg data,
- // so final, accumulated stats need to be saved on a per-target basis
- //
- // In the future, we should really remove this setup and create two immutable
- // result sets that are generated from a single (also immutable) input set of
- // `shards` data
- //
- // Particularly important if/when we add a third target
- function initShardTargets(shard) {
- if (!shard.time) {
- shard.time = {
- searches: 0,
- aggregations: 0
- };
- }
-
- if (!shard.color) {
- shard.color = {
- searches: 0,
- aggregations: 0
- };
- }
-
- if (!shard.relative) {
- shard.relative = {
- searches: 0,
- aggregations: 0
- };
- }
- }
-
- $scope.$watch('data', render);
-
- }
- };
-});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/util.js b/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/util.js
deleted file mode 100644
index 6190d299dcf10..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/util.js
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import uuid from 'uuid';
-import tinycolor from 'tinycolor2';
-import _ from 'lodash';
-
-const comparator = (v1, v2) => {
- if (v1 < v2) {
- return 1;
- }
- return (v1 > v2) ? -1 : 0;
-};
-
-function getToolTip(key) {
- switch (key) {
- case 'build_scorer':
- return 'The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc.';
- case 'create_weight':
- return 'The time taken to create the Weight object, which holds temporary information during scoring.';
- case 'next_doc':
- return 'The time taken to advance the iterator to the next matching document.';
- case 'score':
- return 'The time taken in actually scoring the document against the query.';
- case 'match':
- return 'The time taken to execute a secondary, more precise scoring phase (used by phrase queries).';
- case 'advance':
- return 'The time taken to advance the iterator to the next document.';
- default:
- return '';
- }
-}
-
-export function timeInMilliseconds(data) {
- if (data.time_in_nanos) {
- return data.time_in_nanos / 1000000;
- }
-
- if (typeof data.time === 'string') {
- return data.time.replace('ms', '');
- }
-
- return data.time;
-}
-
-export function calcTimes(data, parentId) {
- if (data == null) {
- return;
- }
-
- let totalTime = 0;
- //First pass to collect total
- for (const child of data) {
- totalTime += timeInMilliseconds(child);
-
- child.id = uuid.v4();
- child.parentId = parentId;
- child.childrenIds = [];
- child.breakdown = normalizeBreakdown(child.breakdown);
-
- let childrenTime = 0;
- if (child.children != null && child.children.length !== 0) {
- childrenTime = calcTimes(child.children, child.id);
- child.hasChildren = true;
-
- // Save the IDs of our children, has to be called after calcTimes recursion above
- for (const c of child.children) {
- child.childrenIds.push(c.id);
- }
- }
- child.selfTime = (timeInMilliseconds(child) - childrenTime);
- }
- return totalTime;
-}
-
-export function normalizeBreakdown(breakdown) {
- const final = [];
- const total = Object.keys(breakdown).reduce((partialTotal, currentKey) => {
- if (currentKey.indexOf('_count') === -1) {
- partialTotal += breakdown[currentKey];
- }
- return partialTotal;
- }, 0);
- Object.keys(breakdown).sort().forEach(key => {
- let relative = 0;
- if (key.indexOf('_count') === -1) {
- relative = ((breakdown[key] / total) * 100).toFixed(1);
- }
- final.push({
- key: key,
- time: breakdown[key],
- relative: relative,
- color: tinycolor.mix('#F5F5F5', '#FFAFAF', relative).toHexString(),
- tip: getToolTip(key)
- });
- });
-
- // Sort by time descending and then key ascending
- return final.sort((a, b) => {
- if (comparator(a.time, b.time) !== 0) {
- return comparator(a.time, b.time);
- }
-
- return -1 * comparator(a.key, b.key);
- });
-}
-
-export function normalizeTimes(data, totalTime, depth) {
- //Second pass to normalize
- for (const child of data) {
- child.timePercentage = ((timeInMilliseconds(child) / totalTime) * 100).toFixed(2);
- child.absoluteColor = tinycolor.mix('#F5F5F5', '#FFAFAF', child.timePercentage).toHexString();
- child.depth = depth;
-
- if (child.children != null && child.children.length !== 0) {
- normalizeTimes(child.children, totalTime, depth + 1);
- }
- }
-
- data.sort((a, b) => comparator(timeInMilliseconds(a), timeInMilliseconds(b)));
-}
-
-export function normalizeIndices(indices, visibility, target) {
- // Sort the shards per-index
- let sortQueryComponents;
- if (target === 'searches') {
- sortQueryComponents = (a, b) => {
- const aTime = _.sum(a.searches, (search) => {
- return search.flat[0].time;
- });
- const bTime = _.sum(b.searches, (search) => {
- return search.flat[0].time;
- });
-
- return comparator(aTime, bTime);
- };
- } else if (target === 'aggregations') {
- sortQueryComponents = (a, b) => {
- const aTime = _.sum(a.aggregations, (agg) => {
- return agg.flat[0].time;
- });
- const bTime = _.sum(b.aggregations, (agg) => {
- return agg.flat[0].time;
- });
-
- return comparator(aTime, bTime);
- };
- }
- const sortedIndices = [];
- for (const [key, index] of Object.entries(indices)) {
- index.shards.sort(sortQueryComponents);
- for (const shard of index.shards) {
- shard.relative[target] = ((shard.time[target] / index.time[target]) * 100).toFixed(2);
- shard.color[target] = tinycolor.mix('#F5F5F5', '#FFAFAF', shard.relative[target]).toHexString();
- }
- sortedIndices.push(index);
- visibility[key] = false;
- }
-
- // And now sort the indices themselves
- sortedIndices.sort((a, b) => comparator(a.time, b.time));
- return sortedIndices;
-}
-
-export function flattenResults(data, accumulator, depth, visibleMap) {
- if (data == null) {
- return;
- }
-
- for (const child of data) {
-
- // For bwc of older profile responses
- if (!child.description) {
- child.description = child.lucene;
- child.lucene = null;
-
- child.type = child.query_type;
- child.query_type = null;
- }
- accumulator.push({
- id: child.id,
- parentId: child.parentId,
- childrenIds: child.childrenIds,
- lucene: child.description,
- time: timeInMilliseconds(child),
- selfTime: child.selfTime,
- timePercentage: child.timePercentage,
- query_type: child.type.split('.').pop(),
- absoluteColor: child.absoluteColor,
- depth: depth,
- hasChildren: child.hasChildren,
- breakdown: child.breakdown
- });
-
- visibleMap[child.id] = {
- visible: child.timePercentage > 20,
- children: child.children
- };
-
- if (child.children != null && child.children.length !== 0) {
- flattenResults(child.children, accumulator, depth + 1, visibleMap);
- }
- }
-}
-
-export function closeNode(visibleMap, id) {
- visibleMap[id].visible = false;
-
- if (visibleMap[id].children == null || visibleMap[id].children.length === 0) {
- return;
- }
-
- for (const child of visibleMap[id].children) {
- closeNode(visibleMap, child.id);
- }
-}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/legacy.ts b/x-pack/legacy/plugins/searchprofiler/public/legacy.ts
new file mode 100644
index 0000000000000..61dabe8ac7b05
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/legacy.ts
@@ -0,0 +1,65 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+/* eslint-disable @kbn/eslint/no-restricted-paths */
+import { npSetup } from 'ui/new_platform';
+import { I18nContext } from 'ui/i18n';
+import uiRoutes from 'ui/routes';
+import 'ui/capabilities/route_setup';
+// @ts-ignore
+import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
+// @ts-ignore
+import { formatAngularHttpError } from 'ui/notify/lib';
+import 'ui/autoload/all';
+/* eslint-enable @kbn/eslint/no-restricted-paths */
+
+import { ApplicationSetup } from 'src/core/public';
+import { plugin } from './np_ready';
+
+const pluginInstance = plugin({} as any);
+
+const template = `
+
+ `;
+
+uiRoutes.when('/dev_tools/searchprofiler', {
+ template,
+ requireUICapability: 'dev_tools.show',
+ controller: $scope => {
+ $scope.startReactApp = () => {
+ const el = document.querySelector('#searchProfilerAppRoot');
+ if (!el) {
+ const errorMessage = 'Could not mount Searchprofiler App!';
+ npSetup.core.fatalErrors.add(errorMessage);
+ throw new Error(errorMessage);
+ }
+
+ const coreApplicationSetupShim: ApplicationSetup = {
+ register(app: any) {
+ const unmount = app.mount();
+ $scope.$on('$destroy', () => unmount());
+ },
+ registerMountContext: {} as any,
+ };
+
+ pluginInstance.setup(
+ {
+ ...npSetup.core,
+ application: coreApplicationSetupShim,
+ },
+ {
+ __LEGACY: {
+ I18nContext,
+ licenseEnabled: xpackInfo.get('features.searchprofiler.enableAppLink'),
+ notifications: npSetup.core.notifications.toasts,
+ formatAngularHttpError,
+ el,
+ },
+ }
+ );
+ };
+ },
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/boot.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/boot.tsx
new file mode 100644
index 0000000000000..fa02124f8a245
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/boot.tsx
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { render, unmountComponentAtNode } from 'react-dom';
+import React from 'react';
+import { HttpStart as Http, ToastsSetup } from 'src/core/public';
+import { App } from '.';
+
+export interface Dependencies {
+ el: HTMLElement;
+ http: Http;
+ licenseEnabled: boolean;
+ I18nContext: any;
+ notifications: ToastsSetup;
+ formatAngularHttpError: any;
+}
+
+export type AppDependencies = Omit;
+
+export function boot(deps: Dependencies): () => void {
+ const { el, ...rest } = deps;
+ render( , deps.el);
+ return () => unmountComponentAtNode(deps.el);
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.test.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.test.tsx
new file mode 100644
index 0000000000000..cf8052cbf3580
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.test.tsx
@@ -0,0 +1,63 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { registerTestBed } from '../../../../../../../../test_utils';
+import { HighlightDetailsFlyout, Props } from '.';
+
+describe('Highlight Details Flyout', () => {
+ it('renders', async () => {
+ const props: Props = {
+ onClose: () => {},
+ shard: {
+ aggregations: [],
+ id: ['test', 'test', 'test'],
+ searches: [],
+ color: '#fff',
+ time: 123,
+ relative: 100,
+ },
+ operation: {
+ parent: null,
+ breakdown: [
+ {
+ color: 'test',
+ key: 'test',
+ relative: 100,
+ tip: 'test',
+ time: 100,
+ },
+ {
+ color: 'test',
+ key: 'test',
+ relative: 100,
+ tip: 'test',
+ time: 100,
+ },
+ {
+ color: 'test',
+ key: 'test',
+ relative: 100,
+ tip: 'test',
+ time: 100,
+ },
+ ],
+ lucene: 'test',
+ query_type: 'test',
+ selfTime: 100,
+ time: 100,
+ children: [],
+ timePercentage: 100,
+ hasChildren: false,
+ visible: true,
+ absoluteColor: '123',
+ },
+ indexName: 'test',
+ };
+
+ const init = registerTestBed(HighlightDetailsFlyout);
+ await init(props);
+ });
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.tsx
new file mode 100644
index 0000000000000..6ba39d15b8341
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.tsx
@@ -0,0 +1,124 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import {
+ EuiFlyout,
+ EuiFlyoutHeader,
+ EuiFlyoutBody,
+ EuiIconTip,
+ EuiText,
+ EuiCodeBlock,
+} from '@elastic/eui';
+
+import { msToPretty } from '../../utils';
+import { HighlightDetailsTable } from './highlight_details_table';
+import { Operation, Shard } from '../../types';
+
+export interface Props {
+ operation: Operation;
+ shard: Shard;
+ indexName: string;
+ onClose: () => void;
+}
+
+const FlyoutEntry = ({
+ title,
+ body,
+}: {
+ title: string | JSX.Element;
+ body: string | JSX.Element;
+}) => (
+ <>
+ {title}
+ {body}
+ >
+);
+
+export const HighlightDetailsFlyout = ({ indexName, operation, shard, onClose }: Props) => {
+ return (
+ onClose()}>
+
+ {indexName}
+
+ [{/* shard id */ shard.id[0]}][{/* shard number */ shard.id[2]}]
+
+
+
+
+
+ {/* Type Entry */}
+
+ {/* Description Entry */}
+ {operation.lucene!}}
+ />
+ {/* Total Time Entry */}
+
+ {i18n.translate('xpack.searchProfiler.highlightDetails.totalTimeTitle', {
+ defaultMessage: 'Total time',
+ })}{' '}
+
+ >
+ }
+ body={msToPretty(operation.time, 3)}
+ />
+ {/* Self Time Entry */}
+
+ {i18n.translate('xpack.searchProfiler.highlightDetails.selfTimeTitle', {
+ defaultMessage: 'Self time',
+ })}{' '}
+
+ >
+ }
+ body={msToPretty(operation.selfTime || 0, 3)}
+ />
+ {/* Breakdown Table Entry */}
+ }
+ />
+
+
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_table.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_table.tsx
new file mode 100644
index 0000000000000..4bfa7365de1ef
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_table.tsx
@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { EuiBasicTable, EuiToolTip, EuiBadge } from '@elastic/eui';
+
+import { BreakdownItem } from '../../types';
+import { nsToPretty } from '../../utils';
+import { PercentageBadge } from '../percentage_badge';
+
+interface Props {
+ breakdown: BreakdownItem[];
+}
+
+export const HighlightDetailsTable = ({ breakdown }: Props) => {
+ const columns = [
+ {
+ name: 'Description',
+ render: (item: BreakdownItem) => (
+
+ {item.key}
+
+ ),
+ },
+ {
+ name: 'Time',
+ render: (item: BreakdownItem) => (
+
+ {nsToPretty(item.time, 1)}
+
+ ),
+ },
+ {
+ name: 'Percentage',
+ render: (item: BreakdownItem) => (
+
+ ),
+ },
+ ];
+
+ return ;
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/index.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/index.ts
similarity index 67%
rename from x-pack/legacy/plugins/searchprofiler/public/directives/index.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/index.ts
index 4bd4146a1a0fe..36ae010fabfa4 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/index.js
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/index.ts
@@ -4,5 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import 'plugins/searchprofiler/directives/profile_tree';
-import 'plugins/searchprofiler/directives/highlight_details';
+export { HighlightDetailsFlyout, Props } from './highlight_details_flyout';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/index.ts
new file mode 100644
index 0000000000000..db1fea0033db5
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/index.ts
@@ -0,0 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { SearchProfilerTabs } from './searchprofiler_tabs';
+export { LicenseWarningNotice } from './license_warning_notice';
+export { ProfileTree, OnHighlightChangeArgs } from './profile_tree';
+export { HighlightDetailsFlyout } from './highlight_details_flyout';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.test.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.test.ts
new file mode 100644
index 0000000000000..ebe7a00737868
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.test.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { registerTestBed } from '../../../../../../../test_utils';
+
+import { LicenseWarningNotice } from './license_warning_notice';
+
+describe('License Error Notice', () => {
+ it('renders', async () => {
+ const init = registerTestBed(LicenseWarningNotice);
+ await init({});
+ });
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.tsx
new file mode 100644
index 0000000000000..da9991529e7d4
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.tsx
@@ -0,0 +1,76 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { EuiCallOut, EuiText, EuiLink, EuiCode } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+export const LicenseWarningNotice = () => {
+ const registerLicenseLinkLabel = i18n.translate('xpack.searchProfiler.registerLicenseLinkLabel', {
+ defaultMessage: 'register a license',
+ });
+
+ const trialLicense = i18n.translate('xpack.searchProfiler.trialLicenseTitle', {
+ defaultMessage: 'Trial',
+ });
+
+ const basicLicense = i18n.translate('xpack.searchProfiler.basicLicenseTitle', {
+ defaultMessage: 'Basic',
+ });
+
+ const goldLicense = i18n.translate('xpack.searchProfiler.goldLicenseTitle', {
+ defaultMessage: 'Gold',
+ });
+
+ const platinumLicense = i18n.translate('xpack.searchProfiler.platinumLicenseTitle', {
+ defaultMessage: 'Platinum',
+ });
+
+ return (
+
+
+
+
+
+ {trialLicense} , {basicLicense} ,{' '}
+ {goldLicense}
+ >
+ ),
+ platinumLicenseType: {platinumLicense} ,
+ }}
+ />
+
+
+
+ {registerLicenseLinkLabel}
+
+ ),
+ }}
+ />
+
+
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/percentage_badge.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/percentage_badge.tsx
new file mode 100644
index 0000000000000..4b53b2e3c18c5
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/percentage_badge.tsx
@@ -0,0 +1,37 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { EuiBadge } from '@elastic/eui';
+import classNames from 'classnames';
+
+interface Props {
+ timePercentage: number;
+ label: string;
+ valueType?: 'percent' | 'time';
+}
+
+/**
+ * This component has IE specific provision for rendering the percentage portion of the badge correctly.
+ *
+ * This component uses CSS vars injected against the DOM element and resolves this in CSS to calculate
+ * how far the percent bar should be drawn.
+ */
+export const PercentageBadge = ({ timePercentage, label, valueType = 'percent' }: Props) => {
+ return (
+
+
+ {label}
+
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/breakdown.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/breakdown.ts
new file mode 100644
index 0000000000000..a65af9a7a3ff3
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/breakdown.ts
@@ -0,0 +1,68 @@
+export const breakdown = {
+ advance: 0,
+ advance_count: 0,
+ build_scorer: 6273,
+ build_scorer_count: 2,
+ create_weight: 1852,
+ create_weight_count: 1,
+ match: 0,
+ match_count: 0,
+ next_doc: 2593093,
+ next_doc_count: 27958,
+ score: 2525502,
+ score_count: 27948,
+};
+
+export const normalized = [
+ {
+ key: 'next_doc',
+ time: 2593093,
+ relative: '50.6',
+ color: '#fad2d2',
+ tip: 'The time taken to advance the iterator to the next matching document.',
+ },
+ {
+ key: 'score',
+ time: 2525502,
+ relative: '49.3',
+ color: '#fad2d2',
+ tip: 'The time taken in actually scoring the document against the query.',
+ },
+ { key: 'next_doc_count', time: 27958, relative: 0, color: '#f5f5f5', tip: '' },
+ { key: 'score_count', time: 27948, relative: 0, color: '#f5f5f5', tip: '' },
+ {
+ key: 'build_scorer',
+ time: 6273,
+ relative: '0.1',
+ color: '#f5f5f5',
+ tip:
+ 'The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc.',
+ },
+ {
+ key: 'create_weight',
+ time: 1852,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip:
+ 'The time taken to create the Weight object, which holds temporary information during scoring.',
+ },
+ { key: 'build_scorer_count', time: 2, relative: 0, color: '#f5f5f5', tip: '' },
+ { key: 'create_weight_count', time: 1, relative: 0, color: '#f5f5f5', tip: '' },
+ {
+ key: 'advance',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip: 'The time taken to advance the iterator to the next document.',
+ },
+ { key: 'advance_count', time: 0, relative: 0, color: '#f5f5f5', tip: '' },
+ {
+ key: 'match',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip:
+ 'The time taken to execute a secondary, more precise scoring phase (used by phrase queries).',
+ },
+ { key: 'match_count', time: 0, relative: 0, color: '#f5f5f5', tip: '' },
+];
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_indices.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_indices.ts
new file mode 100644
index 0000000000000..bd8e44d82379b
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_indices.ts
@@ -0,0 +1,8 @@
+/*eslint-disable */
+export const inputIndices = JSON.parse(
+ '{"test":{"shards":[{"id":["F-R7QxH4S42fMnPfmFUKMQ","test","0"],"searches":[{"query":null,"rewrite_time":2656,"collector":[{"name":"MultiCollector","reason":"search_multi","time":"0.1815780000ms","children":[{"name":"SimpleTopScoreDocCollector","reason":"search_top_hits","time":"0.02393700000ms"},{"name":"ProfilingAggregator: [org.elasticsearch.search.profile.aggregation.ProfilingAggregator@43c8a536]","reason":"aggregation","time":"0.1140000000ms"}]}],"flat":[{"id":"af697413-f76b-458e-b265-f4930dbdee2a","childrenIds":[],"lucene":"name:george","time":0.219343,"selfTime":0.219343,"timePercentage":"100.00","query_type":"TermQuery","absoluteColor":"#ffafaf","depth":0,"breakdown":[{"key":"create_weight","time":160673,"relative":"73.3","color":"#fcc2c2","tip":"The time taken to create the Weight object, which holds temporary information during scoring."},{"key":"build_scorer","time":50157,"relative":"22.9","color":"#f7e5e5","tip":"The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc."},{"key":"score","time":5783,"relative":"2.6","color":"#f5f3f3","tip":"The time taken in actually scoring the document against the query."},{"key":"next_doc","time":2718,"relative":"1.2","color":"#f5f4f4","tip":"The time taken to advance the iterator to the next matching document."},{"key":"build_scorer_count","time":5,"relative":0,"color":"#f5f5f5","tip":""},{"key":"next_doc_count","time":4,"relative":0,"color":"#f5f5f5","tip":""},{"key":"score_count","time":2,"relative":0,"color":"#f5f5f5","tip":""},{"key":"create_weight_count","time":1,"relative":0,"color":"#f5f5f5","tip":""},{"key":"match","time":0,"relative":"0.0","color":"#f5f5f5","tip":"The time taken to execute a secondary, more precise scoring phase (used by phrase queries)."},{"key":"match_count","time":0,"relative":0,"color":"#f5f5f5","tip":""},{"key":"advance","time":0,"relative":"0.0","color":"#f5f5f5","tip":"The time taken to advance the iterator to the next document."},{"key":"advance_count","time":0,"relative":0,"color":"#f5f5f5","tip":""}]}]}],"aggregations":[{"type":"org.elasticsearch.search.aggregations.metrics.stats.StatsAggregator","description":"stats","time":"0.03053500000ms","breakdown":{"reduce":0,"build_aggregation":9447,"build_aggregation_count":1,"initialize":5589,"initialize_count":1,"reduce_count":0,"collect":15495,"collect_count":2}}],"time":0.219343,"color":0,"relative":0,"rewrite_time":2656}],"time":0.219343,"name":"test"}}'
+);
+
+export const normalizedIndices = JSON.parse(
+ '[{"shards":[{"id":["F-R7QxH4S42fMnPfmFUKMQ","test","0"],"searches":[{"query":null,"rewrite_time":2656,"collector":[{"name":"MultiCollector","reason":"search_multi","time":"0.1815780000ms","children":[{"name":"SimpleTopScoreDocCollector","reason":"search_top_hits","time":"0.02393700000ms"},{"name":"ProfilingAggregator: [org.elasticsearch.search.profile.aggregation.ProfilingAggregator@43c8a536]","reason":"aggregation","time":"0.1140000000ms"}]}],"flat":[{"id":"af697413-f76b-458e-b265-f4930dbdee2a","childrenIds":[],"lucene":"name:george","time":0.219343,"selfTime":0.219343,"timePercentage":"100.00","query_type":"TermQuery","absoluteColor":"#ffafaf","depth":0,"breakdown":[{"key":"create_weight","time":160673,"relative":"73.3","color":"#fcc2c2","tip":"The time taken to create the Weight object, which holds temporary information during scoring."},{"key":"build_scorer","time":50157,"relative":"22.9","color":"#f7e5e5","tip":"The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc."},{"key":"score","time":5783,"relative":"2.6","color":"#f5f3f3","tip":"The time taken in actually scoring the document against the query."},{"key":"next_doc","time":2718,"relative":"1.2","color":"#f5f4f4","tip":"The time taken to advance the iterator to the next matching document."},{"key":"build_scorer_count","time":5,"relative":0,"color":"#f5f5f5","tip":""},{"key":"next_doc_count","time":4,"relative":0,"color":"#f5f5f5","tip":""},{"key":"score_count","time":2,"relative":0,"color":"#f5f5f5","tip":""},{"key":"create_weight_count","time":1,"relative":0,"color":"#f5f5f5","tip":""},{"key":"match","time":0,"relative":"0.0","color":"#f5f5f5","tip":"The time taken to execute a secondary, more precise scoring phase (used by phrase queries)."},{"key":"match_count","time":0,"relative":0,"color":"#f5f5f5","tip":""},{"key":"advance","time":0,"relative":"0.0","color":"#f5f5f5","tip":"The time taken to advance the iterator to the next document."},{"key":"advance_count","time":0,"relative":0,"color":"#f5f5f5","tip":""}]}]}],"aggregations":[{"type":"org.elasticsearch.search.aggregations.metrics.stats.StatsAggregator","description":"stats","time":"0.03053500000ms","breakdown":{"reduce":0,"build_aggregation":9447,"build_aggregation_count":1,"initialize":5589,"initialize_count":1,"reduce_count":0,"collect":15495,"collect_count":2}}],"time":0.219343,"color":"#ffafaf","relative":"100.00","rewrite_time":2656}],"time":0.219343,"name":"test"}]'
+);
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/normalize_times.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_times.ts
similarity index 100%
rename from x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/fixtures/normalize_times.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_times.ts
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/processed_search_response.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/processed_search_response.ts
new file mode 100644
index 0000000000000..ede36ba2b0169
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/processed_search_response.ts
@@ -0,0 +1,344 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { produce } from 'immer';
+
+const shard1 = {
+ id: ['L22w_FX2SbqlQYOP5QrYDg', '.kibana_1', '0'],
+ searches: [],
+ aggregations: [],
+ time: 0.058419,
+ color: '#ffafaf',
+ relative: '100.00',
+ rewrite_time: 14670,
+};
+
+const searchRoot = {
+ query: null,
+ rewrite_time: 14670,
+ collector: [
+ {
+ name: 'CancellableCollector',
+ reason: 'search_cancelled',
+ time_in_nanos: 14706,
+ children: [
+ {
+ name: 'SimpleTopScoreDocCollector',
+ reason: 'search_top_hits',
+ time_in_nanos: 7851,
+ },
+ ],
+ },
+ ],
+ treeRoot: null,
+};
+
+const search1 = {
+ type: 'ConstantScoreQuery',
+ description: 'ConstantScore(DocValuesFieldExistsQuery [field=_primary_term])',
+ time_in_nanos: 58419,
+ breakdown: [
+ {
+ key: 'build_scorer',
+ time: 40061,
+ relative: '68.7',
+ color: '#fcc5c5',
+ tip:
+ 'The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc.',
+ },
+ {
+ key: 'create_weight',
+ time: 8238,
+ relative: '14.1',
+ color: '#f6ebeb',
+ tip:
+ 'The time taken to create the Weight object, which holds temporary information during scoring.',
+ },
+ {
+ key: 'next_doc',
+ time: 5767,
+ relative: '9.9',
+ color: '#f6eeee',
+ tip: 'The time taken to advance the iterator to the next matching document.',
+ },
+ {
+ key: 'advance',
+ time: 2849,
+ relative: '4.9',
+ color: '#f5f2f2',
+ tip: 'The time taken to advance the iterator to the next document.',
+ },
+ {
+ key: 'score',
+ time: 1431,
+ relative: '2.5',
+ color: '#f5f3f3',
+ tip: 'The time taken in actually scoring the document against the query.',
+ },
+ {
+ key: 'next_doc_count',
+ time: 24,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'score_count',
+ time: 24,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'build_scorer_count',
+ time: 16,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'advance_count',
+ time: 8,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'create_weight_count',
+ time: 1,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'compute_max_score',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'compute_max_score_count',
+ time: 0,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'match',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip:
+ 'The time taken to execute a secondary, more precise scoring phase (used by phrase queries).',
+ },
+ {
+ key: 'match_count',
+ time: 0,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'set_min_competitive_score',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'set_min_competitive_score_count',
+ time: 0,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'shallow_advance',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'shallow_advance_count',
+ time: 0,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ ],
+ children: [
+ /* See search1Child */
+ ],
+ hasChildren: true,
+ selfTime: 0.028784999999999998,
+ timePercentage: '100.00',
+ absoluteColor: '#ffafaf',
+ depth: 0,
+ parent: null,
+ time: 0.058419,
+ lucene: 'ConstantScore(DocValuesFieldExistsQuery [field=_primary_term])',
+ query_type: 'ConstantScoreQuery',
+ visible: true,
+};
+
+const search1Child = {
+ type: 'DocValuesFieldExistsQuery',
+ description: 'DocValuesFieldExistsQuery [field=_primary_term]',
+ time_in_nanos: 29634,
+ breakdown: [
+ {
+ key: 'build_scorer',
+ time: 24059,
+ relative: '81.3',
+ color: '#fdbcbc',
+ tip:
+ 'The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc.',
+ },
+ {
+ key: 'next_doc',
+ time: 2434,
+ relative: '8.2',
+ color: '#f6efef',
+ tip: 'The time taken to advance the iterator to the next matching document.',
+ },
+ {
+ key: 'create_weight',
+ time: 1586,
+ relative: '5.4',
+ color: '#f6f1f1',
+ tip:
+ 'The time taken to create the Weight object, which holds temporary information during scoring.',
+ },
+ {
+ key: 'advance',
+ time: 1506,
+ relative: '5.1',
+ color: '#f6f1f1',
+ tip: 'The time taken to advance the iterator to the next document.',
+ },
+ {
+ key: 'next_doc_count',
+ time: 24,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'build_scorer_count',
+ time: 16,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'advance_count',
+ time: 8,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'create_weight_count',
+ time: 1,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'compute_max_score',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'compute_max_score_count',
+ time: 0,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'match',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip:
+ 'The time taken to execute a secondary, more precise scoring phase (used by phrase queries).',
+ },
+ {
+ key: 'match_count',
+ time: 0,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'score',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip: 'The time taken in actually scoring the document against the query.',
+ },
+ {
+ key: 'score_count',
+ time: 0,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'set_min_competitive_score',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'set_min_competitive_score_count',
+ time: 0,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'shallow_advance',
+ time: 0,
+ relative: '0.0',
+ color: '#f5f5f5',
+ tip: '',
+ },
+ {
+ key: 'shallow_advance_count',
+ time: 0,
+ relative: 0,
+ color: '#f5f5f5',
+ tip: '',
+ },
+ ],
+ selfTime: 0.029634,
+ timePercentage: '50.73',
+ absoluteColor: '#fad1d1',
+ depth: 1,
+ parent: search1,
+ time: 0.029634,
+ lucene: 'DocValuesFieldExistsQuery [field=_primary_term]',
+ query_type: 'DocValuesFieldExistsQuery',
+ visible: true,
+};
+(search1.children[0] as any) = search1Child;
+(searchRoot.treeRoot as any) = search1;
+(shard1.searches[0] as any) = searchRoot;
+
+export const processedResponseWithFirstShard = produce(null, () => [
+ {
+ shards: [shard1],
+ time: 0.058419,
+ name: '.kibana_1',
+ visible: false,
+ },
+]);
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/search_response.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/search_response.ts
new file mode 100644
index 0000000000000..b4483cc0fc58e
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/search_response.ts
@@ -0,0 +1,308 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export const searchResponse: any = [
+ {
+ id: '[L22w_FX2SbqlQYOP5QrYDg] [.apm-agent-configuration] [0]',
+ searches: [
+ {
+ query: [
+ {
+ type: 'MatchAllDocsQuery',
+ description: '*:*',
+ time_in_nanos: 1971,
+ breakdown: {
+ set_min_competitive_score_count: 0,
+ match_count: 0,
+ shallow_advance_count: 0,
+ set_min_competitive_score: 0,
+ next_doc: 0,
+ match: 0,
+ next_doc_count: 0,
+ score_count: 0,
+ compute_max_score_count: 0,
+ compute_max_score: 0,
+ advance: 0,
+ advance_count: 0,
+ score: 0,
+ build_scorer_count: 0,
+ create_weight: 1970,
+ shallow_advance: 0,
+ create_weight_count: 1,
+ build_scorer: 0,
+ },
+ },
+ ],
+ rewrite_time: 908,
+ collector: [
+ {
+ name: 'CancellableCollector',
+ reason: 'search_cancelled',
+ time_in_nanos: 1176,
+ children: [
+ { name: 'SimpleTopScoreDocCollector', reason: 'search_top_hits', time_in_nanos: 517 },
+ ],
+ },
+ ],
+ },
+ ],
+ aggregations: [],
+ },
+ {
+ id: '[L22w_FX2SbqlQYOP5QrYDg] [.kibana_1] [0]',
+ searches: [
+ {
+ query: [
+ {
+ type: 'ConstantScoreQuery',
+ description: 'ConstantScore(DocValuesFieldExistsQuery [field=_primary_term])',
+ time_in_nanos: 58419,
+ breakdown: {
+ set_min_competitive_score_count: 0,
+ match_count: 0,
+ shallow_advance_count: 0,
+ set_min_competitive_score: 0,
+ next_doc: 5767,
+ match: 0,
+ next_doc_count: 24,
+ score_count: 24,
+ compute_max_score_count: 0,
+ compute_max_score: 0,
+ advance: 2849,
+ advance_count: 8,
+ score: 1431,
+ build_scorer_count: 16,
+ create_weight: 8238,
+ shallow_advance: 0,
+ create_weight_count: 1,
+ build_scorer: 40061,
+ },
+ children: [
+ {
+ type: 'DocValuesFieldExistsQuery',
+ description: 'DocValuesFieldExistsQuery [field=_primary_term]',
+ time_in_nanos: 29634,
+ breakdown: {
+ set_min_competitive_score_count: 0,
+ match_count: 0,
+ shallow_advance_count: 0,
+ set_min_competitive_score: 0,
+ next_doc: 2434,
+ match: 0,
+ next_doc_count: 24,
+ score_count: 0,
+ compute_max_score_count: 0,
+ compute_max_score: 0,
+ advance: 1506,
+ advance_count: 8,
+ score: 0,
+ build_scorer_count: 16,
+ create_weight: 1586,
+ shallow_advance: 0,
+ create_weight_count: 1,
+ build_scorer: 24059,
+ },
+ },
+ ],
+ },
+ ],
+ rewrite_time: 14670,
+ collector: [
+ {
+ name: 'CancellableCollector',
+ reason: 'search_cancelled',
+ time_in_nanos: 14706,
+ children: [
+ {
+ name: 'SimpleTopScoreDocCollector',
+ reason: 'search_top_hits',
+ time_in_nanos: 7851,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ aggregations: [],
+ },
+ {
+ id: '[L22w_FX2SbqlQYOP5QrYDg] [.kibana_task_manager_1] [0]',
+ searches: [
+ {
+ query: [
+ {
+ type: 'ConstantScoreQuery',
+ description: 'ConstantScore(DocValuesFieldExistsQuery [field=_primary_term])',
+ time_in_nanos: 30013,
+ breakdown: {
+ set_min_competitive_score_count: 0,
+ match_count: 0,
+ shallow_advance_count: 0,
+ set_min_competitive_score: 0,
+ next_doc: 1497,
+ match: 0,
+ next_doc_count: 5,
+ score_count: 3,
+ compute_max_score_count: 0,
+ compute_max_score: 0,
+ advance: 1058,
+ advance_count: 3,
+ score: 309,
+ build_scorer_count: 6,
+ create_weight: 6727,
+ shallow_advance: 0,
+ create_weight_count: 1,
+ build_scorer: 20404,
+ },
+ children: [
+ {
+ type: 'DocValuesFieldExistsQuery',
+ description: 'DocValuesFieldExistsQuery [field=_primary_term]',
+ time_in_nanos: 19795,
+ breakdown: {
+ set_min_competitive_score_count: 0,
+ match_count: 0,
+ shallow_advance_count: 0,
+ set_min_competitive_score: 0,
+ next_doc: 600,
+ match: 0,
+ next_doc_count: 5,
+ score_count: 0,
+ compute_max_score_count: 0,
+ compute_max_score: 0,
+ advance: 378,
+ advance_count: 3,
+ score: 0,
+ build_scorer_count: 6,
+ create_weight: 1121,
+ shallow_advance: 0,
+ create_weight_count: 1,
+ build_scorer: 17681,
+ },
+ },
+ ],
+ },
+ ],
+ rewrite_time: 10713,
+ collector: [
+ {
+ name: 'CancellableCollector',
+ reason: 'search_cancelled',
+ time_in_nanos: 4924,
+ children: [
+ {
+ name: 'SimpleTopScoreDocCollector',
+ reason: 'search_top_hits',
+ time_in_nanos: 2223,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ aggregations: [],
+ },
+ {
+ id: '[L22w_FX2SbqlQYOP5QrYDg] [.security-7] [0]',
+ searches: [
+ {
+ query: [
+ {
+ type: 'MatchAllDocsQuery',
+ description: '*:*',
+ time_in_nanos: 13254,
+ breakdown: {
+ set_min_competitive_score_count: 6,
+ match_count: 0,
+ shallow_advance_count: 0,
+ set_min_competitive_score: 3016,
+ next_doc: 1442,
+ match: 0,
+ next_doc_count: 10,
+ score_count: 10,
+ compute_max_score_count: 0,
+ compute_max_score: 0,
+ advance: 1313,
+ advance_count: 6,
+ score: 1169,
+ build_scorer_count: 12,
+ create_weight: 1132,
+ shallow_advance: 0,
+ create_weight_count: 1,
+ build_scorer: 5137,
+ },
+ },
+ ],
+ rewrite_time: 755,
+ collector: [
+ {
+ name: 'CancellableCollector',
+ reason: 'search_cancelled',
+ time_in_nanos: 18172,
+ children: [
+ {
+ name: 'SimpleTopScoreDocCollector',
+ reason: 'search_top_hits',
+ time_in_nanos: 12507,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ aggregations: [],
+ },
+ {
+ id: '[L22w_FX2SbqlQYOP5QrYDg] [kibana_sample_data_logs] [0]',
+ searches: [
+ {
+ query: [
+ {
+ type: 'MatchAllDocsQuery',
+ description: '*:*',
+ time_in_nanos: 12764,
+ breakdown: {
+ set_min_competitive_score_count: 4,
+ match_count: 0,
+ shallow_advance_count: 0,
+ set_min_competitive_score: 2685,
+ next_doc: 1831,
+ match: 0,
+ next_doc_count: 10,
+ score_count: 10,
+ compute_max_score_count: 0,
+ compute_max_score: 0,
+ advance: 1621,
+ advance_count: 4,
+ score: 835,
+ build_scorer_count: 8,
+ create_weight: 972,
+ shallow_advance: 0,
+ create_weight_count: 1,
+ build_scorer: 4783,
+ },
+ },
+ ],
+ rewrite_time: 691,
+ collector: [
+ {
+ name: 'CancellableCollector',
+ reason: 'search_cancelled',
+ time_in_nanos: 17700,
+ children: [
+ {
+ name: 'SimpleTopScoreDocCollector',
+ reason: 'search_top_hits',
+ time_in_nanos: 12839,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ aggregations: [],
+ },
+];
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/init_data.test.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/init_data.test.ts
new file mode 100644
index 0000000000000..6cd19947a26bc
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/init_data.test.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { ShardSerialized } from '../../../types';
+import { initDataFor } from '../init_data';
+
+import { searchResponse } from './fixtures/search_response';
+import { processedResponseWithFirstShard } from './fixtures/processed_search_response';
+
+describe('ProfileTree init data', () => {
+ test('provides the expected result', () => {
+ const input: ShardSerialized[] = searchResponse as any;
+ const actual = initDataFor('searches')(input);
+
+ expect(actual[0].name).toEqual(processedResponseWithFirstShard[0].name);
+ const expectedFirstShard = processedResponseWithFirstShard[0].shards[0];
+ expect(actual[0].shards[0]).toEqual(expectedFirstShard);
+ });
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/profile_tree.test.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/profile_tree.test.tsx
new file mode 100644
index 0000000000000..ca95ac97e260a
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/profile_tree.test.tsx
@@ -0,0 +1,21 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { registerTestBed } from '../../../../../../../../../test_utils';
+import { searchResponse } from './fixtures/search_response';
+import { ProfileTree, Props } from '../profile_tree';
+
+describe('ProfileTree', () => {
+ it('renders', async () => {
+ const props: Props = {
+ onHighlight: () => {},
+ target: 'searches',
+ data: searchResponse,
+ };
+ const init = registerTestBed(ProfileTree);
+ await init(props);
+ });
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/unsafe_utils.test.ts
similarity index 52%
rename from x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/unsafe_utils.test.ts
index 6da9a452e5e3c..17c7051f09769 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/unsafe_utils.test.ts
@@ -5,21 +5,20 @@
*/
import expect from '@kbn/expect';
-import * as util from '../util.js';
-import { normalized, breakdown } from './fixtures/breakdown.js';
-import { inputTimes, normalizedTimes } from './fixtures/normalize_times.js';
-import { inputIndices, normalizedIndices } from './fixtures/normalize_indices.js';
-import { flatTimes } from './fixtures/flatten_times.js';
+import * as util from '../unsafe_utils';
+import { normalized, breakdown } from './fixtures/breakdown';
+import { inputTimes, normalizedTimes } from './fixtures/normalize_times';
+import { inputIndices, normalizedIndices } from './fixtures/normalize_indices';
-describe('normalizeBreakdown', function () {
- it('returns correct breakdown', function () {
+describe('normalizeBreakdown', function() {
+ it('returns correct breakdown', function() {
const result = util.normalizeBreakdown(breakdown);
expect(result).to.eql(normalized);
});
});
-describe('normalizeTimes', function () {
- it('returns correct normalization', function () {
+describe('normalizeTimes', function() {
+ it('returns correct normalization', function() {
const totalTime = 0.447365;
// Deep clone the object to preserve the original
@@ -31,21 +30,12 @@ describe('normalizeTimes', function () {
});
});
-describe('flattenResults', function () {
- it('returns correct flattening', function () {
- // Deep clone the object to preserve the original
- const input = JSON.parse(JSON.stringify(normalizedTimes));
- const flat = [];
- util.flattenResults(input, flat, 0, []);
- expect(JSON.parse(JSON.stringify(flat))).to.eql(flatTimes);
- });
-});
-
-describe('normalizeIndices', function () {
- it('returns correct ordering', function () {
+describe('normalizeIndices', function() {
+ it('returns correct ordering', function() {
// Deep clone the object to preserve the original
const input = JSON.parse(JSON.stringify(inputIndices));
- const result = util.normalizeIndices(input, [], 'searches');
+ util.normalizeIndices(input, 'searches');
+ const result = util.sortIndices(input);
expect(result).to.eql(normalizedIndices);
});
});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/utils.test.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/utils.test.ts
new file mode 100644
index 0000000000000..3a3d606434241
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/utils.test.ts
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { hasVisibleChild } from '../utils';
+
+describe('Profile Tree utils', () => {
+ describe('#hasVisibleChild', () => {
+ it('base case no children', () => {
+ const op: any = { children: [] };
+ expect(hasVisibleChild(op)).toBe(false);
+ });
+
+ it('base case with children', () => {
+ const op: any = { children: [{ visible: false }, { visible: false }, { visible: true }] };
+ expect(hasVisibleChild(op)).toBe(true);
+ });
+
+ it('is robust', () => {
+ const op: any = {};
+ expect(hasVisibleChild(op)).toBe(false);
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/highlight_context.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/highlight_context.tsx
new file mode 100644
index 0000000000000..f781d01352f85
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/highlight_context.tsx
@@ -0,0 +1,52 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useContext, createContext, useState } from 'react';
+import { Operation, Shard } from '../../types';
+
+const HighlightContext = createContext<{
+ selectedRow: string;
+ setStore: (args: OnHighlightChangeArgs & { id: string }) => void;
+}>(null as any);
+
+export interface OnHighlightChangeArgs {
+ indexName: string;
+ shard: Shard;
+ operation: Operation;
+}
+
+type OnHighlightChangeHandler = (data: OnHighlightChangeArgs) => void;
+
+export const HighlightContextProvider = ({
+ children,
+ onHighlight,
+}: {
+ children: React.ReactNode;
+ onHighlight: OnHighlightChangeHandler;
+}) => {
+ const [selectedRow, setSelectedRow] = useState('');
+ return (
+ {
+ onHighlight(onHighlightChangeArgs);
+ setSelectedRow(id);
+ },
+ }}
+ >
+ {children}
+
+ );
+};
+
+export const useHighlightContext = () => {
+ const ctx = useContext(HighlightContext);
+ if (ctx == null) {
+ throw new Error(`useHighlightContext must be called inside HighlightContext`);
+ }
+ return ctx;
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index.ts
new file mode 100644
index 0000000000000..78efd2cb6687f
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { ProfileTree } from './profile_tree';
+export { OnHighlightChangeArgs } from './highlight_context';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index_details.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index_details.tsx
new file mode 100644
index 0000000000000..20ea7c636ee74
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index_details.tsx
@@ -0,0 +1,56 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiText, EuiToolTip, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+
+import { msToPretty } from '../../utils';
+import { Index } from '../../types';
+
+export interface Props {
+ index: Index;
+}
+
+export const IndexDetails = ({ index }: Props) => {
+ const { time, name } = index;
+ return (
+
+ {/* Index Title group */}
+
+
+
+
+ {i18n.translate('xpack.searchProfiler.profileTree.indexTitle', {
+ defaultMessage: 'Index:',
+ })}
+
+ {' ' + name}
+
+
+
+ {/* Time details group */}
+
+
+
+
+ {i18n.translate('xpack.searchProfiler.profileTree.cumulativeTimeTitle', {
+ defaultMessage: 'Cumulative time:',
+ })}
+
+
+ {' ' + msToPretty(time, 3)}
+
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/init_data.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/init_data.ts
new file mode 100644
index 0000000000000..d7990b1204b21
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/init_data.ts
@@ -0,0 +1,114 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { produce } from 'immer';
+import { flow } from 'fp-ts/lib/function';
+import { Targets, Shard, ShardSerialized } from '../../types';
+import { calcTimes, normalizeTimes, initTree, normalizeIndices, sortIndices } from './unsafe_utils';
+import { IndexMap } from './types';
+
+/**
+ * Functions prefixed with "mutate" change values by reference. Be careful when using these!
+ *
+ * It's recommended to us immer's `produce` functions to ensure immutability.
+ */
+
+export function mutateAggsTimesTree(shard: Shard) {
+ if (shard.aggregations == null) {
+ shard.time = 0;
+ }
+ let shardTime = 0;
+ for (const agg of shard.aggregations!) {
+ const totalTime = calcTimes([agg]);
+ shardTime += totalTime;
+ }
+ for (const agg of shard.aggregations!) {
+ normalizeTimes([agg], shardTime, 0);
+ initTree([agg], 0);
+ }
+ shard.time = shardTime;
+}
+
+export function mutateSearchTimesTree(shard: Shard) {
+ if (shard.searches == null) {
+ shard.time = 0;
+ }
+ shard.rewrite_time = 0;
+
+ let shardTime = 0;
+ for (const search of shard.searches!) {
+ shard.rewrite_time += search.rewrite_time!;
+ const totalTime = calcTimes(search.query!);
+ shardTime += totalTime;
+ normalizeTimes(search.query!, totalTime, 0);
+ initTree(search.query!, 0);
+ search.treeRoot = search.query![0];
+ search.query = null as any;
+ }
+ shard.time = shardTime;
+}
+
+const initShards = (data: ShardSerialized[]) =>
+ produce(data, draft => {
+ return draft.map(s => {
+ const idMatch = s.id.match(/\[([^\]\[]*?)\]/g) || [];
+ const ids = idMatch.map(id => {
+ return id.replace('[', '').replace(']', '');
+ });
+ return {
+ ...s,
+ id: ids,
+ time: 0,
+ color: '',
+ relative: 0,
+ };
+ });
+ });
+
+export const calculateShardValues = (target: Targets) => (data: Shard[]) =>
+ produce(data, draft => {
+ for (const shard of draft) {
+ if (target === 'searches') {
+ mutateSearchTimesTree(shard);
+ } else if (target === 'aggregations') {
+ mutateAggsTimesTree(shard);
+ }
+ }
+ });
+
+export const initIndices = (data: Shard[]) =>
+ produce(data, doNotChange => {
+ const indices: IndexMap = {};
+
+ for (const shard of doNotChange) {
+ if (!indices[shard.id[1]]) {
+ indices[shard.id[1]] = {
+ shards: [],
+ time: 0,
+ name: shard.id[1],
+ visible: false,
+ };
+ }
+ indices[shard.id[1]].shards.push(shard);
+ indices[shard.id[1]].time += shard.time;
+ }
+
+ return indices;
+ });
+
+export const normalize = (target: Targets) => (data: IndexMap) =>
+ produce(data, draft => {
+ normalizeIndices(draft, target);
+ });
+
+export const initDataFor = (target: Targets) =>
+ flow(
+ initShards,
+ calculateShardValues(target),
+ initIndices,
+ normalize(target),
+ sortIndices
+ );
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/profile_tree.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/profile_tree.tsx
new file mode 100644
index 0000000000000..ea24abbdb56db
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/profile_tree.tsx
@@ -0,0 +1,64 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { memo } from 'react';
+import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
+
+import { IndexDetails } from './index_details';
+import { ShardDetails } from './shard_details';
+import { initDataFor } from './init_data';
+import { Targets, ShardSerialized } from '../../types';
+import { HighlightContextProvider, OnHighlightChangeArgs } from './highlight_context';
+
+export interface Props {
+ target: Targets;
+ data: ShardSerialized[] | null;
+ onHighlight: (args: OnHighlightChangeArgs) => void;
+}
+
+export const ProfileTree = memo(({ data, target, onHighlight }: Props) => {
+ if (!data || data.length === 0) {
+ return null;
+ }
+
+ const sortedIndices = initDataFor(target)(data);
+
+ return (
+
+
+ {sortedIndices.map(index => (
+
+
+
+
+
+
+
+ {index.shards.map(shard => (
+
+ ))}
+
+
+
+ ))}
+
+
+ );
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/templates/default_query.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/index.ts
similarity index 77%
rename from x-pack/legacy/plugins/searchprofiler/public/templates/default_query.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/index.ts
index afab7e808eb1a..ea9874d559b37 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/templates/default_query.js
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/index.ts
@@ -4,8 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export const defaultQuery = `{
- "query":{
- "match_all" : {}
- }
-}`;
+export { ShardDetails } from './shard_details';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details.tsx
new file mode 100644
index 0000000000000..eca2d1994f8c5
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details.tsx
@@ -0,0 +1,55 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useState } from 'react';
+import { EuiFlexGroup, EuiFlexItem, EuiText, EuiLink, EuiIcon } from '@elastic/eui';
+
+import { Index, Operation, Shard } from '../../../types';
+import { msToPretty } from '../../../utils';
+import { ShardDetailTree } from './shard_details_tree';
+import { PercentageBadge } from '../../percentage_badge';
+
+interface Props {
+ index: Index;
+ shard: Shard;
+ operations: Operation[];
+}
+
+export const ShardDetails = ({ index, shard, operations }: Props) => {
+ const { relative, time } = shard;
+
+ const [shardVisibility, setShardVisibility] = useState(false);
+
+ return (
+ <>
+
+
+ setShardVisibility(!shardVisibility)}
+ >
+ [{shard.id[0]}][
+ {shard.id[2]}]
+
+
+
+
+
+
+
+
+ {shardVisibility
+ ? operations.map((data, idx) => (
+
+ ))
+ : null}
+ >
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree.tsx
new file mode 100644
index 0000000000000..d3b0a1a5a6355
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree.tsx
@@ -0,0 +1,59 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiText, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import { ShardDetailsTreeNode } from './shard_details_tree_node';
+import { Index, Operation, Shard } from '../../../types';
+
+export interface Props {
+ data: Operation;
+ index: Index;
+ shard: Shard;
+}
+
+export const ShardDetailTree = ({ data, index, shard }: Props) => {
+ const renderOperations = (operation: Operation): JSX.Element => {
+ const nextOperation = operation.treeRoot || operation;
+ return ;
+ };
+
+ return (
+
+
+ {/* Setting grow to false here is important for IE11. Don't change without testing first! */}
+
+
+
+ {i18n.translate('xpack.searchProfiler.profileTree.header.typeTitle', {
+ defaultMessage: 'Type and description',
+ })}
+
+
+ {i18n.translate('xpack.searchProfiler.profileTree.header.selfTimeTitle', {
+ defaultMessage: 'Self time',
+ })}
+
+
+ {i18n.translate('xpack.searchProfiler.profileTree.header.totalTimeTitle', {
+ defaultMessage: 'Total time',
+ })}
+
+
+
+
+ {renderOperations(data)}
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree_node.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree_node.tsx
new file mode 100644
index 0000000000000..75da10f8aca2e
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree_node.tsx
@@ -0,0 +1,114 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useState } from 'react';
+import { EuiLink, EuiBadge, EuiCodeBlock, EuiIcon } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { hasVisibleChild } from '../utils';
+import { useHighlightTreeNode } from '../use_highlight_tree_node';
+import { msToPretty } from '../../../utils';
+
+import { PercentageBadge } from '../../percentage_badge';
+
+import { Index, Operation, Shard } from '../../../types';
+
+export interface Props {
+ index: Index;
+ shard: Shard;
+ operation: Operation;
+}
+
+const TAB_WIDTH_PX = 32;
+
+const limitString = (string: string, limit: number) =>
+ `${string.slice(0, limit)}${string.length > limit ? '...' : ''}`;
+
+/**
+ * This is a component that recursively iterates over data to render out a tree like
+ * structure in a flatly.
+ */
+export const ShardDetailsTreeNode = ({ operation, index, shard }: Props) => {
+ const [childrenVisible, setChildrenVisible] = useState(hasVisibleChild(operation));
+ const { highlight, isHighlighted, id } = useHighlightTreeNode();
+
+ const renderTimeRow = (op: Operation) => (
+
+
+ {op.hasChildren ? (
+ setChildrenVisible(!childrenVisible)}
+ >
+
+
+ {' ' + op.query_type}
+
+ ) : (
+ <>
+
+ {' ' + op.query_type}
+ >
+ )}
+
+ {/* Self Time Badge */}
+
+
+ {msToPretty(op.selfTime || 0, 1)}
+
+
+ {/* Total Time Badge */}
+
+
+ {msToPretty(op.time, 1)}
+
+
+ {/* Time percentage Badge */}
+
+
+ );
+
+ return (
+ <>
+
+ {renderTimeRow(operation)}
+
+
+
+ {limitString(operation.lucene || '', 120)}
+
+ highlight({ indexName: index.name, operation, shard })}
+ >
+ {i18n.translate('xpack.searchProfiler.profileTree.body.viewDetailsLabel', {
+ defaultMessage: 'View details',
+ })}
+
+
+
+
+ {childrenVisible &&
+ operation.hasChildren &&
+ operation.children.flatMap((childOp, idx) => (
+
+ ))}
+ >
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/types.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/types.ts
new file mode 100644
index 0000000000000..d38e895f66bbc
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/types.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { Index } from '../../types';
+
+export type IndexMap = Record;
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/unsafe_utils.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/unsafe_utils.ts
new file mode 100644
index 0000000000000..fc21c5da37764
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/unsafe_utils.ts
@@ -0,0 +1,221 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { produce } from 'immer';
+import { i18n } from '@kbn/i18n';
+import tinycolor from 'tinycolor2';
+import _ from 'lodash';
+
+import { BreakdownItem, Index, Operation, Shard, Targets } from '../../types';
+import { IndexMap } from './types';
+
+export const comparator = (v1: number, v2: number) => {
+ if (v1 < v2) {
+ return 1;
+ }
+ return v1 > v2 ? -1 : 0;
+};
+
+function getToolTip(key: string) {
+ switch (key) {
+ case 'build_scorer':
+ return i18n.translate('xpack.searchProfiler.buildScorerTimeDescription', {
+ defaultMessage:
+ 'The time taken to create the Scoring object, which is later used to execute the actual scoring of each doc.',
+ });
+ case 'create_weight':
+ return i18n.translate('xpack.searchProfiler.createWeightTimeDescription', {
+ defaultMessage:
+ 'The time taken to create the Weight object, which holds temporary information during scoring.',
+ });
+ case 'next_doc':
+ return i18n.translate('xpack.searchProfiler.nextDocTimeDescription', {
+ defaultMessage: 'The time taken to advance the iterator to the next matching document.',
+ });
+ case 'score':
+ return i18n.translate('xpack.searchProfiler.scoreTimeDescription', {
+ defaultMessage: 'The time taken in actually scoring the document against the query.',
+ });
+ case 'match':
+ return i18n.translate('xpack.searchProfiler.matchTimeDescription', {
+ defaultMessage:
+ 'The time taken to execute a secondary, more precise scoring phase (used by phrase queries).',
+ });
+ case 'advance':
+ return i18n.translate('xpack.searchProfiler.advanceTimeDescription', {
+ defaultMessage: 'The time taken to advance the iterator to the next document.',
+ });
+ default:
+ return '';
+ }
+}
+
+export function timeInMilliseconds(data: any) {
+ if (data.time_in_nanos) {
+ return data.time_in_nanos / 1000000;
+ }
+
+ if (typeof data.time === 'string') {
+ return data.time.replace('ms', '');
+ }
+
+ return data.time;
+}
+
+export function calcTimes(data: any[], parentId?: string) {
+ let totalTime = 0;
+ // First pass to collect total
+ for (const child of data) {
+ totalTime += timeInMilliseconds(child);
+
+ child.breakdown = normalizeBreakdown(child.breakdown);
+
+ let childrenTime = 0;
+ if (child.children != null && child.children.length !== 0) {
+ childrenTime = calcTimes(child.children, child.id)!;
+ child.hasChildren = true;
+ }
+ child.selfTime = timeInMilliseconds(child) - childrenTime;
+ }
+ return totalTime;
+}
+
+export function normalizeBreakdown(breakdown: Record) {
+ const final: BreakdownItem[] = [];
+ const total = Object.keys(breakdown).reduce((partialTotal, currentKey) => {
+ if (currentKey.indexOf('_count') === -1) {
+ partialTotal += breakdown[currentKey];
+ }
+ return partialTotal;
+ }, 0);
+ Object.keys(breakdown)
+ .sort()
+ .forEach(key => {
+ let relative = 0;
+ if (key.indexOf('_count') === -1) {
+ relative = ((breakdown[key] / total) * 100).toFixed(1) as any;
+ }
+ final.push({
+ key,
+ time: breakdown[key],
+ relative,
+ color: tinycolor.mix('#F5F5F5', '#FFAFAF', relative).toHexString(),
+ tip: getToolTip(key),
+ });
+ });
+
+ // Sort by time descending and then key ascending
+ return final.sort((a, b) => {
+ if (comparator(a.time, b.time) !== 0) {
+ return comparator(a.time, b.time);
+ }
+
+ return -1 * comparator(a.key as any, b.key as any);
+ });
+}
+
+export function normalizeTimes(data: any[], totalTime: number, depth: number) {
+ // Second pass to normalize
+ for (const child of data) {
+ child.timePercentage = ((timeInMilliseconds(child) / totalTime) * 100).toFixed(2);
+ child.absoluteColor = tinycolor.mix('#F5F5F5', '#FFAFAF', child.timePercentage).toHexString();
+ child.depth = depth;
+
+ if (child.children != null && child.children.length !== 0) {
+ normalizeTimes(child.children, totalTime, depth + 1);
+ }
+ }
+
+ data.sort((a, b) => comparator(timeInMilliseconds(a), timeInMilliseconds(b)));
+}
+
+export function normalizeIndices(indices: IndexMap, target: Targets) {
+ // Sort the shards per-index
+ let sortQueryComponents;
+ if (target === 'searches') {
+ sortQueryComponents = (a: Shard, b: Shard) => {
+ const aTime = _.sum(a.searches!, search => {
+ return search.treeRoot!.time;
+ });
+ const bTime = _.sum(b.searches!, search => {
+ return search.treeRoot!.time;
+ });
+
+ return comparator(aTime, bTime);
+ };
+ } else if (target === 'aggregations') {
+ sortQueryComponents = (a: Shard, b: Shard) => {
+ const aTime = _.sum(a.aggregations!, agg => {
+ return agg.treeRoot!.time;
+ });
+ const bTime = _.sum(b.aggregations!, agg => {
+ return agg.treeRoot!.time;
+ });
+
+ return comparator(aTime, bTime);
+ };
+ }
+ for (const index of Object.values(indices)) {
+ index.shards.sort(sortQueryComponents);
+ for (const shard of index.shards) {
+ shard.relative = ((shard.time / index.time) * 100).toFixed(2);
+ shard.color = tinycolor.mix('#F5F5F5', '#FFAFAF', shard.relative as any).toHexString();
+ }
+ }
+}
+
+export function initTree(data: Operation[], depth = 0, parent: Operation | null = null) {
+ for (const child of data) {
+ // For bwc of older profile responses
+ if (!child.description) {
+ child.description = child.lucene!;
+ child.lucene = null;
+
+ child.type = child.query_type!;
+ child.query_type = null;
+ }
+
+ // Use named function for tests.
+ child.parent = parent;
+ child.time = timeInMilliseconds(child);
+ child.lucene = child.description;
+ child.query_type = child.type!.split('.').pop()!;
+ child.visible = child.timePercentage > 20;
+ child.depth = depth;
+
+ if (child.children != null && child.children.length !== 0) {
+ initTree(child.children, depth + 1, child);
+ }
+ }
+}
+
+export function closeNode(node: Operation) {
+ const closeDraft = (draft: Operation) => {
+ draft.visible = false;
+
+ if (draft.children == null || draft.children.length === 0) {
+ return;
+ }
+
+ for (const child of draft.children) {
+ closeDraft(child);
+ }
+ };
+ return produce(node, draft => {
+ closeDraft(draft);
+ });
+}
+
+export const sortIndices = (data: IndexMap) =>
+ produce(data, doNotChange => {
+ const sortedIndices: Index[] = [];
+ for (const index of Object.values(doNotChange)) {
+ sortedIndices.push(index);
+ }
+ // And now sort the indices themselves
+ sortedIndices.sort((a, b) => comparator(a.time, b.time));
+ return sortedIndices;
+ });
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/use_highlight_tree_node.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/use_highlight_tree_node.ts
new file mode 100644
index 0000000000000..6e6f16a2cb683
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/use_highlight_tree_node.ts
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { useRef } from 'react';
+import uuid from 'uuid';
+
+import { useHighlightContext, OnHighlightChangeArgs } from './highlight_context';
+
+export const useHighlightTreeNode = () => {
+ const idRef = useRef(uuid.v4());
+ const { selectedRow, setStore } = useHighlightContext();
+
+ const highlight = (value: OnHighlightChangeArgs) => {
+ setStore({ id: idRef.current, ...value });
+ };
+
+ const isHighlighted = () => {
+ return selectedRow === idRef.current;
+ };
+
+ return {
+ id: idRef.current,
+ highlight,
+ isHighlighted,
+ };
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/utils.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/utils.ts
new file mode 100644
index 0000000000000..d0bedd873a1bd
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/utils.ts
@@ -0,0 +1,11 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { Operation } from '../../types';
+
+export const hasVisibleChild = ({ children }: Operation) => {
+ return Boolean(children && children.some(child => child.visible));
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.test.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.test.ts
new file mode 100644
index 0000000000000..8ee43e28bcd2c
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.test.ts
@@ -0,0 +1,24 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { registerTestBed } from '../../../../../../../test_utils';
+
+import { SearchProfilerTabs, Props } from './searchprofiler_tabs';
+
+describe('Search Profiler Tabs', () => {
+ it('renders', async () => {
+ const props: Props = {
+ activateTab: () => {},
+ activeTab: null,
+ has: {
+ aggregations: true,
+ searches: true,
+ },
+ };
+ const init = registerTestBed(SearchProfilerTabs);
+ await init(props);
+ });
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.tsx
new file mode 100644
index 0000000000000..19224e7099fd6
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.tsx
@@ -0,0 +1,46 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+
+import { EuiTabs, EuiTab } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { Targets } from '../types';
+
+export interface Props {
+ activeTab: Targets | null;
+ activateTab: (target: Targets) => void;
+ has: {
+ searches: boolean;
+ aggregations: boolean;
+ };
+}
+
+export const SearchProfilerTabs = ({ activeTab, activateTab, has }: Props) => {
+ return (
+
+ activateTab('searches')}
+ >
+ {i18n.translate('xpack.searchProfiler.queryProfileTabTitle', {
+ defaultMessage: 'Query Profile',
+ })}
+
+ activateTab('aggregations')}
+ >
+ {i18n.translate('xpack.searchProfiler.aggregationProfileTabTitle', {
+ defaultMessage: 'Aggregation Profile',
+ })}
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/index.ts
new file mode 100644
index 0000000000000..1830a34e93d30
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/index.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { Main } from './main';
+export { ProfileQueryEditor } from './profile_query_editor';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.test.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.test.tsx
new file mode 100644
index 0000000000000..4f17d0b4304f6
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.test.tsx
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { registerTestBed } from '../../../../../../../../../test_utils';
+import { EmptyTreePlaceHolder } from '.';
+
+describe('EmptyTreePlaceholder', () => {
+ it('renders', async () => {
+ const init = registerTestBed(EmptyTreePlaceHolder);
+ await init();
+ });
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.tsx
new file mode 100644
index 0000000000000..bf27620dcac18
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.tsx
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { EuiText } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+export const EmptyTreePlaceHolder = () => {
+ return (
+
+
+ {/* TODO: translations */}
+
+ {i18n.translate('xpack.searchProfiler.emptyProfileTreeTitle', {
+ defaultMessage: 'Nothing to see here yet.',
+ })}
+
+
+ {i18n.translate('xpack.searchProfiler.emptyProfileTreeDescription', {
+ defaultMessage:
+ 'Enter a query and press the "Profile" button or provide profile data in the editor.',
+ })}
+
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/index.ts
new file mode 100644
index 0000000000000..e8b7450ed9645
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/index.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { EmptyTreePlaceHolder } from './empty_tree_placeholder';
+export { ProfileLoadingPlaceholder } from './profile_loading_placeholder';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.test.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.test.tsx
new file mode 100644
index 0000000000000..9b3348b4cab4b
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.test.tsx
@@ -0,0 +1,15 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { registerTestBed } from '../../../../../../../../../test_utils';
+import { ProfileLoadingPlaceholder } from '.';
+
+describe('Profile Loading Placeholder', () => {
+ it('renders', async () => {
+ const init = registerTestBed(ProfileLoadingPlaceholder);
+ await init();
+ });
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.tsx
new file mode 100644
index 0000000000000..fb09c6cddf70a
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.tsx
@@ -0,0 +1,22 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { EuiText } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+export const ProfileLoadingPlaceholder = () => {
+ return (
+
+
+
+ {i18n.translate('xpack.searchProfiler.profilingLoaderText', {
+ defaultMessage: 'Profiling...',
+ })}
+
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/index.ts
new file mode 100644
index 0000000000000..509a15c0c71a5
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { Main } from './main';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/main.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/main.tsx
new file mode 100644
index 0000000000000..7f5d223949e61
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/main.tsx
@@ -0,0 +1,136 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useCallback } from 'react';
+import _ from 'lodash';
+
+import {
+ EuiPage,
+ EuiPageBody,
+ EuiPageContent,
+ EuiPageContentBody,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiSpacer,
+} from '@elastic/eui';
+import { ProfileQueryEditor } from '../';
+
+import {
+ SearchProfilerTabs,
+ ProfileTree,
+ HighlightDetailsFlyout,
+ LicenseWarningNotice,
+} from '../../components';
+
+import { useAppContext } from '../../contexts/app_context';
+
+import { EmptyTreePlaceHolder, ProfileLoadingPlaceholder } from './components';
+import { Targets, ShardSerialized } from '../../types';
+import { useProfilerActionContext, useProfilerReadContext } from '../../contexts/profiler_context';
+
+function hasSearch(profileResponse: ShardSerialized[]) {
+ const aggs = _.get(profileResponse, '[0].searches', []);
+ return aggs.length > 0;
+}
+
+function hasAggregations(profileResponse: ShardSerialized[]) {
+ const aggs = _.get(profileResponse, '[0].aggregations', []);
+ return aggs.length > 0;
+}
+
+export const Main = () => {
+ const { licenseEnabled } = useAppContext();
+
+ const {
+ activeTab,
+ currentResponse,
+ highlightDetails,
+ pristine,
+ profiling,
+ } = useProfilerReadContext();
+ const dispatch = useProfilerActionContext();
+
+ const setActiveTab = useCallback(
+ (target: Targets) => dispatch({ type: 'setActiveTab', value: target }),
+ [dispatch]
+ );
+
+ const onHighlight = useCallback(value => dispatch({ type: 'setHighlightDetails', value }), [
+ dispatch,
+ ]);
+
+ const renderLicenseWarning = () => {
+ return !licenseEnabled ? (
+ <>
+
+
+ >
+ ) : null;
+ };
+
+ const renderProfileTreeArea = () => {
+ if (profiling) {
+ return ;
+ }
+
+ if (activeTab) {
+ return (
+
+ );
+ }
+
+ if (licenseEnabled && pristine) {
+ return ;
+ }
+
+ return null;
+ };
+
+ return (
+ <>
+
+
+ {renderLicenseWarning()}
+
+
+
+
+
+
+
+
+
+ {renderProfileTreeArea()}
+
+
+
+ {highlightDetails ? (
+ dispatch({ type: 'setHighlightDetails', value: null })}
+ />
+ ) : null}
+
+
+
+
+ >
+ );
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/profile_query_editor.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/profile_query_editor.tsx
new file mode 100644
index 0000000000000..ea3421ffe89aa
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/profile_query_editor.tsx
@@ -0,0 +1,131 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { useRef, memo, useCallback } from 'react';
+import { i18n } from '@kbn/i18n';
+import {
+ EuiForm,
+ EuiFieldText,
+ EuiFormRow,
+ EuiButton,
+ EuiText,
+ EuiFlexGroup,
+ EuiSpacer,
+ EuiFlexItem,
+} from '@elastic/eui';
+import { Editor, EditorInstance } from '../editor';
+import { useRequestProfile } from '../hooks';
+import { useAppContext } from '../contexts/app_context';
+import { useProfilerActionContext } from '../contexts/profiler_context';
+
+const DEFAULT_INDEX_VALUE = '_all';
+
+const INITIAL_EDITOR_VALUE = `{
+ "query":{
+ "match_all" : {}
+ }
+}`;
+
+/**
+ * This component should only need to render once.
+ *
+ * Drives state changes for mine via profiler action context.
+ */
+export const ProfileQueryEditor = memo(() => {
+ const editorRef = useRef(null as any);
+ const indexInputRef = useRef(null as any);
+
+ const dispatch = useProfilerActionContext();
+
+ const { licenseEnabled, notifications } = useAppContext();
+ const requestProfile = useRequestProfile();
+
+ const handleProfileClick = async () => {
+ dispatch({ type: 'setProfiling', value: true });
+ try {
+ const { current: editor } = editorRef;
+ const { data: result, error } = await requestProfile({
+ query: editorRef.current.getValue(),
+ index: indexInputRef.current.value,
+ });
+ if (error) {
+ notifications.addDanger(error);
+ editor.focus();
+ return;
+ }
+ if (result === null) {
+ return;
+ }
+ dispatch({ type: 'setCurrentResponse', value: result });
+ } finally {
+ dispatch({ type: 'setProfiling', value: false });
+ }
+ };
+
+ const onEditorReady = useCallback(editorInstance => (editorRef.current = editorInstance), []);
+
+ return (
+
+ {/* Form */}
+
+
+
+
+
+ {
+ indexInputRef.current = ref!;
+ ref!.value = DEFAULT_INDEX_VALUE;
+ }}
+ />
+
+
+
+
+
+
+ {/* Editor */}
+
+
+
+
+ {/* Button */}
+
+
+
+
+
+
+ handleProfileClick()}>
+
+ {i18n.translate('xpack.searchProfiler.formProfileButtonLabel', {
+ defaultMessage: 'Profile',
+ })}
+
+
+
+
+
+
+ );
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/app_context.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/app_context.tsx
new file mode 100644
index 0000000000000..7f8a6cf01dcb2
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/app_context.tsx
@@ -0,0 +1,35 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useContext, createContext } from 'react';
+import { HttpSetup, ToastsSetup } from 'kibana/public';
+
+export interface ContextValue {
+ http: HttpSetup;
+ notifications: ToastsSetup;
+ licenseEnabled: boolean;
+ formatAngularHttpError: (error: any) => string;
+}
+
+const AppContext = createContext(null as any);
+
+export const AppContextProvider = ({
+ children,
+ value,
+}: {
+ children: React.ReactNode;
+ value: ContextValue;
+}) => {
+ return {children} ;
+};
+
+export const useAppContext = () => {
+ const ctx = useContext(AppContext);
+ if (ctx == null) {
+ throw new Error(`useAppContext must be called inside AppContextProvider`);
+ }
+ return ctx;
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/profiler_context.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/profiler_context.tsx
new file mode 100644
index 0000000000000..ad46c61b6cd49
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/profiler_context.tsx
@@ -0,0 +1,36 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useContext, createContext, Dispatch } from 'react';
+import { useStore, State, Action } from '../store';
+
+const ProfilerReadContext = createContext(null as any);
+const ProfilerActionContext = createContext>(null as any);
+
+export const ProfileContextProvider = ({ children }: { children: React.ReactNode }) => {
+ const { dispatch, state } = useStore();
+ return (
+
+ {children}
+
+ );
+};
+
+export const useProfilerReadContext = () => {
+ const ctx = useContext(ProfilerReadContext);
+ if (ctx == null) {
+ throw new Error(`useProfilerReadContext must be called inside ProfilerReadContext`);
+ }
+ return ctx;
+};
+
+export const useProfilerActionContext = () => {
+ const ctx = useContext(ProfilerActionContext);
+ if (ctx == null) {
+ throw new Error(`useProfilerActionContext must be called inside ProfilerActionContext`);
+ }
+ return ctx;
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.test.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.test.tsx
new file mode 100644
index 0000000000000..d6702ef080ab7
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.test.tsx
@@ -0,0 +1,27 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import 'brace';
+import 'brace/mode/json';
+
+jest.mock('./worker', () => {
+ return { workerModule: { id: 'ace/mode/json_worker', src: '' } };
+});
+
+import { registerTestBed } from '../../../../../../../test_utils';
+import { Editor, Props } from '.';
+
+describe('Editor Component', () => {
+ it('renders', async () => {
+ const props: Props = {
+ initialValue: '',
+ licenseEnabled: true,
+ onEditorReady: e => {},
+ };
+ // Ignore the warning about Worker not existing for now...
+ const init = registerTestBed(Editor);
+ await init(props);
+ });
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.tsx
new file mode 100644
index 0000000000000..014336f379059
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.tsx
@@ -0,0 +1,57 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { memo, useRef, useEffect, useState } from 'react';
+import { Editor as AceEditor } from 'brace';
+
+import { initializeEditor } from './init_editor';
+import { useUIAceKeyboardMode } from './use_ui_ace_keyboard_mode';
+
+interface EditorShim {
+ getValue(): string;
+ focus(): void;
+}
+
+export type EditorInstance = EditorShim;
+
+export interface Props {
+ licenseEnabled: boolean;
+ initialValue: string;
+ onEditorReady: (editor: EditorShim) => void;
+}
+
+const createEditorShim = (aceEditor: AceEditor): EditorShim => {
+ return {
+ getValue() {
+ return aceEditor.getValue();
+ },
+ focus() {
+ aceEditor.focus();
+ },
+ };
+};
+
+export const Editor = memo(({ licenseEnabled, initialValue, onEditorReady }: Props) => {
+ const containerRef = useRef(null as any);
+ const editorInstanceRef = useRef(null as any);
+
+ const [textArea, setTextArea] = useState(null);
+
+ if (licenseEnabled) {
+ useUIAceKeyboardMode(textArea);
+ }
+
+ useEffect(() => {
+ const divEl = containerRef.current;
+ editorInstanceRef.current = initializeEditor({ el: divEl, licenseEnabled });
+ editorInstanceRef.current.setValue(initialValue, 1);
+ setTextArea(containerRef.current!.querySelector('textarea'));
+
+ onEditorReady(createEditorShim(editorInstanceRef.current));
+ }, [initialValue, onEditorReady, licenseEnabled]);
+
+ return
;
+});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/index.ts
new file mode 100644
index 0000000000000..f17f37923ae83
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { Editor, Props, EditorInstance } from './editor';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/editor/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/init_editor.ts
similarity index 85%
rename from x-pack/legacy/plugins/searchprofiler/public/editor/index.ts
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/init_editor.ts
index 45562385c2e69..e5aad16bc4af2 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/editor/index.ts
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/init_editor.ts
@@ -10,11 +10,9 @@ import { installXJsonMode } from './x_json_mode';
export function initializeEditor({
el,
licenseEnabled,
- initialContent,
}: {
el: HTMLDivElement;
licenseEnabled: boolean;
- initialContent: string;
}) {
const editor: ace.Editor = ace.acequire('ace/ace').edit(el);
@@ -25,6 +23,10 @@ export function initializeEditor({
editor.setReadOnly(true);
editor.container.style.pointerEvents = 'none';
editor.container.style.opacity = '0.5';
+ const textArea = editor.container.querySelector('textarea');
+ if (textArea) {
+ textArea.setAttribute('tabindex', '-1');
+ }
editor.renderer.setStyle('disabled');
editor.blur();
}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/use_ui_ace_keyboard_mode.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/use_ui_ace_keyboard_mode.tsx
new file mode 100644
index 0000000000000..edf31c2e7c07f
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/use_ui_ace_keyboard_mode.tsx
@@ -0,0 +1,110 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+/**
+ * Copied from Console plugin
+ */
+
+import React, { useEffect, useRef } from 'react';
+import * as ReactDOM from 'react-dom';
+import { keyCodes, EuiText } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+const OverlayText = () => (
+ // The point of this element is for accessibility purposes, so ignore eslint error
+ // in this case
+ //
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
+ <>
+
+ {i18n.translate('xpack.searchProfiler.aceAccessibilityOverlayInstructionEnter', {
+ defaultMessage: 'Press Enter to start editing.',
+ })}
+
+
+ {i18n.translate('xpack.searchProfiler.aceAccessibilityOverlayInstructionExit', {
+ defaultMessage: `When you are done, press Escape to stop editing.`,
+ })}
+
+ >
+);
+
+export function useUIAceKeyboardMode(aceTextAreaElement: HTMLTextAreaElement | null) {
+ const overlayMountNode = useRef(null);
+ const autoCompleteVisibleRef = useRef(false);
+
+ useEffect(() => {
+ function onDismissOverlay(event: KeyboardEvent) {
+ if (event.keyCode === keyCodes.ENTER) {
+ event.preventDefault();
+ aceTextAreaElement!.focus();
+ }
+ }
+
+ function enableOverlay() {
+ if (overlayMountNode.current) {
+ overlayMountNode.current.focus();
+ }
+ }
+
+ const isAutoCompleteVisible = () => {
+ const autoCompleter = document.querySelector('.ace_autocomplete');
+ if (!autoCompleter) {
+ return false;
+ }
+ // The autoComplete is just hidden when it's closed, not removed from the DOM.
+ return autoCompleter.style.display !== 'none';
+ };
+
+ const documentKeyDownListener = () => {
+ autoCompleteVisibleRef.current = isAutoCompleteVisible();
+ };
+
+ const aceKeydownListener = (event: KeyboardEvent) => {
+ if (event.keyCode === keyCodes.ESCAPE && !autoCompleteVisibleRef.current) {
+ event.preventDefault();
+ event.stopPropagation();
+ enableOverlay();
+ }
+ };
+
+ if (aceTextAreaElement) {
+ // We don't control HTML elements inside of ace so we imperatively create an element
+ // that acts as a container and insert it just before ace's textarea element
+ // so that the overlay lives at the correct spot in the DOM hierarchy.
+ overlayMountNode.current = document.createElement('div');
+ overlayMountNode.current.className = 'kbnUiAceKeyboardHint';
+ overlayMountNode.current.setAttribute('role', 'application');
+ overlayMountNode.current.tabIndex = 0;
+ overlayMountNode.current.addEventListener('focus', enableOverlay);
+ overlayMountNode.current.addEventListener('keydown', onDismissOverlay);
+
+ ReactDOM.render( , overlayMountNode.current);
+
+ aceTextAreaElement.parentElement!.insertBefore(overlayMountNode.current, aceTextAreaElement);
+ aceTextAreaElement.setAttribute('tabindex', '-1');
+
+ // Order of events:
+ // 1. Document capture event fires first and we check whether an autocomplete menu is open on keydown
+ // (not ideal because this is scoped to the entire document).
+ // 2. Ace changes it's state (like hiding or showing autocomplete menu)
+ // 3. We check what button was pressed and whether autocomplete was visible then determine
+ // whether it should act like a dismiss or if we should display an overlay.
+ document.addEventListener('keydown', documentKeyDownListener, { capture: true });
+ aceTextAreaElement.addEventListener('keydown', aceKeydownListener);
+ }
+ return () => {
+ if (aceTextAreaElement) {
+ document.removeEventListener('keydown', documentKeyDownListener);
+ aceTextAreaElement.removeEventListener('keydown', aceKeydownListener);
+ const textAreaContainer = aceTextAreaElement.parentElement;
+ if (textAreaContainer && textAreaContainer.contains(overlayMountNode.current!)) {
+ textAreaContainer.removeChild(overlayMountNode.current!);
+ }
+ }
+ };
+ }, [aceTextAreaElement]);
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/editor/worker/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/searchprofiler/public/editor/worker/index.ts
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/index.ts
diff --git a/x-pack/legacy/plugins/searchprofiler/public/editor/worker/worker.d.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/worker.d.ts
similarity index 100%
rename from x-pack/legacy/plugins/searchprofiler/public/editor/worker/worker.d.ts
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/worker.d.ts
diff --git a/x-pack/legacy/plugins/searchprofiler/public/editor/worker/worker.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/worker.js
similarity index 100%
rename from x-pack/legacy/plugins/searchprofiler/public/editor/worker/worker.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/worker.js
diff --git a/x-pack/legacy/plugins/searchprofiler/public/editor/x_json_highlight_rules.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/x_json_highlight_rules.ts
similarity index 100%
rename from x-pack/legacy/plugins/searchprofiler/public/editor/x_json_highlight_rules.ts
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/x_json_highlight_rules.ts
diff --git a/x-pack/legacy/plugins/searchprofiler/public/editor/x_json_mode.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/x_json_mode.ts
similarity index 100%
rename from x-pack/legacy/plugins/searchprofiler/public/editor/x_json_mode.ts
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/x_json_mode.ts
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/index.ts
new file mode 100644
index 0000000000000..a9fa5fee994e0
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { useRequestProfile } from './use_request_profile';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/use_request_profile.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/use_request_profile.ts
new file mode 100644
index 0000000000000..34b49be7dc39c
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/use_request_profile.ts
@@ -0,0 +1,77 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { i18n } from '@kbn/i18n';
+
+import { useAppContext } from '../contexts/app_context';
+import { checkForParseErrors } from '../utils';
+import { ShardSerialized } from '../types';
+
+interface Args {
+ query: string;
+ index: string;
+}
+
+interface ReturnValue {
+ data: ShardSerialized[] | null;
+ error?: string;
+}
+
+export const useRequestProfile = () => {
+ const { http, notifications, formatAngularHttpError, licenseEnabled } = useAppContext();
+ return async ({ query, index }: Args): Promise => {
+ if (!licenseEnabled) {
+ return { data: null };
+ }
+ const { error, parsed } = checkForParseErrors(query);
+ if (error) {
+ notifications.addError(error, {
+ title: i18n.translate('xpack.searchProfiler.errorToastTitle', {
+ defaultMessage: 'JSON parse error',
+ }),
+ });
+ return { data: null };
+ }
+ // Shortcut the network request if we have json with shards already...
+ if (parsed.profile && parsed.profile.shards) {
+ return { data: parsed.profile.shards };
+ }
+
+ const payload: Record = { query };
+
+ if (index == null || index === '') {
+ payload.index = '_all';
+ } else {
+ payload.index = index;
+ }
+
+ try {
+ const resp = await http.post('../api/searchprofiler/profile', {
+ body: JSON.stringify(payload),
+ headers: { 'Content-Type': 'application/json' },
+ });
+
+ if (!resp.ok) {
+ return { data: null, error: resp.err.msg };
+ }
+
+ return { data: resp.resp.profile.shards };
+ } catch (e) {
+ try {
+ // Is this a known error type?
+ const errorString = formatAngularHttpError(e);
+ notifications.addError(e, { title: errorString });
+ } catch (_) {
+ // Otherwise just report the original error
+ notifications.addError(e, {
+ title: i18n.translate('xpack.searchProfiler.errorSomethingWentWrongTitle', {
+ defaultMessage: 'Something went wrong',
+ }),
+ });
+ }
+ return { data: null };
+ }
+ };
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/index.scss b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.scss
similarity index 84%
rename from x-pack/legacy/plugins/searchprofiler/public/index.scss
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.scss
index 2db81310a8db4..e04e81c023196 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/index.scss
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.scss
@@ -9,5 +9,4 @@
// prfDevTool__cell
// prfDevTool__shardDetails
-@import 'directives/index';
-@import 'templates/index';
\ No newline at end of file
+@import 'styles/index';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.tsx
new file mode 100644
index 0000000000000..d29f193ce9d90
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.tsx
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React from 'react';
+import { Main } from './containers';
+import { AppContextProvider } from './contexts/app_context';
+import { ProfileContextProvider } from './contexts/profiler_context';
+
+import { AppDependencies } from './boot';
+
+export function App({
+ I18nContext,
+ licenseEnabled,
+ notifications,
+ http,
+ formatAngularHttpError,
+}: AppDependencies) {
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/index.ts
new file mode 100644
index 0000000000000..5e30e07a7b8b7
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/index.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { useStore, State } from './store';
+export { Action } from './reducer';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/reducer.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/reducer.ts
new file mode 100644
index 0000000000000..dac9dab9bd092
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/reducer.ts
@@ -0,0 +1,57 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { produce } from 'immer';
+import { Reducer } from 'react';
+import { State } from './store';
+
+import { OnHighlightChangeArgs } from '../components/profile_tree';
+import { ShardSerialized, Targets } from '../types';
+
+export type Action =
+ | { type: 'setPristine'; value: boolean }
+ | { type: 'setProfiling'; value: boolean }
+ | { type: 'setHighlightDetails'; value: OnHighlightChangeArgs | null }
+ | { type: 'setActiveTab'; value: Targets | null }
+ | { type: 'setCurrentResponse'; value: ShardSerialized[] | null };
+
+export const reducer: Reducer = (state, action) =>
+ produce(state, draft => {
+ if (action.type === 'setPristine') {
+ draft.pristine = action.value;
+ return;
+ }
+
+ if (action.type === 'setProfiling') {
+ draft.profiling = action.value;
+ if (draft.profiling) {
+ draft.currentResponse = null;
+ draft.highlightDetails = null;
+ }
+ return;
+ }
+
+ if (action.type === 'setHighlightDetails') {
+ draft.highlightDetails = action.value;
+ return;
+ }
+
+ if (action.type === 'setActiveTab') {
+ draft.activeTab = action.value;
+ return;
+ }
+
+ if (action.type === 'setCurrentResponse') {
+ draft.currentResponse = action.value;
+ if (draft.currentResponse) {
+ // Default to the searches tab
+ draft.activeTab = 'searches';
+ }
+ return;
+ }
+
+ throw new Error(`Unknown action: ${action}`);
+ });
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/store.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/store.ts
new file mode 100644
index 0000000000000..7b5a1ce93583d
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/store.ts
@@ -0,0 +1,33 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { useReducer } from 'react';
+import { reducer } from './reducer';
+import { ShardSerialized, Targets } from '../types';
+import { OnHighlightChangeArgs } from '../components/profile_tree';
+
+export interface State {
+ profiling: boolean;
+ pristine: boolean;
+ highlightDetails: OnHighlightChangeArgs | null;
+ activeTab: Targets | null;
+ currentResponse: ShardSerialized[] | null;
+}
+
+export const initialState: State = {
+ profiling: false,
+ pristine: false,
+ highlightDetails: null,
+ activeTab: null,
+ currentResponse: null,
+};
+
+export const useStore = () => {
+ const [state, dispatch] = useReducer(reducer, initialState);
+ return {
+ state,
+ dispatch,
+ };
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/_index.scss b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/_index.scss
new file mode 100644
index 0000000000000..a72d079354f89
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/_index.scss
@@ -0,0 +1,83 @@
+@import '@elastic/eui/src/components/header/variables';
+@import '@elastic/eui/src/components/panel/mixins';
+
+@import 'mixins';
+
+@import 'components/highlight_details_flyout';
+@import 'components/profile_tree';
+@import 'components/percentage_badge';
+
+@import 'containers/main';
+@import 'containers/profile_query_editor';
+
+#searchProfilerAppRoot {
+ height: 100%;
+ display: flex;
+ flex: 1 1 auto;
+}
+
+.prfDevTool__licenseWarning {
+ &__container {
+ max-width: 1000px;
+ }
+}
+
+
+.prfDevTool__page {
+ height: 100%;
+ display: flex;
+ flex: 1 1 auto;
+
+ &__body {
+ height: 100%;
+ flex: 1 1 auto;
+ }
+
+ &__pageBody {
+ height: 100%;
+ flex: 1 1 auto;
+ }
+
+ &__pageBodyContent {
+ height: 100%;
+ }
+
+ &__pageBodyContentBody {
+ height: 100%;
+ }
+
+ &__pageContentBodyContent {
+ height: 100%;
+ }
+
+ &__bodyGroup {
+ height: 100%;
+ }
+}
+
+.prfDevTool {
+ height: calc(100vh - #{$euiHeaderChildSize});
+ overflow: hidden;
+
+ .devApp__container {
+ height: 100%;
+ overflow: hidden;
+ flex-shrink: 1;
+ }
+
+ &__container {
+ overflow: hidden;
+ }
+}
+
+.prfDevTool__detail {
+ font-size: $euiFontSizeS;
+ padding-left: $euiSizeL - 3px; // Alignment is weird
+ margin-bottom: $euiSizeS;
+ display: flex;
+ justify-content: space-between;
+
+ .euiLink {
+ flex-shrink: 0;
+ }
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/directives/_mixins.scss b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/_mixins.scss
similarity index 100%
rename from x-pack/legacy/plugins/searchprofiler/public/directives/_mixins.scss
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/_mixins.scss
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_highlight_details_flyout.scss b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_highlight_details_flyout.scss
new file mode 100644
index 0000000000000..4b36e9833979d
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_highlight_details_flyout.scss
@@ -0,0 +1,8 @@
+.prfDevTool__flyoutSubtitle {
+ margin-bottom: $euiSizeS;
+ display: inline-block;
+}
+
+.prfDevTool__details {
+ max-width: map-get($euiBreakpoints, 's');
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_percentage_badge.scss b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_percentage_badge.scss
new file mode 100644
index 0000000000000..204ca3da17574
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_percentage_badge.scss
@@ -0,0 +1,14 @@
+.prfDevTool__percentBadge {
+ &__progress--percent {
+ @include prfDevToolProgress;
+ width: $badgeSize;
+ }
+
+ &__progress--time {
+ @include prfDevToolProgress(#FFAFAF);
+ background-color: #F5F5F5; // Must be light at all times
+ // Width of 3 badges, with the last child not having padding on the left
+ width: ($badgeSize * 3) - ($euiSizeXS * .75);
+ // Force text to always be dark on top of white -> pink color
+ }
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_profile_tree.scss b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_profile_tree.scss
new file mode 100644
index 0000000000000..cc4d334f58fd3
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_profile_tree.scss
@@ -0,0 +1,99 @@
+
+$badgeSize: $euiSize * 5.5;
+
+// Profile details treeview
+
+.prfDevTool__profileTree {
+
+ &__container {
+ height: 100%;
+ }
+
+ &__shardDetails--dim small {
+ color: $euiColorDarkShade;
+ }
+
+ &__shardDetails {
+ line-height: 1;
+ overflow-wrap: break-word;
+
+ h3 {
+ font-size: $euiSize;
+ }
+
+ &:disabled {
+ text-decoration: none !important;
+ cursor: default;
+ }
+ }
+
+ &__shard {
+ border: none;
+
+ &__header-flex-item {
+ align-self: center;
+ }
+ }
+
+ &__index {
+ width: 100%;
+ padding: $euiSize $euiSizeS;
+ }
+
+ &__indexDetails {
+ align-self: center;
+ }
+
+ &__tvRow--last {
+ cursor: pointer;
+ }
+
+ &__tvRow,
+ &__tvHeader {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+ }
+
+ &__tvHeader {
+ @include euiFontSizeXS;
+ color: $euiColorDarkShade;
+ }
+
+ &__time,
+ &__totalTime,
+ &__percentage {
+ width: $badgeSize;
+ }
+
+ // BADGES (and those used for progress)
+ &__badge {
+ border: none;
+ display: block;
+ // Force text to always be dark on top of white -> pink color
+ color: lightOrDarkTheme($euiColorDarkestShade, $euiColorLightestShade);
+ }
+
+ &__panel {
+ border-bottom: $euiBorderThin;
+ }
+
+ &__panelBody {
+ margin-top: $euiSizeS;
+ margin-left: $euiSizeL;
+ }
+
+ &__cell {
+ display: table-cell;
+ vertical-align: middle;
+ padding: $euiSizeXS;
+
+ &:first-of-type {
+ padding-left: 0;
+ }
+
+ &:last-of-type {
+ padding-right: 0;
+ }
+ }
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_main.scss b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_main.scss
new file mode 100644
index 0000000000000..09bcddef02cc3
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_main.scss
@@ -0,0 +1,62 @@
+
+@include euiBreakpoint('xs', 's') {
+ .prfDevTool__shardDetailsWrapper {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
+
+.prfDevTool__main {
+ height: 100%;
+ order: 2;
+ margin-left: $euiSize;
+ display: flex;
+ overflow: hidden;
+ flex-direction: column;
+
+ // Make only the tab content scroll
+ .search-profiler-tabs {
+ flex-shrink: 0;
+ }
+
+ &__profiletree {
+ height: 100%;
+ overflow-y: auto;
+ flex-grow: 1;
+ }
+
+ &__emptyTreePlaceholder {
+ h1 {
+ font-size: $euiSizeL;
+ color: $euiColorMediumShade;
+ }
+ p {
+ font-size: $euiSize;
+ color: $euiColorMediumShade;
+ }
+ h1, p {
+ cursor: default;
+ user-select: none;
+ }
+ // Slight offset from the top.
+ margin: 5% 0 auto;
+ text-align: center;
+ }
+}
+
+@include euiPanel('prfDevTool__main');
+
+@include euiBreakpoint('xs', 's') {
+ .prfDevTool__container {
+ flex-direction: column;
+ }
+
+ .prfDevTool__main {
+ flex: 0 0 auto;
+ }
+
+ .prfDevTool__main {
+ margin: $euiSize 0;
+ }
+}
+
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_profile_query_editor.scss b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_profile_query_editor.scss
new file mode 100644
index 0000000000000..035ff16c990bb
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_profile_query_editor.scss
@@ -0,0 +1,25 @@
+
+.prfDevTool__sense {
+ order: 1;
+ // To anchor ace editor
+ position: relative;
+
+ // Ace Editor overrides
+ .ace_editor {
+ min-height: $euiSize * 10;
+ flex-grow: 1;
+ margin-bottom: $euiSize;
+ margin-top: $euiSize;
+ outline: solid 1px $euiColorLightShade;
+ }
+
+ .errorMarker {
+ position: absolute;
+ background: rgba($euiColorDanger, .5);
+ z-index: 20;
+ }
+}
+
+.prfDevTool__profileButtonContainer {
+ flex-shrink: 1;
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/types.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/types.ts
new file mode 100644
index 0000000000000..2b4dc01c45d6f
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/types.ts
@@ -0,0 +1,69 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export interface BreakdownItem {
+ tip: string;
+ key: string;
+ time: number;
+ color: string;
+ relative: number;
+}
+
+export type Targets = 'searches' | 'aggregations';
+
+export interface Shard {
+ id: string[];
+ relative: number | string;
+ time: number;
+ color: string;
+ aggregations?: Operation[];
+ searches?: Operation[];
+ rewrite_time?: number;
+}
+
+export interface Index {
+ name: string;
+ time: number;
+ shards: Shard[];
+ visible: boolean;
+}
+
+export interface ShardSerialized {
+ id: string;
+ searches: Operation[];
+ aggregations: Operation[];
+}
+
+export interface Operation {
+ description?: string;
+ hasChildren: boolean;
+ visible: boolean;
+ selfTime: number;
+ timePercentage: number;
+ absoluteColor: string;
+ time: number;
+
+ parent: Operation | null;
+ children: Operation[];
+
+ // Only exists on top level
+ treeRoot?: Operation;
+
+ depth?: number;
+
+ // BWC
+ type?: string;
+
+ lucene: string | null;
+ query_type: string | null;
+
+ // Searches
+ query?: any[];
+ rewrite_time?: number;
+
+ // Aggregations
+ breakdown?: any;
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/__tests__/app_util.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.test.ts
similarity index 61%
rename from x-pack/legacy/plugins/searchprofiler/public/__tests__/app_util.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.test.ts
index 164e7394dead7..9dece5a39e96c 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/__tests__/app_util.js
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.test.ts
@@ -5,18 +5,18 @@
*/
import expect from '@kbn/expect';
-import { checkForParseErrors } from '../app_util.js';
+import { checkForParseErrors } from '.';
-describe('checkForParseErrors', function () {
- it('returns false from bad JSON', function () {
+describe('checkForParseErrors', function() {
+ it('returns error from bad JSON', function() {
const json = '{"foo": {"bar": {"baz": "buzz}}}';
const result = checkForParseErrors(json);
- expect(result.status).to.be(false);
+ expect(result.error.message).to.be(`Unexpected end of JSON input`);
});
- it('returns true from good JSON', function () {
+ it('returns parsed value from good JSON', function() {
const json = '{"foo": {"bar": {"baz": "buzz"}}}';
const result = checkForParseErrors(json);
- expect(result.status).to.be(true);
+ expect(!!result.parsed).to.be(true);
});
});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/app_util.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.ts
similarity index 71%
rename from x-pack/legacy/plugins/searchprofiler/public/app_util.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.ts
index 18eef2259bd6a..4267fd0d2f901 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/app_util.js
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.ts
@@ -5,18 +5,18 @@
*/
// Convert triple quotes into regular quotes and escape internal quotes.
-function collapseLiteralStrings(data) {
- return data.replace(/"""(?:\s*\r?\n)?((?:.|\r?\n)*?)(?:\r?\n\s*)?"""/g, function (match, literal) {
+function collapseLiteralStrings(data: string) {
+ return data.replace(/"""(?:\s*\r?\n)?((?:.|\r?\n)*?)(?:\r?\n\s*)?"""/g, function(match, literal) {
return JSON.stringify(literal);
});
}
-export function checkForParseErrors(json) {
+export function checkForParseErrors(json: string) {
const sanitizedJson = collapseLiteralStrings(json);
try {
const parsedJson = JSON.parse(sanitizedJson);
- return { status: true, parsed: parsedJson };
+ return { parsed: parsedJson, error: null };
} catch (error) {
- return { status: false, error };
+ return { error, parsed: null };
}
}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/index.ts
new file mode 100644
index 0000000000000..556a03fc96fe3
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/index.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { checkForParseErrors } from './check_for_json_errors';
+export { msToPretty } from './ms_to_pretty';
+export { nsToPretty } from './ns_to_pretty';
diff --git a/x-pack/legacy/plugins/searchprofiler/public/filters/ms_to_pretty.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ms_to_pretty.ts
similarity index 91%
rename from x-pack/legacy/plugins/searchprofiler/public/filters/ms_to_pretty.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ms_to_pretty.ts
index aa088ffc46c59..3df47cfdeb177 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/filters/ms_to_pretty.js
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ms_to_pretty.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export function msToPretty(ms, precision) {
+export function msToPretty(ms: number, precision: number) {
if (!precision) {
precision = 1;
}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.test.ts
similarity index 60%
rename from x-pack/legacy/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.test.ts
index 85208495fc18e..6c0e1124af176 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.test.ts
@@ -5,45 +5,45 @@
*/
import expect from '@kbn/expect';
-import { nsToPretty } from '../ns_to_pretty.js';
+import { nsToPretty } from './ns_to_pretty';
-describe('nsToPretty', function () {
- it('returns correct time for ns', function () {
+describe('nsToPretty', function() {
+ it('returns correct time for ns', function() {
const result = nsToPretty(500, 1);
expect(result).to.eql('500.0ns');
});
- it('returns correct time for µs', function () {
+ it('returns correct time for µs', function() {
const result = nsToPretty(5000, 1);
expect(result).to.eql('5.0µs');
});
- it('returns correct time for ms', function () {
+ it('returns correct time for ms', function() {
const result = nsToPretty(5000000, 1);
expect(result).to.eql('5.0ms');
});
- it('returns correct time for s', function () {
+ it('returns correct time for s', function() {
const result = nsToPretty(5000000000, 1);
expect(result).to.eql('5.0s');
});
- it('returns correct time for min', function () {
+ it('returns correct time for min', function() {
const result = nsToPretty(5000000000 * 60, 1);
expect(result).to.eql('5.0min');
});
- it('returns correct time for hr', function () {
- const result = nsToPretty(3.6e+12 * 5, 1);
+ it('returns correct time for hr', function() {
+ const result = nsToPretty(3.6e12 * 5, 1);
expect(result).to.eql('5.0hr');
});
- it('returns correct time for day', function () {
- const result = nsToPretty(3.6e+12 * 24 * 5, 1);
+ it('returns correct time for day', function() {
+ const result = nsToPretty(3.6e12 * 24 * 5, 1);
expect(result).to.eql('5.0d');
});
- it('returns correct time for precision', function () {
+ it('returns correct time for precision', function() {
const result = nsToPretty(500, 5);
expect(result).to.eql('500.00000ns');
});
diff --git a/x-pack/legacy/plugins/searchprofiler/public/filters/ns_to_pretty.js b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.ts
similarity index 89%
rename from x-pack/legacy/plugins/searchprofiler/public/filters/ns_to_pretty.js
rename to x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.ts
index 74737ed8e30d4..bf0b487566f6f 100644
--- a/x-pack/legacy/plugins/searchprofiler/public/filters/ns_to_pretty.js
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.ts
@@ -6,7 +6,7 @@
import { msToPretty } from './ms_to_pretty';
-export function nsToPretty(ns, precision) {
+export function nsToPretty(ns: number, precision: number) {
if (!precision) {
precision = 1;
}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/index.ts
new file mode 100644
index 0000000000000..3d77f703b42cd
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/index.ts
@@ -0,0 +1,12 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { PluginInitializerContext } from 'src/core/public';
+import { SearchProfilerUIPlugin } from './plugin';
+
+export function plugin(ctx: PluginInitializerContext) {
+ return new SearchProfilerUIPlugin(ctx);
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts
new file mode 100644
index 0000000000000..ff98e706abf5c
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts
@@ -0,0 +1,55 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import {
+ Plugin,
+ CoreStart,
+ CoreSetup,
+ PluginInitializerContext,
+ ToastsStart,
+} from 'src/core/public';
+
+import { boot } from './application/boot';
+
+export class SearchProfilerUIPlugin implements Plugin {
+ constructor(ctx: PluginInitializerContext) {}
+
+ async setup(
+ core: CoreSetup,
+ plugins: {
+ __LEGACY: {
+ I18nContext: any;
+ licenseEnabled: boolean;
+ notifications: ToastsStart;
+ formatAngularHttpError: any;
+ el: HTMLElement;
+ };
+ }
+ ) {
+ const { http } = core;
+ const {
+ __LEGACY: { I18nContext, licenseEnabled, notifications, formatAngularHttpError, el },
+ } = plugins;
+ core.application.register({
+ id: 'searchprofiler',
+ title: 'SearchProfiler',
+ mount(ctx, params) {
+ return boot({
+ http,
+ licenseEnabled,
+ el,
+ I18nContext,
+ notifications,
+ formatAngularHttpError,
+ });
+ },
+ });
+ }
+
+ async start(core: CoreStart, plugins: any) {}
+
+ async stop() {}
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/range.js b/x-pack/legacy/plugins/searchprofiler/public/range.js
deleted file mode 100644
index d52ed783d9720..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/range.js
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-
-// Pulled from Ace because I can't for the life of me
-// figure out how to import it. This needs to be fixed TODO
-
-const comparePoints = function (p1, p2) {
- return p1.row - p2.row || p1.column - p2.column;
-};
-
-export function Range(startRow, startColumn, endRow, endColumn) {
- this.start = {
- row: startRow,
- column: startColumn
- };
-
- this.end = {
- row: endRow,
- column: endColumn
- };
-}
-
-(function () {
- this.isEqual = function (range) {
- return this.start.row === range.start.row &&
- this.end.row === range.end.row &&
- this.start.column === range.start.column &&
- this.end.column === range.end.column;
- };
- this.toString = function () {
- return ('Range: [' + this.start.row + '/' + this.start.column +
- '] -> [' + this.end.row + '/' + this.end.column + ']');
- };
-
- this.contains = function (row, column) {
- return this.compare(row, column) === 0;
- };
- this.compareRange = function (range) {
- let cmp;
- const end = range.end;
- const start = range.start;
-
- cmp = this.compare(end.row, end.column);
- if (cmp === 1) {
- cmp = this.compare(start.row, start.column);
- if (cmp === 1) {
- return 2;
- } else if (cmp === 0) {
- return 1;
- } else {
- return 0;
- }
- } else if (cmp === -1) {
- return -2;
- } else {
- cmp = this.compare(start.row, start.column);
- if (cmp === -1) {
- return -1;
- } else if (cmp === 1) {
- return 42;
- } else {
- return 0;
- }
- }
- };
- this.comparePoint = function (p) {
- return this.compare(p.row, p.column);
- };
- this.containsRange = function (range) {
- return this.comparePoint(range.start) === 0 && this.comparePoint(range.end) === 0;
- };
- this.intersects = function (range) {
- const cmp = this.compareRange(range);
- return (cmp === -1 || cmp === 0 || cmp === 1);
- };
- this.isEnd = function (row, column) {
- return this.end.row === row && this.end.column === column;
- };
- this.isStart = function (row, column) {
- return this.start.row === row && this.start.column === column;
- };
- this.setStart = function (row, column) {
- if (typeof row === 'object') {
- this.start.column = row.column;
- this.start.row = row.row;
- } else {
- this.start.row = row;
- this.start.column = column;
- }
- };
- this.setEnd = function (row, column) {
- if (typeof row === 'object') {
- this.end.column = row.column;
- this.end.row = row.row;
- } else {
- this.end.row = row;
- this.end.column = column;
- }
- };
- this.inside = function (row, column) {
- if (this.compare(row, column) === 0) {
- if (this.isEnd(row, column) || this.isStart(row, column)) {
- return false;
- } else {
- return true;
- }
- }
- return false;
- };
- this.insideStart = function (row, column) {
- if (this.compare(row, column) === 0) {
- if (this.isEnd(row, column)) {
- return false;
- } else {
- return true;
- }
- }
- return false;
- };
- this.insideEnd = function (row, column) {
- if (this.compare(row, column) === 0) {
- if (this.isStart(row, column)) {
- return false;
- } else {
- return true;
- }
- }
- return false;
- };
- this.compare = function (row, column) {
- if (!this.isMultiLine()) {
- if (row === this.start.row) {
- if (column < this.start.column) {
- return -1;
- }
- return column > this.end.column ? 1 : 0;
- }
- }
-
- if (row < this.start.row) {
- return -1;
- }
-
-
- if (row > this.end.row) {
- return 1;
- }
-
- if (this.start.row === row) {
- return column >= this.start.column ? 0 : -1;
- }
-
- if (this.end.row === row) {
- return column <= this.end.column ? 0 : 1;
- }
-
- return 0;
- };
- this.compareStart = function (row, column) {
- if (this.start.row === row && this.start.column === column) {
- return -1;
- } else {
- return this.compare(row, column);
- }
- };
- this.compareEnd = function (row, column) {
- if (this.end.row === row && this.end.column === column) {
- return 1;
- } else {
- return this.compare(row, column);
- }
- };
- this.compareInside = function (row, column) {
- if (this.end.row === row && this.end.column === column) {
- return 1;
- } else if (this.start.row === row && this.start.column === column) {
- return -1;
- } else {
- return this.compare(row, column);
- }
- };
- this.clipRows = function (firstRow, lastRow) {
- let end;
- let start;
- if (this.end.row > lastRow) {
- end = { row: lastRow + 1, column: 0 };
- } else if (this.end.row < firstRow) {
- end = { row: firstRow, column: 0 };
- }
-
- if (this.start.row > lastRow) {
- start = { row: lastRow + 1, column: 0 };
- } else if (this.start.row < firstRow) {
- start = { row: firstRow, column: 0 };
- }
- return Range.fromPoints(start || this.start, end || this.end);
- };
- this.extend = function (row, column) {
- const cmp = this.compare(row, column);
-
- if (cmp === 0) {
- return this;
- }
- let start;
- let end;
- if (cmp === -1) {
- start = { row: row, column: column };
- } else {
- end = { row: row, column: column };
- }
- return Range.fromPoints(start || this.start, end || this.end);
- };
-
- this.isEmpty = function () {
- return (this.start.row === this.end.row && this.start.column === this.end.column);
- };
- this.isMultiLine = function () {
- return (this.start.row !== this.end.row);
- };
- this.clone = function () {
- return Range.fromPoints(this.start, this.end);
- };
- this.collapseRows = function () {
- if (this.end.column === 0) {
- return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row - 1), 0);
- }
- return new Range(this.start.row, 0, this.end.row, 0);
- };
- this.toScreenRange = function (session) {
- const screenPosStart = session.documentToScreenPosition(this.start);
- const screenPosEnd = session.documentToScreenPosition(this.end);
-
- return new Range(
- screenPosStart.row, screenPosStart.column,
- screenPosEnd.row, screenPosEnd.column
- );
- };
- this.moveBy = function (row, column) {
- this.start.row += row;
- this.start.column += column;
- this.end.row += row;
- this.end.column += column;
- };
-
-}).call(Range.prototype);
-Range.fromPoints = function (start, end) {
- return new Range(start.row, start.column, end.row, end.column);
-};
-Range.comparePoints = comparePoints;
-
-Range.comparePoints = function (p1, p2) {
- return p1.row - p2.row || p1.column - p2.column;
-};
diff --git a/x-pack/legacy/plugins/searchprofiler/public/templates/_index.scss b/x-pack/legacy/plugins/searchprofiler/public/templates/_index.scss
deleted file mode 100644
index 495452735ac83..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/templates/_index.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import 'templates';
\ No newline at end of file
diff --git a/x-pack/legacy/plugins/searchprofiler/public/templates/_templates.scss b/x-pack/legacy/plugins/searchprofiler/public/templates/_templates.scss
deleted file mode 100644
index 9acd5cf32051e..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/templates/_templates.scss
+++ /dev/null
@@ -1,103 +0,0 @@
-@import '@elastic/eui/src/components/header/variables';
-@import '@elastic/eui/src/components/panel/mixins';
-
-.prfDevTool {
- height: calc(100vh - #{$euiHeaderChildSize});
- overflow: hidden;
-
- .devApp__container {
- overflow: hidden;
- flex-shrink: 1;
- }
-}
-
-.prfDevTool__container {
- display: flex;
- flex: 1 1 auto;
- padding: $euiSize;
- overflow: hidden;
-
- // SASSTODO/EUITODO/HACK: Reset font styles of headers
- h1, h2, h3, h4, h5, h6 {
- font: inherit;
- }
-}
-
-@include euiPanel('prfDevTool__main');
-
-.prfDevTool__main {
- flex: 3;
- order: 2;
- margin-left: $euiSize;
- display: flex;
- overflow: hidden;
- flex-direction: column;
-
- // Make only the tab content scroll
- search-profiler-tabs {
- flex-shrink: 0;
- }
-
- profiletree {
- overflow-y: auto;
- flex-grow: 1;
- }
-}
-
-.prfDevTool__details {
- max-width: map-get($euiBreakpoints, 's');
-}
-
-highlightdetails {
- flex-grow: 1;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- height: 100%;
-}
-
-.prfDevTool__sense {
- flex: 1;
- order: 1;
- position: relative;
- display: flex;
- flex-direction: column;
-
- > * {
- flex-shrink: 0;
- }
-
- .kuiTextInput {
- width: 100%;
- }
-
- // Ace Editor overrides
- .ace_editor {
- min-height: $euiSize * 10;
- flex-grow: 1;
- margin-bottom: $euiSize;
- margin-top: $euiSize;
- outline: solid 1px $euiColorLightShade;
- }
-
- .errorMarker {
- position: absolute;
- background: rgba($euiColorDanger, .5);
- z-index: 20;
- }
-}
-
-@include euiBreakpoint('xs', 's') {
- .prfDevTool__container {
- flex-direction: column;
- }
-
- .prfDevTool__sense,
- .prfDevTool__main {
- flex: 0 0 auto;
- }
-
- .prfDevTool__main {
- margin: $euiSize 0;
- }
-}
diff --git a/x-pack/legacy/plugins/searchprofiler/public/templates/index.html b/x-pack/legacy/plugins/searchprofiler/public/templates/index.html
deleted file mode 100644
index a2874af17817e..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/public/templates/index.html
+++ /dev/null
@@ -1,113 +0,0 @@
-
-
-
diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/index.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/index.ts
new file mode 100644
index 0000000000000..9253a0d6b1524
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/server/np_ready/index.ts
@@ -0,0 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { SearchProfilerServerPlugin } from './plugin';
+
+export const plugin = () => {
+ return new SearchProfilerServerPlugin();
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/server/lib/__tests__/check_license.js b/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.test.ts
similarity index 80%
rename from x-pack/legacy/plugins/searchprofiler/server/lib/__tests__/check_license.js
rename to x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.test.ts
index f1e19b61cbe2b..f473533fbd48a 100644
--- a/x-pack/legacy/plugins/searchprofiler/server/lib/__tests__/check_license.js
+++ b/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.test.ts
@@ -6,15 +6,14 @@
import expect from '@kbn/expect';
import { set } from 'lodash';
-import { checkLicense } from '../check_license';
+import { checkLicense } from './check_license';
-describe('check_license', function () {
-
- let mockLicenseInfo;
- beforeEach(() => mockLicenseInfo = {});
+describe('check_license', () => {
+ let mockLicenseInfo: any;
+ beforeEach(() => (mockLicenseInfo = {}));
describe('license information is not available', () => {
- beforeEach(() => mockLicenseInfo.isAvailable = () => false);
+ beforeEach(() => (mockLicenseInfo.isAvailable = () => false));
it('should set showLinks to true', () => {
expect(checkLicense(mockLicenseInfo).showAppLink).to.be(true);
@@ -37,11 +36,11 @@ describe('check_license', function () {
describe('& license is active', () => {
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true));
- it ('should set showLinks to true', () => {
+ it('should set showLinks to true', () => {
expect(checkLicense(mockLicenseInfo).showAppLink).to.be(true);
});
- it ('should set enableLinks to true', () => {
+ it('should set enableLinks to true', () => {
expect(checkLicense(mockLicenseInfo).enableAppLink).to.be(true);
});
});
@@ -49,11 +48,11 @@ describe('check_license', function () {
describe('& license is expired', () => {
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false));
- it ('should set showLinks to true', () => {
+ it('should set showLinks to true', () => {
expect(checkLicense(mockLicenseInfo).showAppLink).to.be(true);
});
- it ('should set enableLinks to false', () => {
+ it('should set enableLinks to false', () => {
expect(checkLicense(mockLicenseInfo).enableAppLink).to.be(false);
});
});
@@ -65,7 +64,7 @@ describe('check_license', function () {
describe('& license is active', () => {
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true));
- it ('should set showLinks to false', () => {
+ it('should set showLinks to false', () => {
expect(checkLicense(mockLicenseInfo).showAppLink).to.be(false);
});
});
@@ -73,7 +72,7 @@ describe('check_license', function () {
describe('& license is expired', () => {
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false));
- it ('should set showLinks to false', () => {
+ it('should set showLinks to false', () => {
expect(checkLicense(mockLicenseInfo).showAppLink).to.be(false);
});
});
diff --git a/x-pack/legacy/plugins/searchprofiler/server/lib/check_license.js b/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.ts
similarity index 67%
rename from x-pack/legacy/plugins/searchprofiler/server/lib/check_license.js
rename to x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.ts
index 1093daaafe18a..e41925da3e268 100644
--- a/x-pack/legacy/plugins/searchprofiler/server/lib/check_license.js
+++ b/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.ts
@@ -5,43 +5,46 @@
*/
import { i18n } from '@kbn/i18n';
+import { XPackInfo } from '../../../../xpack_main/server/lib/xpack_info';
-export function checkLicense(xpackLicenseInfo) {
-
+export function checkLicense(
+ xpackLicenseInfo: XPackInfo
+): { showAppLink: boolean; enableAppLink: boolean; message: string | undefined } {
if (!xpackLicenseInfo || !xpackLicenseInfo.isAvailable()) {
return {
showAppLink: true,
enableAppLink: false,
message: i18n.translate('xpack.searchProfiler.unavailableLicenseInformationMessage', {
- defaultMessage: 'Search Profiler is unavailable - license information is not available at this time.',
+ defaultMessage:
+ 'Search Profiler is unavailable - license information is not available at this time.',
}),
};
}
const isLicenseActive = xpackLicenseInfo.license.isActive();
- let message;
+ let message: string | undefined;
if (!isLicenseActive) {
message = i18n.translate('xpack.searchProfiler.licenseHasExpiredMessage', {
defaultMessage: 'Search Profiler is unavailable - license has expired.',
});
}
- if (xpackLicenseInfo.license.isOneOf([ 'trial', 'basic', 'standard', 'gold', 'platinum' ])) {
+ if (xpackLicenseInfo.license.isOneOf(['trial', 'basic', 'standard', 'gold', 'platinum'])) {
return {
showAppLink: true,
enableAppLink: isLicenseActive,
- message
+ message,
};
}
message = i18n.translate('xpack.searchProfiler.upgradeLicenseMessage', {
defaultMessage:
'Search Profiler is unavailable for the current {licenseInfo} license. Please upgrade your license.',
- values: { licenseInfo: xpackLicenseInfo.license.getType() }
+ values: { licenseInfo: xpackLicenseInfo.license.getType() },
});
return {
showAppLink: false,
enableAppLink: false,
- message
+ message,
};
}
diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/index.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/index.ts
new file mode 100644
index 0000000000000..f2c070fd44b6e
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { checkLicense } from './check_license';
diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/plugin.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/plugin.ts
new file mode 100644
index 0000000000000..e00e2829f980d
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/server/np_ready/plugin.ts
@@ -0,0 +1,38 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { CoreSetup, Plugin } from 'src/core/server';
+import { LegacySetup } from './types';
+import { checkLicense } from './lib';
+// @ts-ignore
+import { mirrorPluginStatus } from '../../../../server/lib/mirror_plugin_status';
+
+import * as profileRoute from './routes/profile';
+
+export class SearchProfilerServerPlugin implements Plugin {
+ async setup(
+ core: CoreSetup,
+ {
+ route,
+ plugins: {
+ __LEGACY: { thisPlugin, elasticsearch, xpackMain, commonRouteConfig },
+ },
+ }: LegacySetup
+ ) {
+ mirrorPluginStatus(xpackMain, thisPlugin);
+ (xpackMain as any).status.once('green', () => {
+ // Register a function that is called whenever the xpack info changes,
+ // to re-compute the license check results for this plugin
+ xpackMain.info.feature(thisPlugin.id).registerLicenseCheckResultsGenerator(checkLicense);
+ });
+
+ profileRoute.register({ elasticsearch }, route, commonRouteConfig);
+ }
+
+ async start() {}
+
+ stop(): void {}
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/routes/profile.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/routes/profile.ts
new file mode 100644
index 0000000000000..082307b5a7a2b
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/server/np_ready/routes/profile.ts
@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import Joi from 'joi';
+import { RequestShim, ServerShim, RegisterRoute } from '../types';
+
+export const handler = async (server: ServerShim, request: RequestShim) => {
+ const { callWithRequest } = server.elasticsearch.getCluster('data');
+ let parsed = request.payload.query;
+ parsed.profile = true;
+ parsed = JSON.stringify(parsed, null, 2);
+
+ const body = {
+ index: request.payload.index,
+ body: parsed,
+ };
+ try {
+ const resp = await callWithRequest(request, 'search', body);
+ return {
+ ok: true,
+ resp,
+ };
+ } catch (err) {
+ return {
+ ok: false,
+ err,
+ };
+ }
+};
+
+export const register = (server: ServerShim, route: RegisterRoute, commonConfig: any) => {
+ route({
+ path: '/api/searchprofiler/profile',
+ method: 'POST',
+ config: {
+ ...commonConfig,
+ validate: {
+ payload: Joi.object()
+ .keys({
+ query: Joi.object().required(),
+ index: Joi.string().required(),
+ type: Joi.string().optional(),
+ })
+ .required(),
+ },
+ },
+ handler: req => {
+ return handler(server, { headers: req.headers, payload: req.payload as any });
+ },
+ });
+};
diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/types.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/types.ts
new file mode 100644
index 0000000000000..7862aa386785b
--- /dev/null
+++ b/x-pack/legacy/plugins/searchprofiler/server/np_ready/types.ts
@@ -0,0 +1,33 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { ServerRoute } from 'hapi';
+import { ElasticsearchPlugin, Request } from 'src/legacy/core_plugins/elasticsearch';
+import { XPackMainPlugin } from '../../../xpack_main/xpack_main';
+
+export type RegisterRoute = (args: ServerRoute & { config: any }) => void;
+
+export interface LegacyPlugins {
+ __LEGACY: {
+ thisPlugin: any;
+ elasticsearch: ElasticsearchPlugin;
+ xpackMain: XPackMainPlugin;
+ commonRouteConfig: any;
+ };
+}
+
+export interface LegacySetup {
+ route: RegisterRoute;
+ plugins: LegacyPlugins;
+}
+
+export interface ServerShim {
+ elasticsearch: ElasticsearchPlugin;
+}
+
+export interface RequestShim extends Request {
+ payload: any;
+}
diff --git a/x-pack/legacy/plugins/searchprofiler/server/routes/profile.js b/x-pack/legacy/plugins/searchprofiler/server/routes/profile.js
deleted file mode 100644
index b1ba7527b69dd..0000000000000
--- a/x-pack/legacy/plugins/searchprofiler/server/routes/profile.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import Joi from 'joi';
-
-export function profileRoute(server, commonRouteConfig) {
-
- server.route({
- path: '/api/searchprofiler/profile',
- method: 'POST',
- config: {
- ...commonRouteConfig,
- validate: {
- payload: Joi.object().keys({
- query: Joi.object().required(),
- index: Joi.string().required(),
- type: Joi.string().optional()
- }).required() //Joi validation
- }
- },
- handler: async (request) => {
-
- const { callWithRequest } = server.plugins.elasticsearch.getCluster('data');
- let parsed = request.payload.query;
- parsed.profile = true;
- parsed = JSON.stringify(parsed, null, 2);
-
- const body = {
- index: request.payload.index,
- type: request.payload.type,
- body: parsed
- };
- try {
- const resp = await callWithRequest(request, 'search', body);
- return {
- ok: true,
- resp: resp
- };
- } catch (err) {
- return {
- ok: false,
- err: err
- };
- }
- }
- });
-
-}
diff --git a/x-pack/legacy/plugins/security/public/components/authentication_state_page/authentication_state_page.tsx b/x-pack/legacy/plugins/security/public/components/authentication_state_page/authentication_state_page.tsx
index f28696eb84063..2e02275b39611 100644
--- a/x-pack/legacy/plugins/security/public/components/authentication_state_page/authentication_state_page.tsx
+++ b/x-pack/legacy/plugins/security/public/components/authentication_state_page/authentication_state_page.tsx
@@ -5,32 +5,26 @@
*/
import { EuiIcon, EuiSpacer, EuiTitle } from '@elastic/eui';
-import React, { Component } from 'react';
+import React from 'react';
interface Props {
title: React.ReactNode;
}
-export class AuthenticationStatePage extends Component {
- public render() {
- return (
-
-
-
- {this.props.children}
-
+export const AuthenticationStatePage: React.SFC
= props => (
+
+);
diff --git a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx b/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx
index e66b37f8cfe5a..94a42166fbb9e 100644
--- a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx
+++ b/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { EuiPage, EuiPageBody, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui';
-import React, { Component } from 'react';
+import React from 'react';
import { getUserDisplayName, AuthenticatedUser } from '../../../../common/model';
import { ChangePassword } from './change_password';
import { PersonalInfo } from './personal_info';
@@ -13,28 +13,20 @@ interface Props {
user: AuthenticatedUser;
}
-export class AccountManagementPage extends Component {
- constructor(props: Props) {
- super(props);
- }
+export const AccountManagementPage: React.SFC = props => (
+
+
+
+
+ {getUserDisplayName(props.user)}
+
- public render() {
- return (
-
-
-
-
- {getUserDisplayName(this.props.user)}
-
+
-
+
-
-
-
-
-
-
- );
- }
-}
+
+
+
+
+);
diff --git a/x-pack/legacy/plugins/security/public/views/login/components/disabled_login_form/disabled_login_form.tsx b/x-pack/legacy/plugins/security/public/views/login/components/disabled_login_form/disabled_login_form.tsx
index 1b28023b6e3e0..012c16c57716e 100644
--- a/x-pack/legacy/plugins/security/public/views/login/components/disabled_login_form/disabled_login_form.tsx
+++ b/x-pack/legacy/plugins/security/public/views/login/components/disabled_login_form/disabled_login_form.tsx
@@ -5,24 +5,20 @@
*/
import { EuiPanel, EuiText } from '@elastic/eui';
-import React, { Component, ReactNode } from 'react';
+import React, { ReactNode } from 'react';
interface Props {
title: ReactNode;
message: ReactNode;
}
-export class DisabledLoginForm extends Component {
- public render() {
- return (
-
-
- {this.props.title}
-
-
- {this.props.message}
-
-
- );
- }
-}
+export const DisabledLoginForm: React.SFC = props => (
+
+
+ {props.title}
+
+
+ {props.message}
+
+
+);
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx
index 1c712f874969c..b9c28105e99d1 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx
@@ -5,7 +5,6 @@
*/
import { EuiLink, EuiText } from '@elastic/eui';
-import { Filter } from '@kbn/es-query';
import React, { useEffect, useState } from 'react';
import { createPortalNode, InPortal } from 'react-reverse-portal';
import { Query } from 'src/plugins/data/common';
@@ -30,6 +29,7 @@ import { IndexPatternsMissingPrompt } from './index_patterns_missing_prompt';
import { MapToolTip } from './map_tool_tip/map_tool_tip';
import * as i18n from './translations';
import { MapEmbeddable, SetQuery } from './types';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
interface EmbeddableMapProps {
maintainRatio?: boolean;
@@ -75,7 +75,7 @@ EmbeddableMap.displayName = 'EmbeddableMap';
export interface EmbeddedMapProps {
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
startDate: number;
endDate: number;
setQuery: SetQuery;
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx
index 7f514b0e53b71..a50cfa98fc977 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import uuid from 'uuid';
import React from 'react';
import { OutPortal, PortalNode } from 'react-reverse-portal';
@@ -28,6 +27,7 @@ import { getLayerList } from './map_config';
// @ts-ignore Missing type defs as maps moves to Typescript
import { MAP_SAVED_OBJECT_TYPE } from '../../../../maps/common/constants';
import * as i18n from './translations';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
/**
* Displays an error toast for the provided title and message
@@ -86,7 +86,7 @@ export const setupEmbeddablesAPI = (plugins: PluginsStart) => {
* @throws Error if EmbeddableFactory does not exist
*/
export const createEmbeddable = async (
- filters: Filter[],
+ filters: esFilters.Filter[],
indexPatterns: IndexPatternMapping[],
query: Query,
startDate: number,
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/__snapshots__/line_tool_tip_content.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/__snapshots__/line_tool_tip_content.test.tsx.snap
index 29656a91eff72..05f507ec3a775 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/__snapshots__/line_tool_tip_content.test.tsx.snap
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/__snapshots__/line_tool_tip_content.test.tsx.snap
@@ -24,13 +24,13 @@ exports[`LineToolTipContent renders correctly against snapshot 1`] = `
contextId="contextId"
destinationBytes={
Array [
- undefined,
+ "testPropValue",
]
}
eventId="map-line-tooltip-contextId"
sourceBytes={
Array [
- undefined,
+ "testPropValue",
]
}
/>
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap
index a6702a4ff6ed5..2a17a2aae8497 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap
@@ -10,7 +10,6 @@ exports[`PointToolTipContent renders correctly against snapshot 1`] = `
Object {
"_propertyKey": "host.name",
"_rawValue": "testPropValue",
- "getESFilters": [Function],
},
]
}
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/line_tool_tip_content.test.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/line_tool_tip_content.test.tsx
index 3f563550428f8..0bbcd4a7dcbdb 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/line_tool_tip_content.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/line_tool_tip_content.test.tsx
@@ -9,13 +9,17 @@ import toJson from 'enzyme-to-json';
import * as React from 'react';
import { LineToolTipContent } from './line_tool_tip_content';
import { FeatureProperty } from '../types';
+import { SUM_OF_DESTINATION_BYTES, SUM_OF_SOURCE_BYTES } from '../map_config';
describe('LineToolTipContent', () => {
const mockFeatureProps: FeatureProperty[] = [
{
- _propertyKey: 'host.name',
+ _propertyKey: SUM_OF_DESTINATION_BYTES,
+ _rawValue: 'testPropValue',
+ },
+ {
+ _propertyKey: SUM_OF_SOURCE_BYTES,
_rawValue: 'testPropValue',
- getESFilters: () => new Promise(resolve => setTimeout(resolve)),
},
];
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/line_tool_tip_content.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/line_tool_tip_content.tsx
index 5103c37c86c23..7cdf3a545a2d6 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/line_tool_tip_content.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/line_tool_tip_content.tsx
@@ -28,8 +28,11 @@ interface LineToolTipContentProps {
export const LineToolTipContent = React.memo(
({ contextId, featureProps }) => {
- const lineProps = featureProps.reduce>(
- (acc, f) => ({ ...acc, ...{ [f._propertyKey]: f._rawValue } }),
+ const lineProps = featureProps.reduce>(
+ (acc, f) => ({
+ ...acc,
+ ...{ [f._propertyKey]: Array.isArray(f._rawValue) ? f._rawValue : [f._rawValue] },
+ }),
{}
);
@@ -44,9 +47,9 @@ export const LineToolTipContent = React.memo(
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx
index dca68fe7ab967..567f091e78cb5 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { shallow } from 'enzyme';
+import { mount, shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
import * as React from 'react';
import { FeatureProperty } from '../types';
@@ -24,7 +24,13 @@ describe('PointToolTipContent', () => {
{
_propertyKey: 'host.name',
_rawValue: 'testPropValue',
- getESFilters: () => new Promise(resolve => setTimeout(resolve)),
+ },
+ ];
+
+ const mockFeaturePropsArrayValue: FeatureProperty[] = [
+ {
+ _propertyKey: 'host.name',
+ _rawValue: ['testPropValue1', 'testPropValue2'],
},
];
@@ -43,6 +49,32 @@ describe('PointToolTipContent', () => {
expect(toJson(wrapper)).toMatchSnapshot();
});
+ test('renders array filter correctly', () => {
+ const closeTooltip = jest.fn();
+
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="add-to-kql-host.name"]').prop('filter')).toEqual({
+ meta: {
+ alias: null,
+ disabled: false,
+ key: 'host.name',
+ negate: false,
+ params: { query: 'testPropValue1' },
+ type: 'phrase',
+ value: 'testPropValue1',
+ },
+ query: { match: { 'host.name': { query: 'testPropValue1', type: 'phrase' } } },
+ });
+ });
+
describe('#getRenderedFieldValue', () => {
test('it returns empty tag if value is empty', () => {
expect(getRenderedFieldValue('host.name', '')).toStrictEqual(getEmptyStringTag());
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/point_tool_tip_content.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/point_tool_tip_content.tsx
index cd286d82c1bf1..c747c44fd8cca 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/point_tool_tip_content.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/point_tool_tip_content.tsx
@@ -29,7 +29,7 @@ export const PointToolTipContent = React.memo(
title: sourceDestinationFieldMappings[key],
description: (
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts b/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts
index 3a13753ba25e4..10412ecdb5013 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter as ESFilterType } from '@kbn/es-query';
import { Query } from 'src/plugins/data/common';
import { TimeRange } from 'src/plugins/data/public';
import {
@@ -14,9 +13,10 @@ import {
EmbeddableFactory,
} from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public';
import { inputsModel } from '../../store/inputs';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
export interface MapEmbeddableInput extends EmbeddableInput {
- filters: ESFilterType[];
+ filters: esFilters.Filter[];
query: Query;
refreshConfig: {
isPaused: boolean;
@@ -51,8 +51,7 @@ export interface LoadFeatureProps {
export interface FeatureProperty {
_propertyKey: string;
- _rawValue: string;
- getESFilters(): Promise;
+ _rawValue: string | string[];
}
export interface FeatureGeometry {
diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx
index 13f0666b31212..6b79a6402586e 100644
--- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx
@@ -5,7 +5,7 @@
*/
import { EuiPanel } from '@elastic/eui';
-import { Filter, getEsQueryConfig } from '@kbn/es-query';
+import { getEsQueryConfig } from '@kbn/es-query';
import { getOr, isEmpty, isEqual } from 'lodash/fp';
import React from 'react';
import styled from 'styled-components';
@@ -31,6 +31,7 @@ import { TimelineRefetch } from '../timeline/refetch_timeline';
import { isCompactFooter } from '../timeline/timeline';
import { ManageTimelineContext } from '../timeline/timeline_context';
import * as i18n from './translations';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
const DEFAULT_EVENTS_VIEWER_HEIGHT = 500;
@@ -44,7 +45,7 @@ interface Props {
columns: ColumnHeader[];
dataProviders: DataProvider[];
end: number;
- filters: Filter[];
+ filters: esFilters.Filter[];
height?: number;
id: string;
indexPattern: StaticIndexPattern;
diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx
index 9483c60dcc552..5681588cb44b7 100644
--- a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { isEqual } from 'lodash/fp';
import React, { useEffect, useState, useCallback } from 'react';
import { connect } from 'react-redux';
@@ -19,6 +18,7 @@ import { ColumnHeader } from '../timeline/body/column_headers/column_header';
import { DataProvider } from '../timeline/data_providers/data_provider';
import { Sort } from '../timeline/body/sort';
import { OnChangeItemsPerPage } from '../timeline/events';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
import { EventsViewer } from './events_viewer';
import { InputsModelId } from '../../store/inputs/constants';
@@ -33,7 +33,7 @@ interface StateReduxProps {
activePage?: number;
columns: ColumnHeader[];
dataProviders?: DataProvider[];
- filters: Filter[];
+ filters: esFilters.Filter[];
isLive: boolean;
itemsPerPage?: number;
itemsPerPageOptions?: number[];
diff --git a/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.tsx b/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.tsx
index ffad36c7f9396..5df961dfceeb5 100644
--- a/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.tsx
@@ -271,7 +271,7 @@ export const DefaultFieldRendererOverflow = React.memo
+ />
)}
diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_over_time/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/matrix_over_time/index.test.tsx
index e52d44173f656..3334447739fc5 100644
--- a/x-pack/legacy/plugins/siem/public/components/matrix_over_time/index.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/matrix_over_time/index.test.tsx
@@ -12,13 +12,13 @@ import { MatrixOverTimeHistogram } from '.';
jest.mock('@elastic/eui', () => {
return {
EuiPanel: (children: JSX.Element) => <>{children}>,
- EuiLoadingContent: () =>
,
+ EuiLoadingContent: () =>
,
};
});
jest.mock('../loader', () => {
return {
- Loader: () =>
,
+ Loader: () =>
,
};
});
@@ -28,13 +28,13 @@ jest.mock('../../lib/settings/use_kibana_ui_setting', () => {
jest.mock('../header_panel', () => {
return {
- HeaderPanel: () =>
,
+ HeaderPanel: () =>
,
};
});
jest.mock('../charts/barchart', () => {
return {
- BarChart: () =>
,
+ BarChart: () =>
,
};
});
diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx b/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx
index 15e9c15744e9c..4dcdd282a12a8 100644
--- a/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx
@@ -8,6 +8,8 @@ import { EuiButton, EuiCallOut, EuiPopover, EuiPopoverTitle, EuiSpacer } from '@
import React, { useContext, useReducer, useState } from 'react';
import styled from 'styled-components';
import moment from 'moment';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { DOC_LINK_VERSION, ELASTIC_WEBSITE_URL } from 'ui/documentation_links';
import * as i18n from './translations';
import { JobsFilters, JobSummary, SiemJob } from './types';
import { hasMlAdminPermissions } from '../ml/permissions/has_ml_admin_permissions';
@@ -216,7 +218,23 @@ export const MlPopover = React.memo(() => {
iconType="alert"
size="s"
>
- {i18n.MODULE_NOT_COMPATIBLE_DESCRIPTION}
+
+
diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/translations.ts b/x-pack/legacy/plugins/siem/public/components/ml_popover/translations.ts
index 3fc9f3a484b89..442068dd0e193 100644
--- a/x-pack/legacy/plugins/siem/public/components/ml_popover/translations.ts
+++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/translations.ts
@@ -39,14 +39,6 @@ export const MODULE_NOT_COMPATIBLE_TITLE = (incompatibleJobCount: number) =>
'{incompatibleJobCount} {incompatibleJobCount, plural, =1 {job} other {jobs}} are currently unavailable',
});
-export const MODULE_NOT_COMPATIBLE_DESCRIPTION = i18n.translate(
- 'xpack.siem.components.mlPopup.moduleNotCompatibleDescription',
- {
- defaultMessage:
- 'You may be missing the required index patterns. Learn more in our documentation.',
- }
-);
-
export const START_JOB_FAILURE = i18n.translate(
'xpack.siem.components.mlPopup.errors.startJobFailureTitle',
{
diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/helpers.ts b/x-pack/legacy/plugins/siem/public/components/navigation/helpers.ts
index 68aa115c965d6..0c44b8d44c317 100644
--- a/x-pack/legacy/plugins/siem/public/components/navigation/helpers.ts
+++ b/x-pack/legacy/plugins/siem/public/components/navigation/helpers.ts
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { isEmpty } from 'lodash/fp';
import { Location } from 'history';
import { Query } from 'src/plugins/data/common';
@@ -17,6 +16,7 @@ import {
replaceStateKeyInQueryString,
getQueryStringFromLocation,
} from '../url_state/helpers';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
import { TabNavigationProps } from './tab_navigation/types';
import { SearchNavTab } from './types';
@@ -25,7 +25,7 @@ export const getSearch = (tab: SearchNavTab, urlState: TabNavigationProps): stri
if (tab && tab.urlKey != null && URL_STATE_KEYS[tab.urlKey] != null) {
return URL_STATE_KEYS[tab.urlKey].reduce(
(myLocation: Location, urlKey: KeyUrlState) => {
- let urlStateToReplace: UrlInputsModel | Query | Filter[] | Timeline | string = '';
+ let urlStateToReplace: UrlInputsModel | Query | esFilters.Filter[] | Timeline | string = '';
if (urlKey === CONSTANTS.appQuery && urlState.query != null) {
if (urlState.query.query === '') {
diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/types.ts b/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/types.ts
index 1d5ebf2097974..856651e6f97dc 100644
--- a/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/types.ts
+++ b/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/types.ts
@@ -4,12 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
-import { Query } from 'src/plugins/data/common';
import { UrlInputsModel } from '../../../store/inputs/model';
import { CONSTANTS } from '../../url_state/constants';
import { Timeline } from '../../url_state/types';
import { HostsTableType } from '../../../store/hosts/model';
+import { esFilters, Query } from '../../../../../../../../src/plugins/data/public';
import { SiemNavigationComponentProps } from '../types';
@@ -18,7 +17,7 @@ export interface TabNavigationProps extends SiemNavigationComponentProps {
pageName: string;
tabName: HostsTableType | undefined;
[CONSTANTS.appQuery]?: Query;
- [CONSTANTS.filters]?: Filter[];
+ [CONSTANTS.filters]?: esFilters.Filter[];
[CONSTANTS.savedQuery]?: string;
[CONSTANTS.timerange]: UrlInputsModel;
[CONSTANTS.timeline]: Timeline;
diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx
index c96d25f0d11f0..ba99a92f66b49 100644
--- a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx
@@ -22,7 +22,7 @@ import {
} from '../../store/timeline/actions';
import { OpenTimeline } from './open_timeline';
import { OPEN_TIMELINE_CLASS_NAME, queryTimelineById, dispatchUpdateTimeline } from './helpers';
-import { OpenTimelineModal } from './open_timeline_modal/open_timeline_modal';
+import { OpenTimelineModalBody } from './open_timeline_modal/open_timeline_modal_body';
import {
DeleteTimelines,
EuiSearchBarQuery,
@@ -281,7 +281,7 @@ export const StatefulOpenTimelineComponent = React.memo(
totalSearchResultsCount={totalCount}
/>
) : (
- ({
+ useApolloClient: () => ({}),
+}));
-describe('OpenTimelineModalButton', () => {
+describe('OpenTimelineModal', () => {
const theme = () => ({ eui: euiDarkVars, darkMode: true });
- test('it renders the expected button text', async () => {
+ test('it renders the expected modal', async () => {
const wrapper = mount(
-
-
-
-
-
- );
-
- await wait();
-
- wrapper.update();
-
- expect(
- wrapper
- .find('[data-test-subj="open-timeline-button"]')
- .first()
- .text()
- ).toEqual(i18n.OPEN_TIMELINE);
- });
-
- describe('statefulness', () => {
- test('defaults showModal to false', async () => {
- const wrapper = mount(
-
-
-
-
-
-
-
- );
-
- await wait();
-
- wrapper.update();
-
- expect(wrapper.find('div[data-test-subj="open-timeline-modal"].euiModal').length).toEqual(0);
- });
-
- test('it sets showModal to true when the button is clicked', async () => {
- const wrapper = mount(
-
-
-
-
-
-
-
- );
-
- await wait();
-
- wrapper
- .find('[data-test-subj="open-timeline-button"]')
- .first()
- .simulate('click');
-
- wrapper.update();
-
- expect(wrapper.find('div[data-test-subj="open-timeline-modal"].euiModal').length).toEqual(1);
- });
-
- test('it does NOT render the modal when showModal is false', async () => {
- const wrapper = mount(
+
-
+
- );
-
- await wait();
-
- wrapper.update();
-
- expect(
- wrapper
- .find('[data-test-subj="open-timeline-modal"]')
- .first()
- .exists()
- ).toBe(false);
- });
-
- test('it renders the modal when showModal is true', async () => {
- const wrapper = mount(
-
-
-
-
-
-
-
- );
-
- await wait();
-
- wrapper.update();
-
- wrapper
- .find('[data-test-subj="open-timeline-button"]')
- .first()
- .simulate('click');
-
- expect(
- wrapper
- .find('[data-test-subj="open-timeline-modal"]')
- .first()
- .exists()
- ).toBe(true);
- });
- });
-
- describe('onToggle prop', () => {
- test('it still correctly updates the showModal state if `onToggle` is not provided as a prop', async () => {
- const wrapper = mount(
-
-
-
-
-
-
-
- );
-
- await wait();
-
- wrapper
- .find('[data-test-subj="open-timeline-button"]')
- .first()
- .simulate('click');
-
- wrapper.update();
-
- expect(wrapper.find('div[data-test-subj="open-timeline-modal"].euiModal').length).toEqual(1);
- });
-
- test('it invokes the optional onToggle function provided as a prop when the open timeline button is clicked', async () => {
- const onToggle = jest.fn();
- const wrapper = mount(
-
-
-
-
-
-
-
- );
-
- await wait();
+
+ );
- wrapper
- .find('[data-test-subj="open-timeline-button"]')
- .first()
- .simulate('click');
+ await wait();
- wrapper.update();
+ wrapper.update();
- expect(onToggle).toBeCalled();
- });
+ expect(wrapper.find('div[data-test-subj="open-timeline-modal"].euiModal').length).toEqual(1);
});
});
diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.tsx
index e8242237cd2c8..cd89eb8aad6f4 100644
--- a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.tsx
@@ -4,80 +4,42 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiButtonEmpty, EuiModal, EuiOverlayMask } from '@elastic/eui';
-import React, { useCallback, useState } from 'react';
+import { EuiModal, EuiOverlayMask } from '@elastic/eui';
+import React from 'react';
-import { ApolloConsumer } from 'react-apollo';
+import { useApolloClient } from '../../../utils/apollo_context';
import * as i18n from '../translations';
import { StatefulOpenTimeline } from '..';
-export interface OpenTimelineModalButtonProps {
- /**
- * An optional callback that if specified, will perform arbitrary IO before
- * this component updates its internal toggle state.
- */
- onToggle?: () => void;
+export interface OpenTimelineModalProps {
+ onClose: () => void;
}
const DEFAULT_SEARCH_RESULTS_PER_PAGE = 10;
const OPEN_TIMELINE_MODAL_WIDTH = 1000; // px
-/**
- * Renders a button that when clicked, displays the `Open Timelines` modal
- */
-export const OpenTimelineModalButton = React.memo(({ onToggle }) => {
- const [showModal, setShowModal] = useState(false);
-
- /** shows or hides the `Open Timeline` modal */
- const openModal = useCallback(() => {
- if (onToggle != null) {
- onToggle();
- }
- setShowModal(true);
- }, [onToggle]);
+export const OpenTimelineModal = React.memo(({ onClose }) => {
+ const apolloClient = useApolloClient();
- const closeModal = useCallback(() => {
- if (onToggle != null) {
- onToggle();
- }
- setShowModal(false);
- }, [onToggle]);
+ if (!apolloClient) return null;
return (
-
- {client => (
- <>
-
- {i18n.OPEN_TIMELINE}
-
-
- {showModal && (
-
-
-
-
-
- )}
- >
- )}
-
+
+
+
+
+
);
});
-OpenTimelineModalButton.displayName = 'OpenTimelineModalButton';
+OpenTimelineModal.displayName = 'OpenTimelineModal';
diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx
similarity index 97%
rename from x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal.test.tsx
rename to x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx
index 3a5bf4be5d72f..4237caf8f3c51 100644
--- a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx
@@ -14,7 +14,7 @@ import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timeli
import { OpenTimelineResult } from '../types';
import { TimelinesTableProps } from '../timelines_table';
import { mockTimelineResults } from '../../../mock/timeline_results';
-import { OpenTimelineModal } from './open_timeline_modal';
+import { OpenTimelineModalBody } from './open_timeline_modal_body';
import { DEFAULT_SORT_DIRECTION, DEFAULT_SORT_FIELD } from '../constants';
jest.mock('../../../lib/settings/use_kibana_ui_setting');
@@ -32,7 +32,7 @@ describe('OpenTimelineModal', () => {
test('it renders the title row', () => {
const wrapper = mountWithIntl(
- {
test('it renders the search row', () => {
const wrapper = mountWithIntl(
- {
test('it renders the timelines table', () => {
const wrapper = mountWithIntl(
- {
test('it shows extended columns and actions when onDeleteSelected and deleteTimelines are specified', () => {
const wrapper = mountWithIntl(
- {
test('it does NOT show extended columns and actions when is onDeleteSelected undefined and deleteTimelines is specified', () => {
const wrapper = mountWithIntl(
- {
test('it does NOT show extended columns and actions when is onDeleteSelected provided and deleteTimelines is undefined', () => {
const wrapper = mountWithIntl(
- {
test('it does NOT show extended columns and actions when both onDeleteSelected and deleteTimelines are undefined', () => {
const wrapper = mountWithIntl(
- (
+export const OpenTimelineModalBody = pure(
({
deleteTimelines,
defaultPageSize,
@@ -91,4 +91,4 @@ export const OpenTimelineModal = pure(
)
);
-OpenTimelineModal.displayName = 'OpenTimelineModal';
+OpenTimelineModalBody.displayName = 'OpenTimelineModalBody';
diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.test.tsx
new file mode 100644
index 0000000000000..a5e436c73f93b
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.test.tsx
@@ -0,0 +1,71 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
+import { mount } from 'enzyme';
+import * as React from 'react';
+import { MockedProvider } from 'react-apollo/test-utils';
+import { ThemeProvider } from 'styled-components';
+
+import { wait } from '../../../lib/helpers';
+import { TestProviderWithoutDragAndDrop } from '../../../mock/test_providers';
+import { mockOpenTimelineQueryResults } from '../../../mock/timeline_results';
+import * as i18n from '../translations';
+
+import { OpenTimelineModalButton } from './open_timeline_modal_button';
+
+jest.mock('../../../lib/settings/use_kibana_ui_setting');
+
+describe('OpenTimelineModalButton', () => {
+ const theme = () => ({ eui: euiDarkVars, darkMode: true });
+
+ test('it renders the expected button text', async () => {
+ const wrapper = mount(
+
+
+
+
+
+ );
+
+ await wait();
+
+ wrapper.update();
+
+ expect(
+ wrapper
+ .find('[data-test-subj="open-timeline-button"]')
+ .first()
+ .text()
+ ).toEqual(i18n.OPEN_TIMELINE);
+ });
+
+ describe('onClick prop', () => {
+ test('it invokes onClick function provided as a prop when the button is clicked', async () => {
+ const onClick = jest.fn();
+ const wrapper = mount(
+
+
+
+
+
+
+
+ );
+
+ await wait();
+
+ wrapper
+ .find('[data-test-subj="open-timeline-button"]')
+ .first()
+ .simulate('click');
+
+ wrapper.update();
+
+ expect(onClick).toBeCalled();
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.tsx
new file mode 100644
index 0000000000000..373868a769d22
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.tsx
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiButtonEmpty } from '@elastic/eui';
+import React from 'react';
+
+import * as i18n from '../translations';
+
+export interface OpenTimelineModalButtonProps {
+ onClick: () => void;
+}
+
+export const OpenTimelineModalButton = React.memo(({ onClick }) => (
+
+ {i18n.OPEN_TIMELINE}
+
+));
+
+OpenTimelineModalButton.displayName = 'OpenTimelineModalButton';
diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/index.test.tsx
index 44da23153fe15..6cf56ad6a770f 100644
--- a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/index.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/index.test.tsx
@@ -241,7 +241,7 @@ describe('TimelinesTable', () => {
expect(
wrapper
- .find('[id="customizablePagination"]')
+ .find('EuiTablePagination EuiPopover')
.first()
.exists()
).toBe(true);
@@ -272,7 +272,7 @@ describe('TimelinesTable', () => {
expect(
wrapper
- .find('[id="customizablePagination"]')
+ .find('EuiTablePagination EuiPopover')
.first()
.exists()
).toBe(false);
@@ -305,7 +305,7 @@ describe('TimelinesTable', () => {
expect(
wrapper
- .find('[id="customizablePagination"]')
+ .find('EuiTablePagination EuiPopover')
.first()
.text()
).toEqual('Rows per page: 123');
diff --git a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.test.tsx
index 34e2bc01a4ea7..ed614d79174f0 100644
--- a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.test.tsx
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { mount, shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
import * as React from 'react';
@@ -13,9 +12,10 @@ import { apolloClientObservable, mockGlobalState, TestProviders } from '../../..
import { createStore, State } from '../../../store';
import { siemFilterManager } from '../../search_bar';
import { AddFilterToGlobalSearchBar } from '.';
+import { esFilters } from '../../../../../../../../src/plugins/data/public';
interface MockSiemFilterManager {
- addFilters: (filters: Filter[]) => void;
+ addFilters: (filters: esFilters.Filter[]) => void;
}
const mockSiemFilterManager: MockSiemFilterManager = siemFilterManager as MockSiemFilterManager;
jest.mock('../../search_bar', () => ({
diff --git a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.tsx
index 6f3b56417173c..6e1e6545e5534 100644
--- a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.tsx
@@ -5,12 +5,12 @@
*/
import { EuiIcon, EuiPanel, EuiToolTip } from '@elastic/eui';
-import { Filter } from '@kbn/es-query';
import React from 'react';
import styled from 'styled-components';
import { WithHoverActions } from '../../with_hover_actions';
import { siemFilterManager } from '../../search_bar';
+import { esFilters } from '../../../../../../../../src/plugins/data/public';
import * as i18n from './translations';
@@ -18,7 +18,7 @@ export * from './helpers';
interface OwnProps {
children: JSX.Element;
- filter: Filter;
+ filter: esFilters.Filter;
onFilterAdded?: () => void;
}
diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/index.tsx
index 40460f81fa83c..1f502635a8de4 100644
--- a/x-pack/legacy/plugins/siem/public/components/page/network/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/page/network/index.tsx
@@ -9,3 +9,4 @@ export { KpiNetworkComponent } from './kpi_network';
export { NetworkDnsTable } from './network_dns_table';
export { NetworkTopCountriesTable } from './network_top_countries_table';
export { NetworkTopNFlowTable } from './network_top_n_flow_table';
+export { NetworkHttpTable } from './network_http_table';
diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/kpi_network/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/kpi_network/index.tsx
index 898990c4497f7..d59d4ccd60c60 100644
--- a/x-pack/legacy/plugins/siem/public/components/page/network/kpi_network/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/page/network/kpi_network/index.tsx
@@ -39,7 +39,7 @@ interface KpiNetworkProps {
export const fieldTitleChartMapping: Readonly = [
{
key: 'UniqueIps',
- index: 4,
+ index: 2,
fields: [
{
key: 'uniqueSourcePrivateIps',
@@ -92,7 +92,7 @@ const fieldTitleMatrixMapping: Readonly = [
},
{
key: 'uniqueFlowId',
- index: 2,
+ index: 3,
fields: [
{
key: 'uniqueFlowId',
@@ -103,7 +103,7 @@ const fieldTitleMatrixMapping: Readonly = [
},
{
key: 'tlsHandshakes',
- index: 3,
+ index: 4,
fields: [
{
key: 'tlsHandshakes',
diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/kpi_network/mock.ts b/x-pack/legacy/plugins/siem/public/components/page/network/kpi_network/mock.ts
index e06bb1477bc7f..38d73d5a5895b 100644
--- a/x-pack/legacy/plugins/siem/public/components/page/network/kpi_network/mock.ts
+++ b/x-pack/legacy/plugins/siem/public/components/page/network/kpi_network/mock.ts
@@ -223,7 +223,7 @@ export const mockEnableChartsData = {
from: 1560578400000,
grow: 2,
id: 'statItem',
- index: 4,
+ index: 2,
statKey: 'UniqueIps',
to: 1560837600000,
narrowDateRange: mockNarrowDateRange,
diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap
new file mode 100644
index 0000000000000..dfc1b2cf64e38
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,102 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NetworkHttp Table Component rendering it renders the default NetworkHttp table 1`] = `
+
+`;
diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/columns.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/columns.tsx
new file mode 100644
index 0000000000000..6a47a58c85f31
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/columns.tsx
@@ -0,0 +1,113 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import numeral from '@elastic/numeral';
+import { NetworkHttpEdges, NetworkHttpFields, NetworkHttpItem } from '../../../../graphql/types';
+import { escapeDataProviderId } from '../../../drag_and_drop/helpers';
+import { getEmptyTagValue } from '../../../empty_value';
+import { IPDetailsLink } from '../../../links';
+import { Columns } from '../../../paginated_table';
+
+import * as i18n from './translations';
+import { getRowItemDraggable, getRowItemDraggables } from '../../../tables/helpers';
+export type NetworkHttpColumns = [
+ Columns,
+ Columns,
+ Columns,
+ Columns,
+ Columns,
+ Columns,
+ Columns
+];
+
+export const getNetworkHttpColumns = (tableId: string): NetworkHttpColumns => [
+ {
+ name: i18n.METHOD,
+ render: ({ node: { methods, path } }) => {
+ return Array.isArray(methods) && methods.length > 0
+ ? getRowItemDraggables({
+ attrName: 'http.request.method',
+ displayCount: 3,
+ idPrefix: escapeDataProviderId(`${tableId}-table-methods-${path}`),
+ rowItems: methods,
+ })
+ : getEmptyTagValue();
+ },
+ },
+ {
+ name: i18n.DOMAIN,
+ render: ({ node: { domains, path } }) =>
+ Array.isArray(domains) && domains.length > 0
+ ? getRowItemDraggables({
+ attrName: 'url.domain',
+ displayCount: 3,
+ idPrefix: escapeDataProviderId(`${tableId}-table-domains-${path}`),
+ rowItems: domains,
+ })
+ : getEmptyTagValue(),
+ },
+ {
+ field: `node.${NetworkHttpFields.path}`,
+ name: i18n.PATH,
+ render: path =>
+ path != null
+ ? getRowItemDraggable({
+ attrName: 'url.path',
+ idPrefix: escapeDataProviderId(`${tableId}-table-path-${path}`),
+ rowItem: path,
+ })
+ : getEmptyTagValue(),
+ },
+ {
+ name: i18n.STATUS,
+ render: ({ node: { statuses, path } }) =>
+ Array.isArray(statuses) && statuses.length > 0
+ ? getRowItemDraggables({
+ attrName: 'http.response.status_code',
+ displayCount: 3,
+ idPrefix: escapeDataProviderId(`${tableId}-table-statuses-${path}`),
+ rowItems: statuses,
+ })
+ : getEmptyTagValue(),
+ },
+ {
+ name: i18n.LAST_HOST,
+ render: ({ node: { lastHost, path } }) =>
+ lastHost != null
+ ? getRowItemDraggable({
+ attrName: 'host.name',
+ idPrefix: escapeDataProviderId(`${tableId}-table-lastHost-${path}`),
+ rowItem: lastHost,
+ })
+ : getEmptyTagValue(),
+ },
+ {
+ name: i18n.LAST_SOURCE_IP,
+ render: ({ node: { lastSourceIp, path } }) =>
+ lastSourceIp != null
+ ? getRowItemDraggable({
+ attrName: 'source.ip',
+ idPrefix: escapeDataProviderId(`${tableId}-table-lastSourceIp-${path}`),
+ rowItem: lastSourceIp,
+ render: () => ,
+ })
+ : getEmptyTagValue(),
+ },
+ {
+ align: 'right',
+ field: `node.${NetworkHttpFields.requestCount}`,
+ name: i18n.REQUESTS,
+ sortable: true,
+ render: requestCount => {
+ if (requestCount != null) {
+ return numeral(requestCount).format('0,000');
+ } else {
+ return getEmptyTagValue();
+ }
+ },
+ },
+];
diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.test.tsx
new file mode 100644
index 0000000000000..277e136d776fa
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.test.tsx
@@ -0,0 +1,104 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { mount, shallow } from 'enzyme';
+import toJson from 'enzyme-to-json';
+import { getOr } from 'lodash/fp';
+import * as React from 'react';
+import { MockedProvider } from 'react-apollo/test-utils';
+import { Provider as ReduxStoreProvider } from 'react-redux';
+
+import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock';
+import { createStore, networkModel, State } from '../../../../store';
+
+import { NetworkHttpTable } from '.';
+import { mockData } from './mock';
+
+jest.mock('../../../../lib/settings/use_kibana_ui_setting');
+
+describe('NetworkHttp Table Component', () => {
+ const loadPage = jest.fn();
+ const state: State = mockGlobalState;
+
+ let store = createStore(state, apolloClientObservable);
+
+ beforeEach(() => {
+ store = createStore(state, apolloClientObservable);
+ });
+
+ describe('rendering', () => {
+ test('it renders the default NetworkHttp table', () => {
+ const wrapper = shallow(
+
+
+
+ );
+
+ expect(toJson(wrapper)).toMatchSnapshot();
+ });
+ });
+
+ describe('Sorting', () => {
+ test('when you click on the column header, you should show the sorting icon', () => {
+ const wrapper = mount(
+
+
+
+
+
+ );
+
+ expect(store.getState().network.page.queries!.http.sort).toEqual({
+ direction: 'desc',
+ });
+
+ wrapper
+ .find('.euiTable thead tr th button')
+ .first()
+ .simulate('click');
+
+ wrapper.update();
+
+ expect(store.getState().network.page.queries!.http.sort).toEqual({
+ direction: 'asc',
+ });
+ expect(
+ wrapper
+ .find('.euiTable thead tr th button')
+ .first()
+ .find('svg')
+ ).toBeTruthy();
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx
new file mode 100644
index 0000000000000..71807280ebcb4
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx
@@ -0,0 +1,149 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { connect } from 'react-redux';
+import { compose } from 'redux';
+import { ActionCreator } from 'typescript-fsa';
+
+import { networkActions } from '../../../../store/actions';
+import {
+ NetworkHttpEdges,
+ NetworkHttpFields,
+ NetworkHttpSortField,
+} from '../../../../graphql/types';
+import { networkModel, networkSelectors, State } from '../../../../store';
+import { Criteria, ItemsPerRow, PaginatedTable } from '../../../paginated_table';
+
+import { getNetworkHttpColumns } from './columns';
+import * as i18n from './translations';
+
+interface OwnProps {
+ data: NetworkHttpEdges[];
+ fakeTotalCount: number;
+ id: string;
+ isInspect: boolean;
+ loading: boolean;
+ loadPage: (newActivePage: number) => void;
+ showMorePagesIndicator: boolean;
+ totalCount: number;
+ type: networkModel.NetworkType;
+}
+
+interface NetworkHttpTableReduxProps {
+ activePage: number;
+ limit: number;
+ sort: NetworkHttpSortField;
+}
+
+interface NetworkHttpTableDispatchProps {
+ updateNetworkTable: ActionCreator<{
+ networkType: networkModel.NetworkType;
+ tableType: networkModel.AllNetworkTables;
+ updates: networkModel.TableUpdates;
+ }>;
+}
+
+type NetworkHttpTableProps = OwnProps & NetworkHttpTableReduxProps & NetworkHttpTableDispatchProps;
+
+const rowItems: ItemsPerRow[] = [
+ {
+ text: i18n.ROWS_5,
+ numberOfRow: 5,
+ },
+ {
+ text: i18n.ROWS_10,
+ numberOfRow: 10,
+ },
+];
+
+const NetworkHttpTableComponent = React.memo(
+ ({
+ activePage,
+ data,
+ fakeTotalCount,
+ id,
+ isInspect,
+ limit,
+ loading,
+ loadPage,
+ showMorePagesIndicator,
+ sort,
+ totalCount,
+ type,
+ updateNetworkTable,
+ }) => {
+ const onChange = (criteria: Criteria, tableType: networkModel.HttpTableType) => {
+ if (criteria.sort != null && criteria.sort.direction !== sort.direction) {
+ updateNetworkTable({
+ networkType: type,
+ tableType,
+ updates: {
+ sort: {
+ direction: criteria.sort.direction,
+ },
+ },
+ });
+ }
+ };
+ const tableType =
+ type === networkModel.NetworkType.page
+ ? networkModel.NetworkTableType.http
+ : networkModel.IpDetailsTableType.http;
+ return (
+ loadPage(newActivePage)}
+ onChange={criteria => onChange(criteria, tableType)}
+ pageOfItems={data}
+ showMorePagesIndicator={showMorePagesIndicator}
+ sorting={{ field: `node.${NetworkHttpFields.requestCount}`, direction: sort.direction }}
+ totalCount={fakeTotalCount}
+ updateActivePage={newPage =>
+ updateNetworkTable({
+ networkType: type,
+ tableType,
+ updates: { activePage: newPage },
+ })
+ }
+ updateLimitPagination={newLimit =>
+ updateNetworkTable({
+ networkType: type,
+ tableType,
+ updates: { limit: newLimit },
+ })
+ }
+ />
+ );
+ }
+);
+
+NetworkHttpTableComponent.displayName = 'NetworkHttpTableComponent';
+
+const makeMapStateToProps = () => {
+ const getNetworkHttpSelector = networkSelectors.httpSelector();
+ const mapStateToProps = (state: State, { type }: OwnProps) => getNetworkHttpSelector(state, type);
+ return mapStateToProps;
+};
+
+export const NetworkHttpTable = compose>(
+ connect(
+ makeMapStateToProps,
+ {
+ updateNetworkTable: networkActions.updateNetworkTable,
+ }
+ )
+)(NetworkHttpTableComponent);
diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/mock.ts b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/mock.ts
new file mode 100644
index 0000000000000..ed9b00ba8e49e
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/mock.ts
@@ -0,0 +1,88 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { NetworkHttpData } from '../../../../graphql/types';
+
+export const mockData: { NetworkHttp: NetworkHttpData } = {
+ NetworkHttp: {
+ edges: [
+ {
+ node: {
+ _id: '/computeMetadata/v1/instance/virtual-clock/drift-token',
+ domains: ['metadata.google.internal'],
+ methods: ['get'],
+ statuses: [],
+ lastHost: 'suricata-iowa',
+ lastSourceIp: '10.128.0.21',
+ path: '/computeMetadata/v1/instance/virtual-clock/drift-token',
+ requestCount: 1440,
+ },
+ cursor: {
+ value: '/computeMetadata/v1/instance/virtual-clock/drift-token',
+ tiebreaker: null,
+ },
+ },
+ {
+ node: {
+ _id: '/computeMetadata/v1/',
+ domains: ['metadata.google.internal'],
+ methods: ['get'],
+ statuses: ['200'],
+ lastHost: 'suricata-iowa',
+ lastSourceIp: '10.128.0.21',
+ path: '/computeMetadata/v1/',
+ requestCount: 1020,
+ },
+ cursor: {
+ value: '/computeMetadata/v1/',
+ tiebreaker: null,
+ },
+ },
+ {
+ node: {
+ _id: '/computeMetadata/v1/instance/network-interfaces/',
+ domains: ['metadata.google.internal'],
+ methods: ['get'],
+ statuses: [],
+ lastHost: 'suricata-iowa',
+ lastSourceIp: '10.128.0.21',
+ path: '/computeMetadata/v1/instance/network-interfaces/',
+ requestCount: 960,
+ },
+ cursor: {
+ value: '/computeMetadata/v1/instance/network-interfaces/',
+ tiebreaker: null,
+ },
+ },
+ {
+ node: {
+ _id: '/downloads/ca_setup.exe',
+ domains: ['www.oxid.it'],
+ methods: ['get'],
+ statuses: ['200'],
+ lastHost: 'jessie',
+ lastSourceIp: '10.0.2.15',
+ path: '/downloads/ca_setup.exe',
+ requestCount: 3,
+ },
+ cursor: {
+ value: '/downloads/ca_setup.exe',
+ tiebreaker: null,
+ },
+ },
+ ],
+ inspect: {
+ dsl: [''],
+ response: [''],
+ },
+ pageInfo: {
+ activePage: 0,
+ fakeTotalCount: 4,
+ showMorePagesIndicator: false,
+ },
+ totalCount: 4,
+ },
+};
diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/translations.ts b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/translations.ts
new file mode 100644
index 0000000000000..c891a7c75fc3c
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/translations.ts
@@ -0,0 +1,57 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { i18n } from '@kbn/i18n';
+
+export const HTTP_REQUESTS = i18n.translate('xpack.siem.networkHttpTable.title', {
+ defaultMessage: 'HTTP Requests',
+});
+
+export const UNIT = (totalCount: number) =>
+ i18n.translate('xpack.siem.networkHttpTable.unit', {
+ values: { totalCount },
+ defaultMessage: `{totalCount, plural, =1 {request} other {requests}}`,
+ });
+
+export const METHOD = i18n.translate('xpack.siem.networkHttpTable.column.methodTitle', {
+ defaultMessage: 'Method',
+});
+export const DOMAIN = i18n.translate('xpack.siem.networkHttpTable.column.domainTitle', {
+ defaultMessage: 'Domain',
+});
+
+export const PATH = i18n.translate('xpack.siem.networkHttpTable.column.pathTitle', {
+ defaultMessage: 'Path',
+});
+
+export const STATUS = i18n.translate('xpack.siem.networkHttpTable.column.statusTitle', {
+ defaultMessage: 'Status',
+});
+
+export const LAST_HOST = i18n.translate('xpack.siem.networkHttpTable.column.lastHostTitle', {
+ defaultMessage: 'Last host',
+});
+
+export const LAST_SOURCE_IP = i18n.translate(
+ 'xpack.siem.networkHttpTable.column.lastSourceIpTitle',
+ {
+ defaultMessage: 'Last source Ip',
+ }
+);
+
+export const REQUESTS = i18n.translate('xpack.siem.networkHttpTable.column.requestsTitle', {
+ defaultMessage: 'Requests',
+});
+
+export const ROWS_5 = i18n.translate('xpack.siem.networkHttpTable.rows', {
+ values: { numRows: 5 },
+ defaultMessage: '{numRows} {numRows, plural, =0 {rows} =1 {row} other {rows}}',
+});
+
+export const ROWS_10 = i18n.translate('xpack.siem.networkHttpTable.rows', {
+ values: { numRows: 10 },
+ defaultMessage: '{numRows} {numRows, plural, =0 {rows} =1 {row} other {rows}}',
+});
diff --git a/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx
index 4de64c6b32aa9..646d003051e83 100644
--- a/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx
@@ -23,6 +23,7 @@ import { Direction } from '../../graphql/types';
import { AuthTableColumns } from '../page/hosts/authentications_table';
import { HostsTableColumns } from '../page/hosts/hosts_table';
import { NetworkDnsColumns } from '../page/network/network_dns_table/columns';
+import { NetworkHttpColumns } from '../page/network/network_http_table/columns';
import {
NetworkTopNFlowColumns,
NetworkTopNFlowColumnsIpDetails,
@@ -72,6 +73,7 @@ declare type BasicTableColumns =
| HostsTableColumns
| HostsTableColumnsTest
| NetworkDnsColumns
+ | NetworkHttpColumns
| NetworkTopCountriesColumns
| NetworkTopCountriesColumnsIpDetails
| NetworkTopNFlowColumns
diff --git a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx
index 2ee93471b62d0..c885d001542e5 100644
--- a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { getOr, isEqual, set } from 'lodash/fp';
import React, { memo, useEffect, useCallback, useMemo } from 'react';
import { connect } from 'react-redux';
@@ -17,6 +16,7 @@ import { TimeRange, Query } from 'src/plugins/data/common/types';
import { SavedQuery } from 'src/legacy/core_plugins/data/public';
import { OnTimeChangeProps } from '@elastic/eui';
+import { npStart } from 'ui/new_platform';
import { start as data } from '../../../../../../../src/legacy/core_plugins/data/public/legacy';
import { inputsActions } from '../../store/inputs';
@@ -36,15 +36,15 @@ import {
toStrSelector,
} from './selectors';
import { timelineActions, hostsActions, networkActions } from '../../store/actions';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
const {
ui: { SearchBar },
- filter,
search,
timefilter,
} = data;
-export const siemFilterManager = filter.filterManager;
+export const siemFilterManager = npStart.plugins.data.query.filterManager;
export const savedQueryService = search.services.savedQueryService;
interface SiemSearchBarRedux {
@@ -67,7 +67,7 @@ interface SiemSearchBarDispatch {
id: InputsModelId;
savedQuery: SavedQuery | undefined;
}) => void;
- setSearchBarFilter: ({ id, filters }: { id: InputsModelId; filters: Filter[] }) => void;
+ setSearchBarFilter: ({ id, filters }: { id: InputsModelId; filters: esFilters.Filter[] }) => void;
}
interface SiemSearchBarProps {
@@ -313,7 +313,7 @@ SearchBarComponent.displayName = 'SiemSearchBar';
interface UpdateReduxSearchBar extends OnTimeChangeProps {
id: InputsModelId;
- filters?: Filter[];
+ filters?: esFilters.Filter[];
query?: Query;
savedQuery?: SavedQuery;
resetSavedQuery?: boolean;
@@ -397,7 +397,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
updateSearch: dispatchUpdateSearch(dispatch),
setSavedQuery: ({ id, savedQuery }: { id: InputsModelId; savedQuery: SavedQuery | undefined }) =>
dispatch(inputsActions.setSavedQuery({ id, savedQuery })),
- setSearchBarFilter: ({ id, filters }: { id: InputsModelId; filters: Filter[] }) =>
+ setSearchBarFilter: ({ id, filters }: { id: InputsModelId; filters: esFilters.Filter[] }) =>
dispatch(inputsActions.setSearchBarFilter({ id, filters })),
});
diff --git a/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.tsx b/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.tsx
index 4859dc0d05556..6359063798ba8 100644
--- a/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.tsx
@@ -54,7 +54,7 @@ export interface SkeletonRowProps extends CellProps, RowProps {
export const SkeletonRow = React.memo(
({ cellColor, cellCount = 4, cellMargin, rowHeight, rowPadding, style }) => {
const cells = [...Array(cellCount)].map((_, i) => (
- |
+ |
));
return (
diff --git a/x-pack/legacy/plugins/siem/public/components/stat_items/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/stat_items/index.test.tsx
index 8453ec1cfb5d7..ed3eaa6cf1e91 100644
--- a/x-pack/legacy/plugins/siem/public/components/stat_items/index.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/stat_items/index.test.tsx
@@ -38,11 +38,11 @@ const from = new Date('2019-06-15T06:00:00.000Z').valueOf();
const to = new Date('2019-06-18T06:00:00.000Z').valueOf();
jest.mock('../charts/areachart', () => {
- return { AreaChart: () =>
};
+ return { AreaChart: () =>
};
});
jest.mock('../charts/barchart', () => {
- return { BarChart: () =>
};
+ return { BarChart: () =>
};
});
describe('Stat Items Component', () => {
diff --git a/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx b/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx
index 66afd78fd0321..caeb29fc6de7d 100644
--- a/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx
@@ -55,13 +55,18 @@ interface UpdateReduxTime extends OnTimeChangeProps {
timelineId?: string;
}
+interface ReturnUpdateReduxTime {
+ kqlHaveBeenUpdated: boolean;
+}
+
export type DispatchUpdateReduxTime = ({
end,
id,
isQuickSelection,
+ kql,
start,
timelineId,
-}: UpdateReduxTime) => void;
+}: UpdateReduxTime) => ReturnUpdateReduxTime;
interface SuperDatePickerDispatchProps {
setDuration: ({ id, duration }: { id: InputsModelId; duration: number }) => void;
@@ -105,7 +110,7 @@ export const SuperDatePickerComponent = React.memo(
);
const onRefresh = useCallback(
({ start: newStart, end: newEnd }: OnRefreshProps): void => {
- updateReduxTime({
+ const { kqlHaveBeenUpdated } = updateReduxTime({
end: newEnd,
id,
isInvalid: false,
@@ -118,7 +123,10 @@ export const SuperDatePickerComponent = React.memo(
const currentEnd = isQuickSelection
? formatDate(newEnd, { roundUp: true })
: formatDate(newEnd);
- if (!isQuickSelection || (start === currentStart && end === currentEnd)) {
+ if (
+ !kqlHaveBeenUpdated &&
+ (!isQuickSelection || (start === currentStart && end === currentEnd))
+ ) {
refetchQuery(queries);
}
},
@@ -217,9 +225,10 @@ export const dispatchUpdateReduxTime = (dispatch: Dispatch) => ({
end,
id,
isQuickSelection,
+ kql,
start,
timelineId,
-}: UpdateReduxTime): void => {
+}: UpdateReduxTime): ReturnUpdateReduxTime => {
const fromDate = formatDate(start);
let toDate = formatDate(end, { roundUp: true });
if (isQuickSelection) {
@@ -251,6 +260,15 @@ export const dispatchUpdateReduxTime = (dispatch: Dispatch) => ({
})
);
}
+ if (kql) {
+ return {
+ kqlHaveBeenUpdated: kql.refetch(dispatch),
+ };
+ }
+
+ return {
+ kqlHaveBeenUpdated: false,
+ };
};
export const makeMapStateToProps = () => {
diff --git a/x-pack/legacy/plugins/siem/public/components/tables/__snapshots__/helpers.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/tables/__snapshots__/helpers.test.tsx.snap
index aa8666c247cae..1e6c5eb89352b 100644
--- a/x-pack/legacy/plugins/siem/public/components/tables/__snapshots__/helpers.test.tsx.snap
+++ b/x-pack/legacy/plugins/siem/public/components/tables/__snapshots__/helpers.test.tsx.snap
@@ -33,7 +33,7 @@ exports[`Table Helpers #getRowItemDraggables it returns correctly against snapsh
"and": Array [],
"enabled": true,
"excluded": false,
- "id": "idPrefix-attrName-item1",
+ "id": "idPrefix-attrName-item1-0",
"kqlQuery": "",
"name": "item1",
"queryMatch": Object {
@@ -44,7 +44,7 @@ exports[`Table Helpers #getRowItemDraggables it returns correctly against snapsh
},
}
}
- key="idPrefix-attrName-item1"
+ key="idPrefix-attrName-item1-0"
render={[Function]}
/>
,
@@ -55,7 +55,7 @@ exports[`Table Helpers #getRowItemDraggables it returns correctly against snapsh
"and": Array [],
"enabled": true,
"excluded": false,
- "id": "idPrefix-attrName-item2",
+ "id": "idPrefix-attrName-item2-1",
"kqlQuery": "",
"name": "item2",
"queryMatch": Object {
@@ -66,7 +66,7 @@ exports[`Table Helpers #getRowItemDraggables it returns correctly against snapsh
},
}
}
- key="idPrefix-attrName-item2"
+ key="idPrefix-attrName-item2-1"
render={[Function]}
/>
,
@@ -77,7 +77,7 @@ exports[`Table Helpers #getRowItemDraggables it returns correctly against snapsh
"and": Array [],
"enabled": true,
"excluded": false,
- "id": "idPrefix-attrName-item3",
+ "id": "idPrefix-attrName-item3-2",
"kqlQuery": "",
"name": "item3",
"queryMatch": Object {
@@ -88,7 +88,7 @@ exports[`Table Helpers #getRowItemDraggables it returns correctly against snapsh
},
}
}
- key="idPrefix-attrName-item3"
+ key="idPrefix-attrName-item3-2"
render={[Function]}
/>
diff --git a/x-pack/legacy/plugins/siem/public/components/tables/helpers.tsx b/x-pack/legacy/plugins/siem/public/components/tables/helpers.tsx
index 2557630a60306..b4ee93f9963e4 100644
--- a/x-pack/legacy/plugins/siem/public/components/tables/helpers.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/tables/helpers.tsx
@@ -89,7 +89,7 @@ export const getRowItemDraggables = ({
}): JSX.Element => {
if (rowItems != null && rowItems.length > 0) {
const draggables = rowItems.slice(0, displayCount).map((rowItem, index) => {
- const id = escapeDataProviderId(`${idPrefix}-${attrName}-${rowItem}`);
+ const id = escapeDataProviderId(`${idPrefix}-${attrName}-${rowItem}-${index}`);
return (
{index !== 0 && (
diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/file_draggable.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/file_draggable.test.tsx
index 68acc58972370..80be9fd339f51 100644
--- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/file_draggable.test.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/file_draggable.test.tsx
@@ -22,7 +22,7 @@ describe('FileDraggable', () => {
eventId="1"
fileName="[fileName]"
filePath="[filePath]"
- >
+ />
);
expect(wrapper.text()).toEqual('[fileName]in[filePath]');
@@ -38,7 +38,7 @@ describe('FileDraggable', () => {
eventId="1"
fileName={undefined}
filePath={undefined}
- >
+ />
);
expect(wrapper.text()).toEqual('');
diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx
index a18e4d7962e95..6182fca6e2e99 100644
--- a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx
@@ -4,11 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { isEmpty, isNumber, get } from 'lodash/fp';
import memoizeOne from 'memoize-one';
import { StaticIndexPattern } from 'ui/index_patterns';
-import { Query } from 'src/plugins/data/common';
+import { Query, esFilters } from 'src/plugins/data/public';
import { escapeQueryValue, convertToBuildEsQuery, EsQueryConfig } from '../../lib/keury';
@@ -106,7 +105,7 @@ export const combineQueries = ({
dataProviders: DataProvider[];
indexPattern: StaticIndexPattern;
browserFields: BrowserFields;
- filters: Filter[];
+ filters: esFilters.Filter[];
kqlQuery: Query;
kqlMode: string;
start: number;
diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx
index 111e31479932a..40ba16c0c128a 100644
--- a/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx
@@ -113,6 +113,7 @@ export const Properties = React.memo(
}) => {
const [showActions, setShowActions] = useState(false);
const [showNotes, setShowNotes] = useState(false);
+ const [showTimelineModal, setShowTimelineModal] = useState(false);
const onButtonClick = useCallback(() => {
setShowActions(!showActions);
@@ -126,6 +127,15 @@ export const Properties = React.memo(
setShowActions(false);
}, []);
+ const onOpenTimelineModal = useCallback(() => {
+ onClosePopover();
+ setShowTimelineModal(true);
+ }, []);
+
+ const onCloseTimelineModal = useCallback(() => {
+ setShowTimelineModal(false);
+ }, []);
+
const datePickerWidth =
width -
rightGutter -
@@ -173,11 +183,14 @@ export const Properties = React.memo(
noteIds={noteIds}
onButtonClick={onButtonClick}
onClosePopover={onClosePopover}
+ onCloseTimelineModal={onCloseTimelineModal}
+ onOpenTimelineModal={onOpenTimelineModal}
onToggleShowNotes={onToggleShowNotes}
showActions={showActions}
showDescription={width < showDescriptionThreshold}
showNotes={showNotes}
showNotesFromWidth={width < showNotesThreshold}
+ showTimelineModal={showTimelineModal}
showUsersView={title.length > 0}
timelineId={timelineId}
updateDescription={updateDescription}
diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/properties/properties_right.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/properties/properties_right.tsx
index 2eef253d7be7c..4027682282dcd 100644
--- a/x-pack/legacy/plugins/siem/public/components/timeline/properties/properties_right.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/timeline/properties/properties_right.tsx
@@ -15,7 +15,8 @@ import {
EuiAvatar,
} from '@elastic/eui';
import { NewTimeline, Description, NotesButton } from './helpers';
-import { OpenTimelineModalButton } from '../../open_timeline/open_timeline_modal';
+import { OpenTimelineModalButton } from '../../open_timeline/open_timeline_modal/open_timeline_modal_button';
+import { OpenTimelineModal } from '../../open_timeline/open_timeline_modal';
import { InspectButton } from '../../inspect';
import * as i18n from './translations';
@@ -75,6 +76,9 @@ interface Props {
getNotesByIds: (noteIds: string[]) => Note[];
noteIds: string[];
onToggleShowNotes: () => void;
+ onCloseTimelineModal: () => void;
+ onOpenTimelineModal: () => void;
+ showTimelineModal: boolean;
updateNote: UpdateNote;
}
@@ -98,6 +102,9 @@ export const PropertiesRight = React.memo(
noteIds,
onToggleShowNotes,
updateNote,
+ showTimelineModal,
+ onCloseTimelineModal,
+ onOpenTimelineModal,
}) => (
@@ -125,7 +132,7 @@ export const PropertiesRight = React.memo(
-
+
@@ -186,6 +193,8 @@ export const PropertiesRight = React.memo(
))
: null}
+
+ {showTimelineModal ? : null}
)
);
diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/helpers.ts b/x-pack/legacy/plugins/siem/public/components/url_state/helpers.ts
index 9c49d356cd4bc..f7487d7a81a7a 100644
--- a/x-pack/legacy/plugins/siem/public/components/url_state/helpers.ts
+++ b/x-pack/legacy/plugins/siem/public/components/url_state/helpers.ts
@@ -4,11 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { decode, encode, RisonValue } from 'rison-node';
import { Location } from 'history';
import { QueryString } from 'ui/utils/query_string';
-import { Query } from 'src/plugins/data/common';
+import { Query, esFilters } from 'src/plugins/data/public';
import { inputsSelectors, State, timelineSelectors } from '../../store';
import { SiemPageName } from '../../pages/home/types';
@@ -154,7 +153,7 @@ export const makeMapStateToProps = () => {
let searchAttr: {
[CONSTANTS.appQuery]?: Query;
- [CONSTANTS.filters]?: Filter[];
+ [CONSTANTS.filters]?: esFilters.Filter[];
[CONSTANTS.savedQuery]?: string;
} = {
[CONSTANTS.appQuery]: getGlobalQuerySelector(state),
diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/initialize_redux_by_url.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/initialize_redux_by_url.tsx
index fa3b278866704..013983c78a3a5 100644
--- a/x-pack/legacy/plugins/siem/public/components/url_state/initialize_redux_by_url.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/url_state/initialize_redux_by_url.tsx
@@ -4,11 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { get, isEmpty } from 'lodash/fp';
import { Dispatch } from 'redux';
import { SavedQuery } from 'src/legacy/core_plugins/data/public';
-import { Query } from 'src/plugins/data/common';
+import { Query, esFilters } from 'src/plugins/data/public';
import { inputsActions } from '../../store/actions';
import { InputsModelId, TimeRangeKinds } from '../../store/inputs/constants';
@@ -125,7 +124,7 @@ export const dispatchSetInitialStateFromUrl = (
}
if (urlKey === CONSTANTS.filters) {
- const filters: Filter[] = decodeRisonUrlState(newUrlStateString);
+ const filters: esFilters.Filter[] = decodeRisonUrlState(newUrlStateString);
siemFilterManager.setFilters(filters || []);
}
diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/types.ts b/x-pack/legacy/plugins/siem/public/components/url_state/types.ts
index f858ffc32ddbc..44c050a1990ce 100644
--- a/x-pack/legacy/plugins/siem/public/components/url_state/types.ts
+++ b/x-pack/legacy/plugins/siem/public/components/url_state/types.ts
@@ -4,11 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import ApolloClient from 'apollo-client';
import { ActionCreator } from 'typescript-fsa';
import { StaticIndexPattern } from 'ui/index_patterns';
-import { Query } from 'src/plugins/data/common';
+import { Query, esFilters } from 'src/plugins/data/public';
import { UrlInputsModel } from '../../store/inputs/model';
import { RouteSpyState } from '../../utils/route/types';
@@ -60,7 +59,7 @@ export interface Timeline {
export interface UrlState {
[CONSTANTS.appQuery]?: Query;
- [CONSTANTS.filters]?: Filter[];
+ [CONSTANTS.filters]?: esFilters.Filter[];
[CONSTANTS.savedQuery]?: string;
[CONSTANTS.timerange]: UrlInputsModel;
[CONSTANTS.timeline]: Timeline;
diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx
index 5b9511f169744..f1eeb4e6fbec4 100644
--- a/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx
@@ -3,11 +3,11 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
+
import { Location } from 'history';
import { isEqual, difference, isEmpty } from 'lodash/fp';
import { useEffect, useRef, useState } from 'react';
-import { Query } from 'src/plugins/data/common';
+import { Query, esFilters } from 'src/plugins/data/public';
import { UrlInputsModel } from '../../store/inputs/model';
import { useApolloClient } from '../../utils/apollo_context';
@@ -59,7 +59,7 @@ export const useUrlStateHooks = ({
const prevProps = usePrevious({ pathName, urlState });
const replaceStateInLocation = (
- urlStateToReplace: UrlInputsModel | Query | Filter[] | Timeline | string,
+ urlStateToReplace: UrlInputsModel | Query | esFilters.Filter[] | Timeline | string,
urlStateKey: string,
latestLocation: Location = {
hash: '',
@@ -94,7 +94,10 @@ export const useUrlStateHooks = ({
urlKey
);
if (newUrlStateString) {
- const queryState: Query | Timeline | Filter[] = decodeRisonUrlState(newUrlStateString);
+ const queryState: Query | Timeline | esFilters.Filter[] = decodeRisonUrlState(
+ newUrlStateString
+ );
+
if (
urlKey === CONSTANTS.appQuery &&
queryState != null &&
diff --git a/x-pack/legacy/plugins/siem/public/containers/network_http/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/network_http/index.gql_query.ts
new file mode 100644
index 0000000000000..bedf13dfa9849
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/containers/network_http/index.gql_query.ts
@@ -0,0 +1,57 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import gql from 'graphql-tag';
+
+export const networkHttpQuery = gql`
+ query GetNetworkHttpQuery(
+ $sourceId: ID!
+ $ip: String
+ $filterQuery: String
+ $pagination: PaginationInputPaginated!
+ $sort: NetworkHttpSortField!
+ $timerange: TimerangeInput!
+ $defaultIndex: [String!]!
+ $inspect: Boolean!
+ ) {
+ source(id: $sourceId) {
+ id
+ NetworkHttp(
+ filterQuery: $filterQuery
+ ip: $ip
+ pagination: $pagination
+ sort: $sort
+ timerange: $timerange
+ defaultIndex: $defaultIndex
+ ) {
+ totalCount
+ edges {
+ node {
+ domains
+ lastHost
+ lastSourceIp
+ methods
+ path
+ requestCount
+ statuses
+ }
+ cursor {
+ value
+ }
+ }
+ pageInfo {
+ activePage
+ fakeTotalCount
+ showMorePagesIndicator
+ }
+ inspect @include(if: $inspect) {
+ dsl
+ response
+ }
+ }
+ }
+ }
+`;
diff --git a/x-pack/legacy/plugins/siem/public/containers/network_http/index.tsx b/x-pack/legacy/plugins/siem/public/containers/network_http/index.tsx
new file mode 100644
index 0000000000000..d76ab53b2de3a
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/containers/network_http/index.tsx
@@ -0,0 +1,154 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { getOr } from 'lodash/fp';
+import React from 'react';
+import { Query } from 'react-apollo';
+import { connect } from 'react-redux';
+import { compose } from 'redux';
+import chrome from 'ui/chrome';
+
+import { DEFAULT_INDEX_KEY } from '../../../common/constants';
+import {
+ GetNetworkHttpQuery,
+ NetworkHttpEdges,
+ NetworkHttpSortField,
+ PageInfoPaginated,
+} from '../../graphql/types';
+import { inputsModel, inputsSelectors, networkModel, networkSelectors, State } from '../../store';
+import { generateTablePaginationOptions } from '../../components/paginated_table/helpers';
+import { createFilter, getDefaultFetchPolicy } from '../helpers';
+import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated';
+import { networkHttpQuery } from './index.gql_query';
+
+const ID = 'networkHttpQuery';
+
+export interface NetworkHttpArgs {
+ id: string;
+ ip?: string;
+ inspect: inputsModel.InspectQuery;
+ isInspected: boolean;
+ loading: boolean;
+ loadPage: (newActivePage: number) => void;
+ networkHttp: NetworkHttpEdges[];
+ pageInfo: PageInfoPaginated;
+ refetch: inputsModel.Refetch;
+ totalCount: number;
+}
+
+export interface OwnProps extends QueryTemplatePaginatedProps {
+ children: (args: NetworkHttpArgs) => React.ReactNode;
+ ip?: string;
+ type: networkModel.NetworkType;
+}
+
+export interface NetworkHttpComponentReduxProps {
+ activePage: number;
+ isInspected: boolean;
+ limit: number;
+ sort: NetworkHttpSortField;
+}
+
+type NetworkHttpProps = OwnProps & NetworkHttpComponentReduxProps;
+
+class NetworkHttpComponentQuery extends QueryTemplatePaginated<
+ NetworkHttpProps,
+ GetNetworkHttpQuery.Query,
+ GetNetworkHttpQuery.Variables
+> {
+ public render() {
+ const {
+ activePage,
+ children,
+ endDate,
+ filterQuery,
+ id = ID,
+ ip,
+ isInspected,
+ limit,
+ skip,
+ sourceId,
+ sort,
+ startDate,
+ } = this.props;
+ const variables: GetNetworkHttpQuery.Variables = {
+ defaultIndex: chrome.getUiSettingsClient().get(DEFAULT_INDEX_KEY),
+ filterQuery: createFilter(filterQuery),
+ inspect: isInspected,
+ ip,
+ pagination: generateTablePaginationOptions(activePage, limit),
+ sort,
+ sourceId,
+ timerange: {
+ interval: '12h',
+ from: startDate!,
+ to: endDate!,
+ },
+ };
+ return (
+
+ fetchPolicy={getDefaultFetchPolicy()}
+ notifyOnNetworkStatusChange
+ query={networkHttpQuery}
+ skip={skip}
+ variables={variables}
+ >
+ {({ data, loading, fetchMore, networkStatus, refetch }) => {
+ const networkHttp = getOr([], `source.NetworkHttp.edges`, data);
+ this.setFetchMore(fetchMore);
+ this.setFetchMoreOptions((newActivePage: number) => ({
+ variables: {
+ pagination: generateTablePaginationOptions(newActivePage, limit),
+ },
+ updateQuery: (prev, { fetchMoreResult }) => {
+ if (!fetchMoreResult) {
+ return prev;
+ }
+ return {
+ ...fetchMoreResult,
+ source: {
+ ...fetchMoreResult.source,
+ NetworkHttp: {
+ ...fetchMoreResult.source.NetworkHttp,
+ edges: [...fetchMoreResult.source.NetworkHttp.edges],
+ },
+ },
+ };
+ },
+ }));
+ const isLoading = this.isItAValidLoading(loading, variables, networkStatus);
+ return children({
+ id,
+ inspect: getOr(null, 'source.NetworkHttp.inspect', data),
+ isInspected,
+ loading: isLoading,
+ loadPage: this.wrappedLoadMore,
+ networkHttp,
+ pageInfo: getOr({}, 'source.NetworkHttp.pageInfo', data),
+ refetch: this.memoizedRefetchQuery(variables, limit, refetch),
+ totalCount: getOr(-1, 'source.NetworkHttp.totalCount', data),
+ });
+ }}
+
+ );
+ }
+}
+
+const makeMapStateToProps = () => {
+ const getHttpSelector = networkSelectors.httpSelector();
+ const getQuery = inputsSelectors.globalQueryByIdSelector();
+ return (state: State, { id = ID, type }: OwnProps) => {
+ const { isInspected } = getQuery(state, id);
+ return {
+ ...getHttpSelector(state, type),
+ isInspected,
+ };
+ };
+};
+
+export const NetworkHttpQuery = compose>(
+ connect(makeMapStateToProps)
+)(NetworkHttpComponentQuery);
diff --git a/x-pack/legacy/plugins/siem/public/containers/tls/index.tsx b/x-pack/legacy/plugins/siem/public/containers/tls/index.tsx
index 4fd24b9cb42a5..7abe14ae745c5 100644
--- a/x-pack/legacy/plugins/siem/public/containers/tls/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/containers/tls/index.tsx
@@ -143,7 +143,7 @@ class TlsComponentQuery extends QueryTemplatePaginated<
const makeMapStateToProps = () => {
const getTlsSelector = networkSelectors.tlsSelector();
const getQuery = inputsSelectors.globalQueryByIdSelector();
- return (state: State, { flowTarget, id = `${ID}-${flowTarget}`, type }: OwnProps) => {
+ return (state: State, { flowTarget, id = ID, type }: OwnProps) => {
const { isInspected } = getQuery(state, id);
return {
...getTlsSelector(state, type, flowTarget),
diff --git a/x-pack/legacy/plugins/siem/public/graphql/introspection.json b/x-pack/legacy/plugins/siem/public/graphql/introspection.json
index 488a6310db3f2..8732b61e5c0eb 100644
--- a/x-pack/legacy/plugins/siem/public/graphql/introspection.json
+++ b/x-pack/legacy/plugins/siem/public/graphql/introspection.json
@@ -1777,6 +1777,93 @@
"isDeprecated": false,
"deprecationReason": null
},
+ {
+ "name": "NetworkHttp",
+ "description": "",
+ "args": [
+ {
+ "name": "id",
+ "description": "",
+ "type": { "kind": "SCALAR", "name": "String", "ofType": null },
+ "defaultValue": null
+ },
+ {
+ "name": "filterQuery",
+ "description": "",
+ "type": { "kind": "SCALAR", "name": "String", "ofType": null },
+ "defaultValue": null
+ },
+ {
+ "name": "ip",
+ "description": "",
+ "type": { "kind": "SCALAR", "name": "String", "ofType": null },
+ "defaultValue": null
+ },
+ {
+ "name": "pagination",
+ "description": "",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "PaginationInputPaginated",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "sort",
+ "description": "",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "NetworkHttpSortField",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "timerange",
+ "description": "",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "defaultIndex",
+ "description": "",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
+ }
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "OBJECT", "name": "NetworkHttpData", "ofType": null }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
{
"name": "OverviewNetwork",
"description": "",
@@ -8048,6 +8135,236 @@
"enumValues": null,
"possibleTypes": null
},
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "NetworkHttpSortField",
+ "description": "",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "direction",
+ "description": "",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null }
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "NetworkHttpData",
+ "description": "",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "OBJECT", "name": "NetworkHttpEdges", "ofType": null }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "totalCount",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "inspect",
+ "description": "",
+ "args": [],
+ "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "NetworkHttpEdges",
+ "description": "",
+ "fields": [
+ {
+ "name": "node",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "OBJECT", "name": "NetworkHttpItem", "ofType": null }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "cursor",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "NetworkHttpItem",
+ "description": "",
+ "fields": [
+ {
+ "name": "_id",
+ "description": "",
+ "args": [],
+ "type": { "kind": "SCALAR", "name": "String", "ofType": null },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "domains",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lastHost",
+ "description": "",
+ "args": [],
+ "type": { "kind": "SCALAR", "name": "String", "ofType": null },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lastSourceIp",
+ "description": "",
+ "args": [],
+ "type": { "kind": "SCALAR", "name": "String", "ofType": null },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "methods",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "path",
+ "description": "",
+ "args": [],
+ "type": { "kind": "SCALAR", "name": "String", "ofType": null },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "requestCount",
+ "description": "",
+ "args": [],
+ "type": { "kind": "SCALAR", "name": "Float", "ofType": null },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "statuses",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [],
+ "enumValues": null,
+ "possibleTypes": null
+ },
{
"kind": "OBJECT",
"name": "OverviewNetworkData",
@@ -11275,6 +11592,54 @@
],
"possibleTypes": null
},
+ {
+ "kind": "ENUM",
+ "name": "NetworkHttpFields",
+ "description": "",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "domains",
+ "description": "",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lastHost",
+ "description": "",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lastSourceIp",
+ "description": "",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "methods",
+ "description": "",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ { "name": "path", "description": "", "isDeprecated": false, "deprecationReason": null },
+ {
+ "name": "requestCount",
+ "description": "",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "statuses",
+ "description": "",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
{
"kind": "ENUM",
"name": "FlowDirection",
diff --git a/x-pack/legacy/plugins/siem/public/graphql/types.ts b/x-pack/legacy/plugins/siem/public/graphql/types.ts
index dbb62d73e5994..a1b259b876a14 100644
--- a/x-pack/legacy/plugins/siem/public/graphql/types.ts
+++ b/x-pack/legacy/plugins/siem/public/graphql/types.ts
@@ -85,6 +85,10 @@ export interface NetworkDnsSortField {
direction: Direction;
}
+export interface NetworkHttpSortField {
+ direction: Direction;
+}
+
export interface TlsSortField {
field: TlsFields;
@@ -294,6 +298,16 @@ export enum NetworkDirectionEcs {
unknown = 'unknown',
}
+export enum NetworkHttpFields {
+ domains = 'domains',
+ lastHost = 'lastHost',
+ lastSourceIp = 'lastSourceIp',
+ methods = 'methods',
+ path = 'path',
+ requestCount = 'requestCount',
+ statuses = 'statuses',
+}
+
export enum FlowDirection {
uniDirectional = 'uniDirectional',
biDirectional = 'biDirectional',
@@ -433,6 +447,8 @@ export interface Source {
NetworkDns: NetworkDnsData;
+ NetworkHttp: NetworkHttpData;
+
OverviewNetwork?: Maybe;
OverviewHost?: Maybe;
@@ -1588,6 +1604,40 @@ export interface NetworkDnsItem {
uniqueDomains?: Maybe;
}
+export interface NetworkHttpData {
+ edges: NetworkHttpEdges[];
+
+ totalCount: number;
+
+ pageInfo: PageInfoPaginated;
+
+ inspect?: Maybe;
+}
+
+export interface NetworkHttpEdges {
+ node: NetworkHttpItem;
+
+ cursor: CursorType;
+}
+
+export interface NetworkHttpItem {
+ _id?: Maybe;
+
+ domains: string[];
+
+ lastHost?: Maybe;
+
+ lastSourceIp?: Maybe;
+
+ methods: string[];
+
+ path?: Maybe;
+
+ requestCount?: Maybe;
+
+ statuses: string[];
+}
+
export interface OverviewNetworkData {
auditbeatSocket?: Maybe;
@@ -2162,6 +2212,21 @@ export interface NetworkDnsSourceArgs {
defaultIndex: string[];
}
+export interface NetworkHttpSourceArgs {
+ id?: Maybe;
+
+ filterQuery?: Maybe;
+
+ ip?: Maybe;
+
+ pagination: PaginationInputPaginated;
+
+ sort: NetworkHttpSortField;
+
+ timerange: TimerangeInput;
+
+ defaultIndex: string[];
+}
export interface OverviewNetworkSourceArgs {
id?: Maybe;
@@ -3209,6 +3274,95 @@ export namespace GetNetworkDnsQuery {
};
}
+export namespace GetNetworkHttpQuery {
+ export type Variables = {
+ sourceId: string;
+ ip?: Maybe;
+ filterQuery?: Maybe;
+ pagination: PaginationInputPaginated;
+ sort: NetworkHttpSortField;
+ timerange: TimerangeInput;
+ defaultIndex: string[];
+ inspect: boolean;
+ };
+
+ export type Query = {
+ __typename?: 'Query';
+
+ source: Source;
+ };
+
+ export type Source = {
+ __typename?: 'Source';
+
+ id: string;
+
+ NetworkHttp: NetworkHttp;
+ };
+
+ export type NetworkHttp = {
+ __typename?: 'NetworkHttpData';
+
+ totalCount: number;
+
+ edges: Edges[];
+
+ pageInfo: PageInfo;
+
+ inspect: Maybe;
+ };
+
+ export type Edges = {
+ __typename?: 'NetworkHttpEdges';
+
+ node: Node;
+
+ cursor: Cursor;
+ };
+
+ export type Node = {
+ __typename?: 'NetworkHttpItem';
+
+ domains: string[];
+
+ lastHost: Maybe;
+
+ lastSourceIp: Maybe;
+
+ methods: string[];
+
+ path: Maybe;
+
+ requestCount: Maybe;
+
+ statuses: string[];
+ };
+
+ export type Cursor = {
+ __typename?: 'CursorType';
+
+ value: Maybe;
+ };
+
+ export type PageInfo = {
+ __typename?: 'PageInfoPaginated';
+
+ activePage: number;
+
+ fakeTotalCount: number;
+
+ showMorePagesIndicator: boolean;
+ };
+
+ export type Inspect = {
+ __typename?: 'Inspect';
+
+ dsl: string[];
+
+ response: string[];
+ };
+}
+
export namespace GetNetworkTopCountriesQuery {
export type Variables = {
sourceId: string;
diff --git a/x-pack/legacy/plugins/siem/public/lib/keury/index.ts b/x-pack/legacy/plugins/siem/public/lib/keury/index.ts
index 7bd8560a1770a..bf8726d5ed377 100644
--- a/x-pack/legacy/plugins/siem/public/lib/keury/index.ts
+++ b/x-pack/legacy/plugins/siem/public/lib/keury/index.ts
@@ -4,10 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { buildEsQuery, Filter, fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
+import { buildEsQuery, fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
import { isEmpty, isString, flow } from 'lodash/fp';
import { StaticIndexPattern } from 'ui/index_patterns';
import { Query } from 'src/plugins/data/common';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
import { KueryFilterQuery } from '../../store';
@@ -83,7 +84,7 @@ export const convertToBuildEsQuery = ({
config: EsQueryConfig;
indexPattern: StaticIndexPattern;
queries: Query[];
- filters: Filter[];
+ filters: esFilters.Filter[];
}) => {
try {
return JSON.stringify(
diff --git a/x-pack/legacy/plugins/siem/public/mock/global_state.ts b/x-pack/legacy/plugins/siem/public/mock/global_state.ts
index 9be209321085f..ada34acbc1946 100644
--- a/x-pack/legacy/plugins/siem/public/mock/global_state.ts
+++ b/x-pack/legacy/plugins/siem/public/mock/global_state.ts
@@ -96,6 +96,11 @@ export const mockGlobalState: State = {
limit: 10,
sort: { field: TlsFields._id, direction: Direction.desc },
},
+ [networkModel.NetworkTableType.http]: {
+ activePage: 0,
+ limit: 10,
+ sort: { direction: Direction.desc },
+ },
},
},
details: {
@@ -131,6 +136,11 @@ export const mockGlobalState: State = {
limit: 10,
sort: { field: UsersFields.name, direction: Direction.asc },
},
+ [networkModel.IpDetailsTableType.http]: {
+ activePage: 0,
+ limit: 10,
+ sort: { direction: Direction.desc },
+ },
},
},
},
diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx
index 30744b3e24c4b..d3a242b41da7b 100644
--- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx
@@ -12,7 +12,6 @@ import { connect } from 'react-redux';
import { StickyContainer } from 'react-sticky';
import { inputsSelectors, State } from '../../../store';
-
import { FiltersGlobal } from '../../../components/filters_global';
import { HeaderPage } from '../../../components/header_page';
import { KpiHostDetailsQuery } from '../../../containers/kpi_host_details';
diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/types.ts b/x-pack/legacy/plugins/siem/public/pages/hosts/details/types.ts
index 9df57970176eb..4f3d34f51fb93 100644
--- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/types.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/types.ts
@@ -5,9 +5,8 @@
*/
import { StaticIndexPattern } from 'ui/index_patterns';
-import { Filter } from '@kbn/es-query';
import { ActionCreator } from 'typescript-fsa';
-import { Query } from 'src/plugins/data/common';
+import { Query, esFilters } from 'src/plugins/data/public';
import { InputsModelId } from '../../../store/inputs/constants';
import { HostComponentProps } from '../../../components/link_to/redirect_to_hosts';
@@ -19,7 +18,7 @@ import { hostsModel } from '../../../store';
interface HostDetailsComponentReduxProps {
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
}
interface HostBodyComponentDispatchProps {
diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts b/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts
index 980c5535129aa..afc577244f7e0 100644
--- a/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts
@@ -6,8 +6,7 @@
import { StaticIndexPattern } from 'ui/index_patterns';
import { ActionCreator } from 'typescript-fsa';
-import { Filter } from '@kbn/es-query';
-import { Query } from 'src/plugins/data/common';
+import { Query, esFilters } from 'src/plugins/data/public';
import { SiemPageName } from '../home/types';
import { hostsModel } from '../../store';
@@ -19,7 +18,7 @@ export const hostDetailsPagePath = `${hostsPagePath}/:detailName`;
export interface HostsComponentReduxProps {
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
}
export interface HostsComponentDispatchProps {
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx
index 824539cad8d52..0fd4e073ebd13 100644
--- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx
@@ -38,6 +38,7 @@ export { getBreadcrumbs } from './utils';
import { TlsQueryTable } from './tls_query_table';
import { UsersQueryTable } from './users_query_table';
import { NetworkTopNFlowQueryTable } from './network_top_n_flow_query_table';
+import { NetworkHttpQueryTable } from './network_http_query_table';
import { NetworkTopCountriesQueryTable } from './network_top_countries_query_table';
import { useKibanaCore } from '../../../lib/compose/kibana_core';
@@ -221,6 +222,18 @@ export const IPDetailsComponent = React.memo(
+
+
+
+
(
+
+ {({
+ id,
+ inspect,
+ isInspected,
+ loading,
+ loadPage,
+ networkHttp,
+ pageInfo,
+ refetch,
+ totalCount,
+ }) => (
+
+ )}
+
+);
+
+NetworkHttpQueryTable.displayName = 'NetworkHttpQueryTable';
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts
index 008409197f77d..e0029d8d219eb 100644
--- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts
@@ -4,10 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { StaticIndexPattern } from 'ui/index_patterns';
import { ActionCreator } from 'typescript-fsa';
-import { Query } from 'src/plugins/data/common';
+import { Query, esFilters } from 'src/plugins/data/public';
import { NetworkType } from '../../../store/network/model';
import { ESTermQuery } from '../../../../common/typed_json';
@@ -25,7 +24,7 @@ type SetAbsoluteRangeDatePicker = ActionCreator<{
}>;
interface IPDetailsComponentReduxProps {
- filters: Filter[];
+ filters: esFilters.Filter[];
flowTarget: FlowTarget;
query: Query;
}
@@ -39,7 +38,7 @@ export type IPDetailsComponentProps = IPDetailsComponentReduxProps &
IPDetailsComponentDispatchProps &
GlobalTimeArgs & { detailName: string };
-interface OwnProps {
+export interface OwnProps {
type: NetworkType;
startDate: number;
endDate: number;
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/http_query_tab_body.tsx b/x-pack/legacy/plugins/siem/public/pages/network/navigation/http_query_tab_body.tsx
new file mode 100644
index 0000000000000..a20a212623fb8
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/http_query_tab_body.tsx
@@ -0,0 +1,63 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { getOr } from 'lodash/fp';
+
+import { NetworkHttpTable } from '../../../components/page/network';
+import { NetworkHttpQuery } from '../../../containers/network_http';
+import { networkModel } from '../../../store';
+import { manageQuery } from '../../../components/page/manage_query';
+
+import { HttpQueryTabBodyProps } from './types';
+
+const NetworkHttpTableManage = manageQuery(NetworkHttpTable);
+
+export const HttpQueryTabBody = ({
+ to,
+ filterQuery,
+ isInitializing,
+ from,
+ setQuery,
+}: HttpQueryTabBodyProps) => (
+
+ {({
+ id,
+ inspect,
+ isInspected,
+ loading,
+ loadPage,
+ networkHttp,
+ pageInfo,
+ refetch,
+ totalCount,
+ }) => (
+
+ )}
+
+);
+
+HttpQueryTabBody.displayName = 'HttpQueryTabBody';
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/nav_tabs.tsx b/x-pack/legacy/plugins/siem/public/pages/network/navigation/nav_tabs.tsx
index ef097373b3ae7..fbf137df39872 100644
--- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/nav_tabs.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/nav_tabs.tsx
@@ -26,6 +26,13 @@ export const navTabsNetwork = (hasMlUserPermissions: boolean): NetworkNavTab =>
disabled: false,
urlKey: 'network',
},
+ [NetworkRouteType.http]: {
+ id: NetworkRouteType.http,
+ name: i18n.NAVIGATION_HTTP_TITLE,
+ href: getTabsOnNetworkUrl(NetworkRouteType.http),
+ disabled: false,
+ urlKey: 'network',
+ },
[NetworkRouteType.tls]: {
id: NetworkRouteType.tls,
name: i18n.NAVIGATION_TLS_TITLE,
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx b/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx
index fff9b1e7a0968..955670b4b098d 100644
--- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx
@@ -13,6 +13,7 @@ import { scoreIntervalToDateTime } from '../../../components/ml/score/score_inte
import { IPsQueryTabBody } from './ips_query_tab_body';
import { CountriesQueryTabBody } from './countries_query_tab_body';
+import { HttpQueryTabBody } from './http_query_tab_body';
import { AnomaliesQueryTabBody } from './anomalies_query_tab_body';
import { DnsQueryTabBody } from './dns_query_tab_body';
import { ConditionalFlexGroup } from './conditional_flex_group';
@@ -96,6 +97,10 @@ export const NetworkRoutes = ({
>
)}
/>
+ }
+ />
}
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/types.ts b/x-pack/legacy/plugins/siem/public/pages/network/navigation/types.ts
index a3639da3cc132..9682495b6f66a 100644
--- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/types.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/types.ts
@@ -34,6 +34,10 @@ export type TlsQueryTabBodyProps = QueryTabBodyProps &
ip?: string;
};
+export type HttpQueryTabBodyProps = QueryTabBodyProps &
+ GlobalTimeArgs & {
+ ip?: string;
+ };
export type AnomaliesQueryTabBodyProps = QueryTabBodyProps &
Pick & {
narrowDateRange: NarrowDateRange;
@@ -63,6 +67,7 @@ export enum NetworkRouteType {
dns = 'dns',
anomalies = 'anomalies',
tls = 'tls',
+ http = 'http',
}
export type GetNetworkRoutePath = (
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/utils.ts b/x-pack/legacy/plugins/siem/public/pages/network/navigation/utils.ts
index a1cb9d61b9c47..059949bf51837 100644
--- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/utils.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/utils.ts
@@ -12,7 +12,7 @@ export const getNetworkRoutePath: GetNetworkRoutePath = (
hasMlUserPermission
) => {
if (capabilitiesFetched && !hasMlUserPermission) {
- return `${pagePath}/:tabName(${NetworkRouteType.flows}|${NetworkRouteType.dns}|${NetworkRouteType.tls})`;
+ return `${pagePath}/:tabName(${NetworkRouteType.flows}|${NetworkRouteType.dns}|${NetworkRouteType.http}|${NetworkRouteType.tls})`;
}
return (
@@ -20,6 +20,7 @@ export const getNetworkRoutePath: GetNetworkRoutePath = (
`${NetworkRouteType.flows}|` +
`${NetworkRouteType.dns}|` +
`${NetworkRouteType.anomalies}|` +
+ `${NetworkRouteType.http}|` +
`${NetworkRouteType.tls})`
);
};
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/translations.ts b/x-pack/legacy/plugins/siem/public/pages/network/translations.ts
index 25c117319248a..be222bf5f2531 100644
--- a/x-pack/legacy/plugins/siem/public/pages/network/translations.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/network/translations.ts
@@ -39,6 +39,10 @@ export const NAVIGATION_TLS_TITLE = i18n.translate('xpack.siem.network.navigatio
defaultMessage: 'TLS',
});
+export const NAVIGATION_HTTP_TITLE = i18n.translate('xpack.siem.network.navigation.httpTitle', {
+ defaultMessage: 'HTTP',
+});
+
export const NAVIGATION_ANOMALIES_TITLE = i18n.translate(
'xpack.siem.network.navigation.anomaliesTitle',
{
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/types.ts b/x-pack/legacy/plugins/siem/public/pages/network/types.ts
index 46c868729b832..e440d0c27e467 100644
--- a/x-pack/legacy/plugins/siem/public/pages/network/types.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/network/types.ts
@@ -4,10 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { RouteComponentProps } from 'react-router-dom';
import { ActionCreator } from 'typescript-fsa';
-import { Query } from 'src/plugins/data/common';
+import { Query, esFilters } from 'src/plugins/data/common';
import { GlobalTimeArgs } from '../../containers/global_time';
import { InputsModelId } from '../../store/inputs/constants';
@@ -19,7 +18,7 @@ export type SetAbsoluteRangeDatePicker = ActionCreator<{
}>;
interface NetworkComponentReduxProps {
- filters: Filter[];
+ filters: esFilters.Filter[];
query: Query;
setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker;
}
diff --git a/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts b/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts
index 598b2854b96eb..aefcd2ea8c696 100644
--- a/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts
+++ b/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts
@@ -4,12 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import actionCreatorFactory from 'typescript-fsa';
import { SavedQuery } from 'src/legacy/core_plugins/data/public';
import { InspectQuery, Refetch } from './model';
import { InputsModelId } from './constants';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
const actionCreator = actionCreatorFactory('x-pack/siem/local/inputs');
@@ -83,5 +83,5 @@ export const setSavedQuery = actionCreator<{
export const setSearchBarFilter = actionCreator<{
id: InputsModelId;
- filters: Filter[];
+ filters: esFilters.Filter[];
}>('SET_SEARCH_BAR_FILTER');
diff --git a/x-pack/legacy/plugins/siem/public/store/inputs/model.ts b/x-pack/legacy/plugins/siem/public/store/inputs/model.ts
index a98ea1f5d0812..01cf386311d77 100644
--- a/x-pack/legacy/plugins/siem/public/store/inputs/model.ts
+++ b/x-pack/legacy/plugins/siem/public/store/inputs/model.ts
@@ -4,13 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Filter } from '@kbn/es-query';
import { Dispatch } from 'redux';
import { Query } from 'src/plugins/data/common/query';
import { SavedQuery } from 'src/legacy/core_plugins/data/public';
import { Omit } from '../../../common/utility_types';
import { InputsModelId } from './constants';
import { CONSTANTS } from '../../components/url_state/constants';
+import { esFilters } from '../../../../../../../src/plugins/data/public';
export interface AbsoluteTimeRange {
kind: 'absolute';
@@ -84,7 +84,7 @@ export interface InputsRange {
queries: GlobalQuery[];
linkTo: InputsModelId[];
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
savedQuery?: SavedQuery;
}
diff --git a/x-pack/legacy/plugins/siem/public/store/network/helpers.test.ts b/x-pack/legacy/plugins/siem/public/store/network/helpers.test.ts
index eb6a5c0c5c631..a15e187b95e60 100644
--- a/x-pack/legacy/plugins/siem/public/store/network/helpers.test.ts
+++ b/x-pack/legacy/plugins/siem/public/store/network/helpers.test.ts
@@ -6,11 +6,11 @@
import {
Direction,
- NetworkTopTablesFields,
+ FlowTarget,
NetworkDnsFields,
+ NetworkTopTablesFields,
TlsFields,
UsersFields,
- FlowTarget,
} from '../../graphql/types';
import { DEFAULT_TABLE_LIMIT } from '../constants';
import { NetworkModel, NetworkTableType, IpDetailsTableType, NetworkType } from './model';
@@ -68,6 +68,11 @@ export const mockNetworkState: NetworkModel = {
direction: Direction.desc,
},
},
+ [NetworkTableType.http]: {
+ activePage: 0,
+ limit: DEFAULT_TABLE_LIMIT,
+ sort: { direction: Direction.desc },
+ },
},
},
details: {
@@ -120,6 +125,11 @@ export const mockNetworkState: NetworkModel = {
direction: Direction.asc,
},
},
+ [IpDetailsTableType.http]: {
+ activePage: 0,
+ limit: DEFAULT_TABLE_LIMIT,
+ sort: { direction: Direction.desc },
+ },
},
flowTarget: FlowTarget.source,
},
@@ -145,6 +155,13 @@ describe('Network redux store', () => {
sort: { field: 'uniqueDomains', direction: 'desc' },
isPtrIncluded: false,
},
+ [NetworkTableType.http]: {
+ activePage: 0,
+ limit: 10,
+ sort: {
+ direction: 'desc',
+ },
+ },
[NetworkTableType.tls]: {
activePage: 0,
limit: 10,
@@ -200,6 +217,13 @@ describe('Network redux store', () => {
field: 'bytes_out',
},
},
+ [IpDetailsTableType.http]: {
+ activePage: 0,
+ limit: 10,
+ sort: {
+ direction: 'desc',
+ },
+ },
[IpDetailsTableType.tls]: {
activePage: 0,
limit: 10,
diff --git a/x-pack/legacy/plugins/siem/public/store/network/helpers.ts b/x-pack/legacy/plugins/siem/public/store/network/helpers.ts
index c438fb6b492ce..0b3a5e65346b8 100644
--- a/x-pack/legacy/plugins/siem/public/store/network/helpers.ts
+++ b/x-pack/legacy/plugins/siem/public/store/network/helpers.ts
@@ -40,6 +40,10 @@ export const setNetworkPageQueriesActivePageToZero = (state: NetworkModel): Netw
...state.page.queries[NetworkTableType.tls],
activePage: DEFAULT_TABLE_ACTIVE_PAGE,
},
+ [NetworkTableType.http]: {
+ ...state.page.queries[NetworkTableType.http],
+ activePage: DEFAULT_TABLE_ACTIVE_PAGE,
+ },
});
export const setNetworkDetailsQueriesActivePageToZero = (
@@ -70,6 +74,10 @@ export const setNetworkDetailsQueriesActivePageToZero = (
...state.details.queries[IpDetailsTableType.users],
activePage: DEFAULT_TABLE_ACTIVE_PAGE,
},
+ [IpDetailsTableType.http]: {
+ ...state.details.queries[IpDetailsTableType.http],
+ activePage: DEFAULT_TABLE_ACTIVE_PAGE,
+ },
});
export const setNetworkQueriesActivePageToZero = (
diff --git a/x-pack/legacy/plugins/siem/public/store/network/model.ts b/x-pack/legacy/plugins/siem/public/store/network/model.ts
index 1f82aa8a5319d..45c49d6598881 100644
--- a/x-pack/legacy/plugins/siem/public/store/network/model.ts
+++ b/x-pack/legacy/plugins/siem/public/store/network/model.ts
@@ -7,6 +7,7 @@
import {
FlowTarget,
NetworkDnsSortField,
+ NetworkHttpSortField,
NetworkTopTablesSortField,
TlsSortField,
UsersSortField,
@@ -19,6 +20,7 @@ export enum NetworkType {
export enum NetworkTableType {
dns = 'dns',
+ http = 'http',
topCountriesDestination = 'topCountriesDestination',
topCountriesSource = 'topCountriesSource',
topNFlowDestination = 'topNFlowDestination',
@@ -40,7 +42,10 @@ export type TopCountriesTableType =
export type TopTlsTableType = IpDetailsTableType.tls | NetworkTableType.tls;
+export type HttpTableType = IpDetailsTableType.http | NetworkTableType.http;
+
export enum IpDetailsTableType {
+ http = 'http',
tls = 'tls',
topCountriesDestination = 'topCountriesDestination',
topCountriesSource = 'topCountriesSource',
@@ -74,15 +79,25 @@ export interface TlsQuery extends BasicQueryPaginated {
sort: TlsSortField;
}
+export interface HttpQuery extends BasicQueryPaginated {
+ sort: NetworkHttpSortField;
+}
+
export interface TableUpdates {
activePage?: number;
limit?: number;
isPtrIncluded?: boolean;
- sort?: NetworkDnsSortField | NetworkTopTablesSortField | TlsSortField | UsersSortField;
+ sort?:
+ | NetworkDnsSortField
+ | NetworkHttpSortField
+ | NetworkTopTablesSortField
+ | TlsSortField
+ | UsersSortField;
}
export interface NetworkQueries {
[NetworkTableType.dns]: DnsQuery;
+ [NetworkTableType.http]: HttpQuery;
[NetworkTableType.topCountriesDestination]: TopCountriesQuery;
[NetworkTableType.topCountriesSource]: TopCountriesQuery;
[NetworkTableType.topNFlowDestination]: TopNFlowQuery;
@@ -99,6 +114,7 @@ export interface UsersQuery extends BasicQueryPaginated {
}
export interface IpOverviewQueries {
+ [IpDetailsTableType.http]: HttpQuery;
[IpDetailsTableType.tls]: TlsQuery;
[IpDetailsTableType.topCountriesDestination]: TopCountriesQuery;
[IpDetailsTableType.topCountriesSource]: TopCountriesQuery;
diff --git a/x-pack/legacy/plugins/siem/public/store/network/reducer.ts b/x-pack/legacy/plugins/siem/public/store/network/reducer.ts
index 88adc118d51dc..373bedb63c3e7 100644
--- a/x-pack/legacy/plugins/siem/public/store/network/reducer.ts
+++ b/x-pack/legacy/plugins/siem/public/store/network/reducer.ts
@@ -58,6 +58,13 @@ export const initialNetworkState: NetworkState = {
},
isPtrIncluded: false,
},
+ [NetworkTableType.http]: {
+ activePage: DEFAULT_TABLE_ACTIVE_PAGE,
+ limit: DEFAULT_TABLE_LIMIT,
+ sort: {
+ direction: Direction.desc,
+ },
+ },
[NetworkTableType.tls]: {
activePage: DEFAULT_TABLE_ACTIVE_PAGE,
limit: DEFAULT_TABLE_LIMIT,
@@ -86,6 +93,13 @@ export const initialNetworkState: NetworkState = {
},
details: {
queries: {
+ [IpDetailsTableType.http]: {
+ activePage: DEFAULT_TABLE_ACTIVE_PAGE,
+ limit: DEFAULT_TABLE_LIMIT,
+ sort: {
+ direction: Direction.desc,
+ },
+ },
[IpDetailsTableType.topCountriesSource]: {
activePage: DEFAULT_TABLE_ACTIVE_PAGE,
limit: DEFAULT_TABLE_LIMIT,
diff --git a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts
index 04cf8f0ea464c..cf57c0d07c43e 100644
--- a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts
+++ b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts
@@ -84,6 +84,21 @@ export const topCountriesSelector = () =>
topCountriesQueries => topCountriesQueries
);
+const selectHttpByType = (state: State, networkType: NetworkType) => {
+ const httpType =
+ networkType === NetworkType.page ? NetworkTableType.http : IpDetailsTableType.http;
+ return (
+ get([networkType, 'queries', httpType], state.network) ||
+ get([networkType, 'queries', httpType], initialNetworkState)
+ );
+};
+
+export const httpSelector = () =>
+ createSelector(
+ selectHttpByType,
+ httpQueries => httpQueries
+ );
+
// IP Details Selectors
export const ipDetailsFlowTargetSelector = () =>
createSelector(
diff --git a/x-pack/legacy/plugins/siem/public/store/timeline/epic_note.ts b/x-pack/legacy/plugins/siem/public/store/timeline/epic_note.ts
index 1c9493ceba9c3..e5a712fe2c666 100644
--- a/x-pack/legacy/plugins/siem/public/store/timeline/epic_note.ts
+++ b/x-pack/legacy/plugins/siem/public/store/timeline/epic_note.ts
@@ -127,9 +127,8 @@ export const epicPersistNote = (
export const createTimelineNoteEpic = (): Epic => action$ =>
action$.pipe(
- withLatestFrom(),
- filter(([action]) => timelineNoteActionsType.includes(action.type)),
- switchMap(([action]) => {
+ filter(action => timelineNoteActionsType.includes(action.type)),
+ switchMap(action => {
dispatcherTimelinePersistQueue.next({ action });
return empty();
})
diff --git a/x-pack/legacy/plugins/siem/scripts/convert_saved_search_to_signals.js b/x-pack/legacy/plugins/siem/scripts/convert_saved_search_to_signals.js
index 78281efa09e52..5692ce2721870 100644
--- a/x-pack/legacy/plugins/siem/scripts/convert_saved_search_to_signals.js
+++ b/x-pack/legacy/plugins/siem/scripts/convert_saved_search_to_signals.js
@@ -30,7 +30,7 @@ const path = require('path');
// into another repository.
const INTERVAL = '24h';
const SEVERITY = 'low';
-const TYPE = 'kql';
+const TYPE = 'query';
const FROM = 'now-24h';
const TO = 'now';
const INDEX = ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'];
@@ -70,43 +70,74 @@ async function main() {
const files = process.argv[2];
const outputDir = process.argv[3];
- const savedSearchesJson = walk(files).filter(file => file.endsWith('.ndjson'));
+ const savedSearchesJson = walk(files).filter(file => {
+ return !path.basename(file).startsWith('.') && file.endsWith('.ndjson');
+ });
const savedSearchesParsed = savedSearchesJson.reduce((accum, json) => {
const jsonFile = fs.readFileSync(json, 'utf8');
- try {
- const parsedFile = JSON.parse(jsonFile);
- parsedFile._file = json;
- parsedFile.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.parse(
- parsedFile.attributes.kibanaSavedObjectMeta.searchSourceJSON
- );
- return [...accum, parsedFile];
- } catch (err) {
- return accum;
- }
+ const jsonLines = jsonFile.split(/\r{0,1}\n/);
+ const parsedLines = jsonLines.reduce((accum, line, index) => {
+ try {
+ const parsedLine = JSON.parse(line);
+ if (index !== 0) {
+ parsedLine._file = `${json.substring(0, json.length - '.ndjson'.length)}_${String(
+ index
+ )}.ndjson`;
+ } else {
+ parsedLine._file = json;
+ }
+ parsedLine.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.parse(
+ parsedLine.attributes.kibanaSavedObjectMeta.searchSourceJSON
+ );
+ return [...accum, parsedLine];
+ } catch (err) {
+ console.log('error parsing a line in this file:', json);
+ return accum;
+ }
+ }, []);
+ return [...accum, ...parsedLines];
}, []);
- savedSearchesParsed.forEach(savedSearch => {
- const fileToWrite = cleanupFileName(savedSearch._file);
+ savedSearchesParsed.forEach(
+ ({
+ _file,
+ attributes: {
+ description,
+ title,
+ kibanaSavedObjectMeta: {
+ searchSourceJSON: {
+ query: { query, language },
+ filter,
+ },
+ },
+ },
+ }) => {
+ const fileToWrite = cleanupFileName(_file);
- const query = savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON.query.query;
- if (query != null && query.trim() !== '') {
- const outputMessage = {
- id: fileToWrite,
- description: savedSearch.attributes.description || savedSearch.attributes.title,
- index: INDEX,
- interval: INTERVAL,
- name: savedSearch.attributes.title,
- severity: SEVERITY,
- type: TYPE,
- from: FROM,
- to: TO,
- kql: savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON.query.query,
- };
+ if (query != null && query.trim() !== '') {
+ const outputMessage = {
+ id: fileToWrite,
+ description: description || title,
+ index: INDEX,
+ interval: INTERVAL,
+ name: title,
+ severity: SEVERITY,
+ type: TYPE,
+ from: FROM,
+ to: TO,
+ query,
+ language,
+ filters: filter,
+ };
- fs.writeFileSync(`${outputDir}/${fileToWrite}.json`, JSON.stringify(outputMessage, null, 2));
+ fs.writeFileSync(
+ `${outputDir}/${fileToWrite}.json`,
+ JSON.stringify(outputMessage, null, 2)
+ );
+ }
}
- });
+ );
}
if (require.main === module) {
diff --git a/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts
index 7ce88ba4880be..db15babc42a72 100644
--- a/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts
+++ b/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts
@@ -20,6 +20,11 @@ type QueryNetworkTopNFlowResolver = ChildResolverOf<
QuerySourceResolver
>;
+type QueryNetworkHttpResolver = ChildResolverOf<
+ AppResolverOf,
+ QuerySourceResolver
+>;
+
type QueryDnsResolver = ChildResolverOf<
AppResolverOf,
QuerySourceResolver
@@ -33,6 +38,7 @@ export const createNetworkResolvers = (
libs: NetworkResolversDeps
): {
Source: {
+ NetworkHttp: QueryNetworkHttpResolver;
NetworkTopCountries: QueryNetworkTopCountriesResolver;
NetworkTopNFlow: QueryNetworkTopNFlowResolver;
NetworkDns: QueryDnsResolver;
@@ -57,6 +63,14 @@ export const createNetworkResolvers = (
};
return libs.network.getNetworkTopNFlow(req, options);
},
+ async NetworkHttp(source, args, { req }, info) {
+ const options = {
+ ...createOptionsPaginated(source, args, info),
+ networkHttpSort: args.sort,
+ ip: args.ip,
+ };
+ return libs.network.getNetworkHttp(req, options);
+ },
async NetworkDns(source, args, { req }, info) {
const options = {
...createOptionsPaginated(source, args, info),
diff --git a/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts
index 36b57ec9368ab..84f8d004198e9 100644
--- a/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts
+++ b/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts
@@ -152,6 +152,43 @@ export const networkSchema = gql`
inspect: Inspect
}
+ enum NetworkHttpFields {
+ domains
+ lastHost
+ lastSourceIp
+ methods
+ path
+ requestCount
+ statuses
+ }
+
+ input NetworkHttpSortField {
+ direction: Direction!
+ }
+
+ type NetworkHttpItem {
+ _id: String
+ domains: [String!]!
+ lastHost: String
+ lastSourceIp: String
+ methods: [String!]!
+ path: String
+ requestCount: Float
+ statuses: [String!]!
+ }
+
+ type NetworkHttpEdges {
+ node: NetworkHttpItem!
+ cursor: CursorType!
+ }
+
+ type NetworkHttpData {
+ edges: [NetworkHttpEdges!]!
+ totalCount: Float!
+ pageInfo: PageInfoPaginated!
+ inspect: Inspect
+ }
+
extend type Source {
NetworkTopCountries(
id: String
@@ -182,5 +219,14 @@ export const networkSchema = gql`
timerange: TimerangeInput!
defaultIndex: [String!]!
): NetworkDnsData!
+ NetworkHttp(
+ id: String
+ filterQuery: String
+ ip: String
+ pagination: PaginationInputPaginated!
+ sort: NetworkHttpSortField!
+ timerange: TimerangeInput!
+ defaultIndex: [String!]!
+ ): NetworkHttpData!
}
`;
diff --git a/x-pack/legacy/plugins/siem/server/graphql/types.ts b/x-pack/legacy/plugins/siem/server/graphql/types.ts
index 6de11e0652871..cf7ce3ad02fa1 100644
--- a/x-pack/legacy/plugins/siem/server/graphql/types.ts
+++ b/x-pack/legacy/plugins/siem/server/graphql/types.ts
@@ -87,6 +87,10 @@ export interface NetworkDnsSortField {
direction: Direction;
}
+export interface NetworkHttpSortField {
+ direction: Direction;
+}
+
export interface TlsSortField {
field: TlsFields;
@@ -296,6 +300,16 @@ export enum NetworkDirectionEcs {
unknown = 'unknown',
}
+export enum NetworkHttpFields {
+ domains = 'domains',
+ lastHost = 'lastHost',
+ lastSourceIp = 'lastSourceIp',
+ methods = 'methods',
+ path = 'path',
+ requestCount = 'requestCount',
+ statuses = 'statuses',
+}
+
export enum FlowDirection {
uniDirectional = 'uniDirectional',
biDirectional = 'biDirectional',
@@ -435,6 +449,8 @@ export interface Source {
NetworkDns: NetworkDnsData;
+ NetworkHttp: NetworkHttpData;
+
OverviewNetwork?: Maybe;
OverviewHost?: Maybe;
@@ -1590,6 +1606,40 @@ export interface NetworkDnsItem {
uniqueDomains?: Maybe;
}
+export interface NetworkHttpData {
+ edges: NetworkHttpEdges[];
+
+ totalCount: number;
+
+ pageInfo: PageInfoPaginated;
+
+ inspect?: Maybe;
+}
+
+export interface NetworkHttpEdges {
+ node: NetworkHttpItem;
+
+ cursor: CursorType;
+}
+
+export interface NetworkHttpItem {
+ _id?: Maybe;
+
+ domains: string[];
+
+ lastHost?: Maybe;
+
+ lastSourceIp?: Maybe;
+
+ methods: string[];
+
+ path?: Maybe;
+
+ requestCount?: Maybe;
+
+ statuses: string[];
+}
+
export interface OverviewNetworkData {
auditbeatSocket?: Maybe;
@@ -2164,6 +2214,21 @@ export interface NetworkDnsSourceArgs {
defaultIndex: string[];
}
+export interface NetworkHttpSourceArgs {
+ id?: Maybe;
+
+ filterQuery?: Maybe;
+
+ ip?: Maybe;
+
+ pagination: PaginationInputPaginated;
+
+ sort: NetworkHttpSortField;
+
+ timerange: TimerangeInput;
+
+ defaultIndex: string[];
+}
export interface OverviewNetworkSourceArgs {
id?: Maybe;
@@ -2643,6 +2708,8 @@ export namespace SourceResolvers {
NetworkDns?: NetworkDnsResolver;
+ NetworkHttp?: NetworkHttpResolver