diff --git a/config/kibana.yml b/config/kibana.yml
index 495d2030083d..aac314c09cb3 100644
--- a/config/kibana.yml
+++ b/config/kibana.yml
@@ -44,7 +44,7 @@
# the username and password that the Kibana server uses to perform maintenance on the Kibana
# index at startup. Your Kibana users still need to authenticate with Elasticsearch, which
# is proxied through the Kibana server.
-#elasticsearch.username: "user"
+#elasticsearch.username: "kibana"
#elasticsearch.password: "pass"
# Enables SSL and paths to the PEM-format SSL certificate and SSL key files, respectively.
diff --git a/docs/ml/creating-jobs.asciidoc b/docs/ml/creating-jobs.asciidoc
index 181de3ea97b6..d88df4d8e14e 100644
--- a/docs/ml/creating-jobs.asciidoc
+++ b/docs/ml/creating-jobs.asciidoc
@@ -46,13 +46,12 @@ These wizards create {ml} jobs, dashboards, searches, and visualizations that
are customized to help you analyze your {auditbeat} and {filebeat} data.
If you are not certain which type of job to create, you can use the
-*Data Visualizer* to learn more about your data and to identify possible fields
-for {ml} analysis.
+*Data Visualizer* to learn more about your data. If your index pattern contains
+a time field, it can identify possible fields for {ml} analysis.
[NOTE]
===============================
-* If your index pattern does not contain a time field, you cannot use the *Data Visualizer*.
-* If your data is located outside of {es}, you cannot use {kib} to create
+If your data is located outside of {es}, you cannot use {kib} to create
your jobs and you cannot use {dfeeds} to retrieve your data in real time.
Machine learning analysis is still possible, however, by using APIs to
create and manage jobs and post data to them. For more information, see
diff --git a/docs/ml/index.asciidoc b/docs/ml/index.asciidoc
index 95d3f55da21d..a7571be6d70f 100644
--- a/docs/ml/index.asciidoc
+++ b/docs/ml/index.asciidoc
@@ -16,8 +16,9 @@ The {ml-features} run in and scale with {es}, and include an
intuitive UI on the {kib} *Machine Learning* page for creating anomaly detection
jobs and understanding results.
-If you have a basic license, you can use the *Data Visualizer* to learn more
-about the data that you've stored in {es} and to identify possible fields for
+If you have a basic license, you can use the *Data Visualizer* to learn more
+about your data. In particular, if your data is stored in {es} and contains a
+time field, you can use the *Data Visualizer* to identify possible fields for
{ml} analysis:
[role="screenshot"]
diff --git a/docs/security/authorization/index.asciidoc b/docs/security/authorization/index.asciidoc
index 788afedaeb5f..6fc0f3f1367d 100644
--- a/docs/security/authorization/index.asciidoc
+++ b/docs/security/authorization/index.asciidoc
@@ -20,7 +20,7 @@ To assign {kib} privileges to the role, click **Add space privilege** in the Kib
[role="screenshot"]
image::security/images/add-space-privileges.png[Add space privileges]
-Open the **Spaces** dropdown menu to specify whether to grant the role access to all spaces *** Global (all spaces)** or one or more individual spaces. If you select *** Global (all spaces)**, you can’t select individual spaces until you clear your selection.
+Open the **Spaces** selection control to specify whether to grant the role access to all spaces *** Global (all spaces)** or one or more individual spaces. If you select *** Global (all spaces)**, you can’t select individual spaces until you clear your selection.
Use the **Privilege** menu to grant access to features. The default is **Custom**, which you can use to grant access to individual features. Otherwise, you can grant read and write access to all current and future features by selecting **All**, or grant read access to all current and future features by selecting **Read**.
@@ -39,7 +39,7 @@ image::security/images/create-space-privilege.png[Create space privilege]
==== Assigning different privileges to different spaces
-Using the same role, it’s possible to assign different privileges to different spaces. After you’ve added space privileges, click **Add space privilege**. If you’ve already added privileges for either *** Global (all spaces)** or an individual space, you will not be able to select these in the **Spaces** control.
+Using the same role, it’s possible to assign different privileges to different spaces. After you’ve added space privileges, click **Add space privilege**. If you’ve already added privileges for either *** Global (all spaces)** or an individual space, you will not be able to select these in the **Spaces** selection control.
Additionally, if you’ve already assigned privileges at *** Global (all spaces)**, you are only able to assign additional privileges to individual spaces. Similar to the behavior of multiple roles granting the union of all privileges, space privileges are also a union. If you’ve already granted the user the **All** privilege at *** Global (all spaces)**, you’re not able to restrict the role to only the **Read** privilege at an individual space.
diff --git a/package.json b/package.json
index 4680edea5f34..5a629c46f6e1 100644
--- a/package.json
+++ b/package.json
@@ -104,7 +104,7 @@
"@babel/register": "7.4.4",
"@elastic/charts": "^4.2.6",
"@elastic/datemath": "5.0.2",
- "@elastic/eui": "10.4.1",
+ "@elastic/eui": "11.0.1",
"@elastic/filesaver": "1.1.2",
"@elastic/good": "8.1.1-kibana2",
"@elastic/numeral": "2.3.3",
@@ -145,17 +145,17 @@
"core-js": "2.6.9",
"css-loader": "1.0.0",
"custom-event-polyfill": "^0.3.0",
- "d3": "3.5.6",
- "d3-cloud": "1.2.1",
+ "d3": "3.5.17",
+ "d3-cloud": "1.2.5",
"del": "^4.0.0",
"dragula": "3.7.2",
"elasticsearch": "^15.5.0",
"elasticsearch-browser": "^15.5.0",
- "encode-uri-query": "1.0.0",
+ "encode-uri-query": "1.0.1",
"execa": "^1.0.0",
"expiry-js": "0.1.7",
"file-loader": "2.0.0",
- "font-awesome": "4.4.0",
+ "font-awesome": "4.7.0",
"getos": "^3.1.0",
"glob": "^7.1.2",
"glob-all": "^3.1.0",
@@ -165,37 +165,37 @@
"handlebars": "4.1.2",
"hapi": "^17.5.3",
"hapi-auth-cookie": "^9.0.0",
- "hjson": "3.1.0",
+ "hjson": "3.1.2",
"hoek": "^5.0.4",
"http-proxy-agent": "^2.1.0",
"https-proxy-agent": "^2.2.1",
"inert": "^5.1.0",
"joi": "^13.5.2",
"jquery": "^3.4.1",
- "js-yaml": "3.4.1",
+ "js-yaml": "3.13.1",
"json-stable-stringify": "^1.0.1",
- "json-stringify-pretty-compact": "1.0.4",
+ "json-stringify-pretty-compact": "1.2.0",
"json-stringify-safe": "5.0.1",
"leaflet": "1.0.3",
- "leaflet-draw": "0.4.10",
- "leaflet-responsive-popup": "0.2.0",
+ "leaflet-draw": "0.4.14",
+ "leaflet-responsive-popup": "0.6.4",
"leaflet-vega": "^0.8.6",
"leaflet.heat": "0.2.0",
"less": "^2.7.3",
"less-loader": "4.1.0",
"lodash": "npm:@elastic/lodash@3.10.1-kibana1",
"lodash.clonedeep": "^4.5.0",
- "lru-cache": "4.1.1",
+ "lru-cache": "4.1.5",
"markdown-it": "^8.4.1",
"mini-css-extract-plugin": "0.4.4",
"minimatch": "^3.0.4",
"mkdirp": "0.5.1",
"moment": "^2.20.1",
"moment-timezone": "^0.5.14",
- "mustache": "2.3.0",
+ "mustache": "2.3.2",
"ngreact": "0.5.1",
"no-ui-slider": "1.2.0",
- "node-fetch": "1.3.2",
+ "node-fetch": "1.7.3",
"opn": "^5.4.0",
"oppsy": "^2.0.0",
"pegjs": "0.9.0",
@@ -258,6 +258,7 @@
},
"devDependencies": {
"@babel/parser": "7.4.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/types": "7.4.4",
"@elastic/eslint-config-kibana": "0.15.0",
"@elastic/github-checks-reporter": "0.0.15",
@@ -268,7 +269,7 @@
"@kbn/expect": "1.0.0",
"@kbn/plugin-generator": "1.0.0",
"@kbn/test": "1.0.0",
- "@microsoft/api-documenter": "7.0.49",
+ "@microsoft/api-documenter": "7.2.1",
"@microsoft/api-extractor": "7.1.1",
"@octokit/rest": "^15.10.0",
"@types/angular": "1.6.50",
@@ -287,7 +288,7 @@
"@types/enzyme": "^3.1.12",
"@types/eslint": "^4.16.6",
"@types/execa": "^0.9.0",
- "@types/fetch-mock": "7.2.1",
+ "@types/fetch-mock": "7.3.0",
"@types/getopts": "^2.0.1",
"@types/glob": "^7.1.1",
"@types/globby": "^8.0.0",
@@ -302,7 +303,7 @@
"@types/jquery": "^3.3.6",
"@types/js-yaml": "^3.11.1",
"@types/json5": "^0.0.30",
- "@types/listr": "^0.13.0",
+ "@types/listr": "^0.14.0",
"@types/lodash": "^3.10.1",
"@types/lru-cache": "^5.1.0",
"@types/minimatch": "^2.0.29",
@@ -338,6 +339,7 @@
"archiver": "^3.0.0",
"babel-eslint": "10.0.1",
"babel-jest": "^24.1.0",
+ "babel-plugin-dynamic-import-node": "^2.2.0",
"backport": "4.5.5",
"chai": "3.5.0",
"chance": "1.0.18",
@@ -366,7 +368,7 @@
"eslint-plugin-react-hooks": "1.6.0",
"exit-hook": "^2.1.0",
"faker": "1.1.0",
- "fetch-mock": "7.3.0",
+ "fetch-mock": "7.3.3",
"geckodriver": "1.13.0",
"getopts": "^2.2.4",
"grunt": "1.0.4",
@@ -378,7 +380,7 @@
"gulp-babel": "8.0.0",
"gulp-sourcemaps": "2.6.5",
"has-ansi": "^3.0.0",
- "image-diff": "1.6.0",
+ "image-diff": "1.6.3",
"intl-messageformat-parser": "^1.4.0",
"is-path-inside": "^2.0.0",
"istanbul-instrumenter-loader": "3.0.1",
@@ -386,7 +388,7 @@
"jest-cli": "^24.1.0",
"jest-dom": "^3.1.3",
"jest-raw-loader": "^1.0.1",
- "jimp": "0.6.0",
+ "jimp": "0.6.4",
"json5": "^1.0.1",
"karma": "3.1.4",
"karma-chrome-launcher": "2.2.0",
diff --git a/packages/eslint-config-kibana/.eslintrc.js b/packages/eslint-config-kibana/.eslintrc.js
index 6d39eb98ddb4..c3e8f5601e47 100644
--- a/packages/eslint-config-kibana/.eslintrc.js
+++ b/packages/eslint-config-kibana/.eslintrc.js
@@ -7,11 +7,11 @@ module.exports = {
plugins: ['@kbn/eslint-plugin-eslint'],
parserOptions: {
- ecmaVersion: 6
+ ecmaVersion: 2018
},
env: {
- es6: true
+ es6: true,
},
rules: {
diff --git a/packages/eslint-config-kibana/javascript.js b/packages/eslint-config-kibana/javascript.js
index a5433fa6b5d9..f1ed905779fb 100644
--- a/packages/eslint-config-kibana/javascript.js
+++ b/packages/eslint-config-kibana/javascript.js
@@ -44,8 +44,7 @@ module.exports = {
parserOptions: {
sourceType: 'module',
- ecmaVersion: 6,
- ecmaFeatures: { experimentalObjectRestSpread: true },
+ ecmaVersion: 2018,
},
rules: {
diff --git a/packages/eslint-config-kibana/typescript.js b/packages/eslint-config-kibana/typescript.js
index 9bce8503d32f..26a5db48d6c2 100644
--- a/packages/eslint-config-kibana/typescript.js
+++ b/packages/eslint-config-kibana/typescript.js
@@ -42,9 +42,8 @@ module.exports = {
parserOptions: {
sourceType: 'module',
- ecmaVersion: 6,
+ ecmaVersion: 2018,
ecmaFeatures: {
- experimentalObjectRestSpread: true,
jsx: true
},
// NOTE: That is to avoid a known performance issue related with the `ts.Program` used by
diff --git a/packages/kbn-eslint-plugin-eslint/rules/__tests__/disallow_license_headers.js b/packages/kbn-eslint-plugin-eslint/rules/__tests__/disallow_license_headers.js
index 61fc1c112b8b..0bf71d717bad 100644
--- a/packages/kbn-eslint-plugin-eslint/rules/__tests__/disallow_license_headers.js
+++ b/packages/kbn-eslint-plugin-eslint/rules/__tests__/disallow_license_headers.js
@@ -24,7 +24,7 @@ const dedent = require('dedent');
const ruleTester = new RuleTester({
parser: 'babel-eslint',
parserOptions: {
- ecmaVersion: 2015,
+ ecmaVersion: 2018,
},
});
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 33d178519d06..11f01a1777ab 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
@@ -35,7 +35,7 @@ const ruleTester = new RuleTester({
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module',
- ecmaVersion: 2015,
+ ecmaVersion: 2018,
},
});
diff --git a/packages/kbn-eslint-plugin-eslint/rules/__tests__/require_license_header.js b/packages/kbn-eslint-plugin-eslint/rules/__tests__/require_license_header.js
index 491ceb2290be..984c090ceb06 100644
--- a/packages/kbn-eslint-plugin-eslint/rules/__tests__/require_license_header.js
+++ b/packages/kbn-eslint-plugin-eslint/rules/__tests__/require_license_header.js
@@ -24,7 +24,7 @@ const dedent = require('dedent');
const ruleTester = new RuleTester({
parser: 'babel-eslint',
parserOptions: {
- ecmaVersion: 2015,
+ ecmaVersion: 2018,
},
});
diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json
index 2c64b560c81e..58b1e10507db 100644
--- a/packages/kbn-plugin-helpers/package.json
+++ b/packages/kbn-plugin-helpers/package.json
@@ -19,7 +19,7 @@
"globby": "^8.0.1",
"gulp-babel": "^8.0.0",
"gulp-rename": "1.4.0",
- "gulp-zip": "4.1.0",
+ "gulp-zip": "4.2.0",
"inquirer": "^1.2.2",
"minimatch": "^3.0.4",
"node-sass": "^4.9.4",
diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json
index ed596d341b02..32c9c9173ed6 100644
--- a/packages/kbn-pm/package.json
+++ b/packages/kbn-pm/package.json
@@ -33,7 +33,7 @@
"@types/read-pkg": "^3.0.0",
"@types/strip-ansi": "^3.0.0",
"@types/strong-log-transformer": "^1.0.0",
- "@types/tempy": "^0.1.0",
+ "@types/tempy": "^0.2.0",
"@types/wrap-ansi": "^2.0.14",
"@types/write-pkg": "^3.1.0",
"babel-loader": "8.0.5",
@@ -60,7 +60,7 @@
"string-replace-loader": "^2.1.1",
"strip-ansi": "^4.0.0",
"strong-log-transformer": "^2.1.0",
- "tempy": "^0.2.1",
+ "tempy": "^0.3.0",
"typescript": "^3.3.3333",
"unlazy-loader": "^0.1.3",
"webpack": "^4.23.1",
diff --git a/renovate.json5 b/renovate.json5
index 35c225b664fa..bb5faa01bee1 100644
--- a/renovate.json5
+++ b/renovate.json5
@@ -106,6 +106,12 @@
groupName: 'grunt related packages',
groupSlug: 'grunt',
},
+ {
+ packagePatterns: ['\\bangular\\b'],
+ groupName: 'angular related packages',
+ groupSlug: 'angular',
+ recreateClosed: false,
+ },
{
packagePatterns: ['\\bd3\\b'],
groupName: 'd3 related packages',
diff --git a/src/core/public/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json b/src/core/public/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json
index 64fcbf1f7488..12307c46b95f 100644
--- a/src/core/public/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json
+++ b/src/core/public/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json
@@ -3,7 +3,7 @@
"strict": true,
"skipLibCheck": true,
"lib": [
- "esnext"
+ "es2018"
]
},
"files": [
diff --git a/src/dev/jest/babel_transform.js b/src/dev/jest/babel_transform.js
index 0796cf859d4e..c31843313731 100644
--- a/src/dev/jest/babel_transform.js
+++ b/src/dev/jest/babel_transform.js
@@ -23,4 +23,9 @@ module.exports = babelJest.createTransformer({
presets: [
require.resolve('@kbn/babel-preset/node_preset')
],
+ plugins: [
+ // enables jest to parse and execute dynamic import() calls
+ '@babel/plugin-syntax-dynamic-import',
+ 'dynamic-import-node'
+ ]
});
diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js
index 2c71b354e520..e1a0c4a87392 100644
--- a/src/dev/jest/config.js
+++ b/src/dev/jest/config.js
@@ -88,7 +88,8 @@ export default {
'^.+\\.html?$': 'jest-raw-loader',
},
transformIgnorePatterns: [
- '[/\\\\]node_modules[/\\\\].+\\.js$',
+ // ignore all node_modules except @elastic/eui which requires babel transforms to handle dynamic import()
+ '[/\\\\]node_modules(?![\\/\\\\]@elastic[\\/\\\\]eui)[/\\\\].+\\.js$',
'packages/kbn-pm/dist/index.js'
],
snapshotSerializers: [
diff --git a/src/dev/license_checker/config.js b/src/dev/license_checker/config.js
index 6c72c918279d..e8adfc90c438 100644
--- a/src/dev/license_checker/config.js
+++ b/src/dev/license_checker/config.js
@@ -60,7 +60,7 @@ export const LICENSE_WHITELIST = [
'MIT*',
'MIT/X11',
'new BSD, and MIT',
- 'OFL-1.1 AND MIT',
+ '(OFL-1.1 AND MIT)',
'Public Domain',
'Unlicense',
'WTFPL OR ISC',
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/panel/__snapshots__/dashboard_panel.test.tsx.snap b/src/legacy/core_plugins/kibana/public/dashboard/panel/__snapshots__/dashboard_panel.test.tsx.snap
index 747b92bb5a5d..107bda0aea08 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/panel/__snapshots__/dashboard_panel.test.tsx.snap
+++ b/src/legacy/core_plugins/kibana/public/dashboard/panel/__snapshots__/dashboard_panel.test.tsx.snap
@@ -33,24 +33,13 @@ exports[`DashboardPanel matches snapshot 1`] = `
>
+ />
diff --git a/src/legacy/core_plugins/kibana/public/discover/directives/__snapshots__/no_results.test.js.snap b/src/legacy/core_plugins/kibana/public/discover/directives/__snapshots__/no_results.test.js.snap
index ebc27316d467..9f400e54899a 100644
--- a/src/legacy/core_plugins/kibana/public/discover/directives/__snapshots__/no_results.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/discover/directives/__snapshots__/no_results.test.js.snap
@@ -20,25 +20,13 @@ Array [
>
+ />
@@ -156,21 +148,14 @@ exports[`Storyshots components/Asset airplane 1`] = `
>
+ />
@@ -194,25 +179,14 @@ exports[`Storyshots components/Asset airplane 1`] = `
>
+ />
@@ -303,18 +277,14 @@ exports[`Storyshots components/Asset marker 1`] = `
>
+ />
@@ -340,18 +310,14 @@ exports[`Storyshots components/Asset marker 1`] = `
>
+ />
@@ -378,21 +344,14 @@ exports[`Storyshots components/Asset marker 1`] = `
>
+ />
@@ -416,25 +375,14 @@ exports[`Storyshots components/Asset marker 1`] = `
>
+ />
diff --git a/x-pack/plugins/canvas/public/components/color_dot/__examples__/__snapshots__/color_dot.examples.storyshot b/x-pack/plugins/canvas/public/components/color_dot/__examples__/__snapshots__/color_dot.examples.storyshot
index 45f32e571f2c..acdcf8689da7 100644
--- a/x-pack/plugins/canvas/public/components/color_dot/__examples__/__snapshots__/color_dot.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/color_dot/__examples__/__snapshots__/color_dot.examples.storyshot
@@ -82,23 +82,18 @@ Array [
}
>
+ />
,
,
,
,
]
diff --git a/x-pack/plugins/canvas/public/components/color_manager/__examples__/__snapshots__/color_manager.examples.storyshot b/x-pack/plugins/canvas/public/components/color_manager/__examples__/__snapshots__/color_manager.examples.storyshot
index a5811a60040c..9e6db06e5a4d 100644
--- a/x-pack/plugins/canvas/public/components/color_manager/__examples__/__snapshots__/color_manager.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/color_manager/__examples__/__snapshots__/color_manager.examples.storyshot
@@ -202,19 +202,14 @@ exports[`Storyshots components/ColorManager interactive 1`] = `
>
+ />
@@ -415,19 +405,14 @@ Array [
>
+ />
,
@@ -512,19 +492,14 @@ Array [
>
+ />
,
@@ -609,19 +579,14 @@ Array [
>
+ />
,
diff --git a/x-pack/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.examples.storyshot b/x-pack/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.examples.storyshot
index ad84c2e54458..14dec33ad073 100644
--- a/x-pack/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.examples.storyshot
@@ -364,23 +364,18 @@ Array [
}
>
+ />
@@ -718,23 +713,18 @@ exports[`Storyshots components/ColorPalette six colors, wrap at 4 1`] = `
}
>
+ />
@@ -995,23 +985,18 @@ Array [
}
>
+ />
diff --git a/x-pack/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.examples.storyshot b/x-pack/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.examples.storyshot
index ccdb666dd77c..c2f4781d4956 100644
--- a/x-pack/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.examples.storyshot
@@ -221,19 +221,14 @@ exports[`Storyshots components/ColorPicker interactive 1`] = `
>
+ />
@@ -317,23 +307,18 @@ exports[`Storyshots components/ColorPicker six colors 1`] = `
}
>
+ />
@@ -527,19 +512,14 @@ exports[`Storyshots components/ColorPicker six colors 1`] = `
>
+ />
@@ -793,19 +768,14 @@ exports[`Storyshots components/ColorPicker six colors, value missing 1`] = `
>
+ />
@@ -868,23 +833,18 @@ exports[`Storyshots components/ColorPicker three colors 1`] = `
}
>
+ />
@@ -1000,19 +960,14 @@ exports[`Storyshots components/ColorPicker three colors 1`] = `
>
+ />
diff --git a/x-pack/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot b/x-pack/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot
index 4fac77ebf47e..42eefbb1feb3 100644
--- a/x-pack/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot
@@ -56,18 +56,14 @@ Array [
>
+ />
+ />
@@ -244,22 +236,14 @@ Array [
className="euiCard__top"
>
+ />
+ />
+ />
@@ -753,18 +729,14 @@ Array [
>
+ />
+ />
@@ -941,22 +909,14 @@ Array [
className="euiCard__top"
>
+ />
+ />
+ />
@@ -1294,22 +1246,14 @@ Array [
className="euiCard__top"
>
+ />
+ />
+ />
+ />
+ />
@@ -71,25 +60,14 @@ exports[`Storyshots components/ElementTypes/ElementControls has two buttons 1`]
>
+ />
diff --git a/x-pack/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot b/x-pack/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot
index 8748623b2377..cd66f2897544 100644
--- a/x-pack/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot
@@ -71,25 +71,14 @@ exports[`Storyshots components/ElementTypes/ElementGrid with controls 1`] = `
>
+ />
@@ -112,25 +101,14 @@ exports[`Storyshots components/ElementTypes/ElementGrid with controls 1`] = `
>
+ />
@@ -196,25 +174,14 @@ exports[`Storyshots components/ElementTypes/ElementGrid with controls 1`] = `
>
+ />
@@ -237,25 +204,14 @@ exports[`Storyshots components/ElementTypes/ElementGrid with controls 1`] = `
>
+ />
@@ -321,25 +277,14 @@ exports[`Storyshots components/ElementTypes/ElementGrid with controls 1`] = `
>
+ />
@@ -362,25 +307,14 @@ exports[`Storyshots components/ElementTypes/ElementGrid with controls 1`] = `
>
+ />
@@ -461,25 +395,14 @@ exports[`Storyshots components/ElementTypes/ElementGrid with controls and filter
>
+ />
@@ -502,25 +425,14 @@ exports[`Storyshots components/ElementTypes/ElementGrid with controls and filter
>
+ />
diff --git a/x-pack/plugins/canvas/public/components/file_upload/__snapshots__/file_upload.examples.storyshot b/x-pack/plugins/canvas/public/components/file_upload/__snapshots__/file_upload.examples.storyshot
index dba0a6bef464..097dad3cf089 100644
--- a/x-pack/plugins/canvas/public/components/file_upload/__snapshots__/file_upload.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/file_upload/__snapshots__/file_upload.examples.storyshot
@@ -21,18 +21,14 @@ exports[`Storyshots components/FileUpload default 1`] = `
>
+ />
diff --git a/x-pack/plugins/canvas/public/components/font_picker/__snapshots__/font_picker.examples.storyshot b/x-pack/plugins/canvas/public/components/font_picker/__snapshots__/font_picker.examples.storyshot
index c7a5afedda7e..7c433bdb983d 100644
--- a/x-pack/plugins/canvas/public/components/font_picker/__snapshots__/font_picker.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/font_picker/__snapshots__/font_picker.examples.storyshot
@@ -48,26 +48,14 @@ exports[`Storyshots components/FontPicker default 1`] = `
>
+ />
@@ -142,26 +130,14 @@ exports[`Storyshots components/FontPicker with value 1`] = `
>
+ />
diff --git a/x-pack/plugins/canvas/public/components/item_grid/__examples__/__snapshots__/item_grid.examples.storyshot b/x-pack/plugins/canvas/public/components/item_grid/__examples__/__snapshots__/item_grid.examples.storyshot
index 965a7dd9bfb6..79b547102b08 100644
--- a/x-pack/plugins/canvas/public/components/item_grid/__examples__/__snapshots__/item_grid.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/item_grid/__examples__/__snapshots__/item_grid.examples.storyshot
@@ -71,23 +71,18 @@ exports[`Storyshots components/ItemGrid complex grid 1`] = `
}
>
+ />
@@ -166,47 +151,32 @@ exports[`Storyshots components/ItemGrid icon grid 1`] = `
className="item-grid-row"
>
+ />
+ />
+ />
`;
diff --git a/x-pack/plugins/canvas/public/components/item_grid/__examples__/item_grid.examples.tsx b/x-pack/plugins/canvas/public/components/item_grid/__examples__/item_grid.examples.tsx
index 632e238d1868..94340888eafc 100644
--- a/x-pack/plugins/canvas/public/components/item_grid/__examples__/item_grid.examples.tsx
+++ b/x-pack/plugins/canvas/public/components/item_grid/__examples__/item_grid.examples.tsx
@@ -16,8 +16,8 @@ storiesOf('components/ItemGrid', module)
))
.add('icon grid', () => (
}
+ items={['plusInCircle', 'minusInCircle', 'check']}
+ children={item => }
/>
))
.add('color dot grid', () => (
diff --git a/x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot b/x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot
index 3f8ae898f5cb..939f3fd77753 100644
--- a/x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot
@@ -57,18 +57,14 @@ exports[`Storyshots components/KeyboardShortcutsDoc default 1`] = `
>
+ />
@@ -92,25 +88,14 @@ exports[`Storyshots components/SidebarHeader/ default 1`] = `
>
+ />
@@ -167,18 +152,14 @@ exports[`Storyshots components/SidebarHeader/ without layer controls 1`] = `
>
+ />
@@ -214,25 +195,14 @@ exports[`Storyshots components/SidebarHeader/ without layer controls 1`] = `
>
+ />
diff --git a/x-pack/plugins/canvas/public/components/tag/__examples__/__snapshots__/tag.examples.storyshot b/x-pack/plugins/canvas/public/components/tag/__examples__/__snapshots__/tag.examples.storyshot
index c1a8ea30eb60..0d4fa0dcb50d 100644
--- a/x-pack/plugins/canvas/public/components/tag/__examples__/__snapshots__/tag.examples.storyshot
+++ b/x-pack/plugins/canvas/public/components/tag/__examples__/__snapshots__/tag.examples.storyshot
@@ -55,31 +55,18 @@ exports[`Storyshots components/Tag as health 1`] = `
className="euiFlexItem euiFlexItem--flexGrowZero"
>
+ />
+ />
+ />
+ />
+ />
{
(e.target.type === monaco.editor.MouseTargetType.GUTTER_LINE_NUMBERS ||
e.target.type === monaco.editor.MouseTargetType.CONTENT_TEXT)
) {
- const lineNumber = (this.props.startLine || 0) + e.target.position.lineNumber;
+ const position = e.target.position || { lineNumber: 0, column: 0 };
+ const lineNumber = (this.props.startLine || 0) + position.lineNumber;
this.props.onClick({
lineNumber,
- column: e.target.position.column,
+ column: position.column,
});
}
});
@@ -94,21 +95,24 @@ export class CodeBlock extends React.PureComponent
{
prevProps.highlightRanges !== this.props.highlightRanges
) {
if (this.ed) {
- this.ed.getModel().setValue(this.props.code);
+ const model = this.ed.getModel();
+ if (model) {
+ model.setValue(this.props.code);
- if (this.props.highlightRanges) {
- const decorations = this.props.highlightRanges!.map((range: IRange) => {
- return {
- range,
- options: {
- inlineClassName: 'codeSearch__highlight',
- },
- };
- });
- this.currentHighlightDecorations = this.ed.deltaDecorations(
- this.currentHighlightDecorations,
- decorations
- );
+ if (this.props.highlightRanges) {
+ const decorations = this.props.highlightRanges!.map((range: IRange) => {
+ return {
+ range,
+ options: {
+ inlineClassName: 'codeSearch__highlight',
+ },
+ };
+ });
+ this.currentHighlightDecorations = this.ed.deltaDecorations(
+ this.currentHighlightDecorations,
+ decorations
+ );
+ }
}
}
}
diff --git a/x-pack/plugins/code/public/components/editor/editor.tsx b/x-pack/plugins/code/public/components/editor/editor.tsx
index 59195350a0d8..19e2dc244103 100644
--- a/x-pack/plugins/code/public/components/editor/editor.tsx
+++ b/x-pack/plugins/code/public/components/editor/editor.tsx
@@ -181,7 +181,8 @@ export class EditorComponent extends React.Component {
this.editor.onMouseDown((e: editorInterfaces.IEditorMouseEvent) => {
if (e.target.type === monaco.editor.MouseTargetType.GUTTER_LINE_NUMBERS) {
const uri = `${repo}/blob/${encodeRevisionString(revision)}/${file}`;
- history.push(`/${uri}!L${e.target.position.lineNumber}:0${qs}`);
+ const position = e.target.position || { lineNumber: 0, column: 0 };
+ history.push(`/${uri}!L${position.lineNumber}:0${qs}`);
}
this.monaco!.container.focus();
});
diff --git a/x-pack/plugins/code/public/components/file_tree/__snapshots__/file_tree.test.tsx.snap b/x-pack/plugins/code/public/components/file_tree/__snapshots__/file_tree.test.tsx.snap
index 63e962517a62..d3f0b3d1c8b5 100644
--- a/x-pack/plugins/code/public/components/file_tree/__snapshots__/file_tree.test.tsx.snap
+++ b/x-pack/plugins/code/public/components/file_tree/__snapshots__/file_tree.test.tsx.snap
@@ -16,25 +16,14 @@ exports[`render correctly 1`] = `
/>
+ />
+ />
+ />
@@ -148,41 +120,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -210,40 +165,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -273,41 +212,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -335,25 +257,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -385,40 +296,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -451,41 +346,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -513,41 +391,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -579,41 +440,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -641,41 +485,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -703,41 +530,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -765,41 +575,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -827,41 +620,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -889,41 +665,24 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
+ />
@@ -951,25 +710,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -1001,25 +749,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -1051,25 +788,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -1101,25 +827,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -1151,25 +866,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -1201,25 +905,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -1251,25 +944,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -1301,25 +983,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -1351,25 +1022,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
@@ -1401,25 +1061,14 @@ exports[`render correctly 1`] = `
tabIndex={0}
>
+ />
diff --git a/x-pack/plugins/code/public/components/file_tree/file_tree.test.tsx b/x-pack/plugins/code/public/components/file_tree/file_tree.test.tsx
index 99a08f33de3c..cd159fab3e68 100644
--- a/x-pack/plugins/code/public/components/file_tree/file_tree.test.tsx
+++ b/x-pack/plugins/code/public/components/file_tree/file_tree.test.tsx
@@ -44,7 +44,6 @@ test('render correctly', () => {
location={location}
closeTreePath={mockFunction}
openTreePath={mockFunction}
- fetchRepoTree={mockFunction}
/>
)
.toJSON();
diff --git a/x-pack/plugins/code/public/components/file_tree/file_tree.tsx b/x-pack/plugins/code/public/components/file_tree/file_tree.tsx
index 2070407bedfc..061787679846 100644
--- a/x-pack/plugins/code/public/components/file_tree/file_tree.tsx
+++ b/x-pack/plugins/code/public/components/file_tree/file_tree.tsx
@@ -11,7 +11,7 @@ import classes from 'classnames';
import { connect } from 'react-redux';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { FileTree as Tree, FileTreeItemType } from '../../../model';
-import { closeTreePath, fetchRepoTree, FetchRepoTreePayload, openTreePath } from '../../actions';
+import { closeTreePath, openTreePath } from '../../actions';
import { EuiSideNavItem, MainRouteParams, PathTypes } from '../../common/types';
import { RootState } from '../../reducers';
import { encodeRevisionString } from '../../utils/url';
@@ -20,9 +20,7 @@ interface Props extends RouteComponentProps {
node?: Tree;
closeTreePath: (paths: string) => void;
openTreePath: (paths: string) => void;
- fetchRepoTree: (p: FetchRepoTreePayload) => void;
openedPaths: string[];
- treeLoading?: boolean;
}
export class CodeFileTree extends React.Component {
@@ -33,16 +31,6 @@ export class CodeFileTree extends React.Component {
}
}
- public fetchTree(path = '', isDir: boolean) {
- const { resource, org, repo, revision } = this.props.match.params;
- this.props.fetchRepoTree({
- uri: `${resource}/${org}/${repo}`,
- revision,
- path: path || '',
- isDir,
- });
- }
-
public onClick = (node: Tree) => {
const { resource, org, repo, revision, path } = this.props.match.params;
if (!(path === node.path)) {
@@ -257,11 +245,9 @@ export class CodeFileTree extends React.Component {
const mapStateToProps = (state: RootState) => ({
node: state.file.tree,
openedPaths: state.file.openedPaths,
- treeLoading: state.file.rootFileTreeLoading,
});
const mapDispatchToProps = {
- fetchRepoTree,
closeTreePath,
openTreePath,
};
diff --git a/x-pack/plugins/code/public/components/main/content.tsx b/x-pack/plugins/code/public/components/main/content.tsx
index fae76c4a0916..c8b5aac55af7 100644
--- a/x-pack/plugins/code/public/components/main/content.tsx
+++ b/x-pack/plugins/code/public/components/main/content.tsx
@@ -53,8 +53,8 @@ interface Props extends RouteComponentProps {
onSearchScopeChanged: (s: SearchScope) => void;
repoScope: string[];
notFoundDirs: string[];
+ fileTreeLoadingPaths: string[];
searchOptions: SearchOptions;
- fileTreeLoading: boolean;
query: string;
}
const LANG_MD = 'markdown';
@@ -266,7 +266,7 @@ class CodeContent extends React.PureComponent {
}
public renderContent() {
- const { file, match, tree, fileTreeLoading, isNotFound, notFoundDirs } = this.props;
+ const { file, match, tree, fileTreeLoadingPaths, isNotFound, notFoundDirs } = this.props;
const { path, pathType, resource, org, repo, revision } = match.params;
if (isNotFound || notFoundDirs.includes(path || '')) {
return ;
@@ -281,7 +281,7 @@ class CodeContent extends React.PureComponent {
const node = this.findNode(path ? path.split('/') : [], tree);
return (
-
+
({
notFoundDirs: state.file.notFoundDirs,
file: state.file.file,
tree: state.file.tree,
- fileTreeLoading: state.file.fileTreeLoading,
+ fileTreeLoadingPaths: state.file.fileTreeLoadingPaths,
currentTree: currentTreeSelector(state),
branches: state.file.branches,
hasMoreCommits: hasMoreCommitsSelector(state),
diff --git a/x-pack/plugins/code/public/components/main/main.tsx b/x-pack/plugins/code/public/components/main/main.tsx
index 6b9579f880a4..40a51c58ce98 100644
--- a/x-pack/plugins/code/public/components/main/main.tsx
+++ b/x-pack/plugins/code/public/components/main/main.tsx
@@ -74,7 +74,7 @@ class CodeMain extends React.Component {
}
const mapStateToProps = (state: RootState) => ({
- loadingFileTree: state.file.rootFileTreeLoading,
+ loadingFileTree: state.file.fileTreeLoadingPaths.includes(''),
loadingStructureTree: state.symbol.loading,
hasStructure: structureSelector(state).length > 0 && !state.symbol.error,
languageServerInitializing: state.symbol.languageServerInitializing,
diff --git a/x-pack/plugins/code/public/components/main/side_tabs.tsx b/x-pack/plugins/code/public/components/main/side_tabs.tsx
index dcc4e5e11d0b..16e1a17d22a1 100644
--- a/x-pack/plugins/code/public/components/main/side_tabs.tsx
+++ b/x-pack/plugins/code/public/components/main/side_tabs.tsx
@@ -71,7 +71,7 @@ class CodeSideTabs extends React.PureComponent {
id: Tabs.file,
name: 'File',
content: fileTabContent,
- 'data-test-subj': 'codeFileTreeTab',
+ 'data-test-subj': `codeFileTreeTab${this.sideTab === Tabs.file ? 'Active' : ''}`,
},
{
id: Tabs.structure,
diff --git a/x-pack/plugins/code/public/components/query_bar/components/__snapshots__/query_bar.test.tsx.snap b/x-pack/plugins/code/public/components/query_bar/components/__snapshots__/query_bar.test.tsx.snap
index 481d0717555e..c8e2a2317095 100644
--- a/x-pack/plugins/code/public/components/query_bar/components/__snapshots__/query_bar.test.tsx.snap
+++ b/x-pack/plugins/code/public/components/query_bar/components/__snapshots__/query_bar.test.tsx.snap
@@ -349,29 +349,21 @@ exports[`render correctly with empty query string 1`] = `
-
-
+ />
+
Search Everything
@@ -408,29 +400,21 @@ exports[`render correctly with empty query string 1`] = `
-
-
+ />
+
Search Everything
@@ -461,40 +445,23 @@ exports[`render correctly with empty query string 1`] = `
className="euiFormControlLayoutCustomIcon__icon"
type="arrowDown"
>
-
-
+ />
+
@@ -1093,29 +1060,21 @@ exports[`render correctly with input query string changed 1`] = `
-
-
+ />
+
Search Everything
@@ -1152,29 +1111,21 @@ exports[`render correctly with input query string changed 1`] = `
-
-
+ />
+
Search Everything
@@ -1205,40 +1156,23 @@ exports[`render correctly with input query string changed 1`] = `
className="euiFormControlLayoutCustomIcon__icon"
type="arrowDown"
>
-
-
+ />
+
diff --git a/x-pack/plugins/code/public/components/query_bar/components/typeahead/__snapshots__/suggestion_component.test.tsx.snap b/x-pack/plugins/code/public/components/query_bar/components/typeahead/__snapshots__/suggestion_component.test.tsx.snap
index daa1c1e2bf9f..87b458f25fa0 100644
--- a/x-pack/plugins/code/public/components/query_bar/components/typeahead/__snapshots__/suggestion_component.test.tsx.snap
+++ b/x-pack/plugins/code/public/components/query_bar/components/typeahead/__snapshots__/suggestion_component.test.tsx.snap
@@ -149,30 +149,21 @@ exports[`render symbol item 1`] = `
-
-
+ />
+
diff --git a/x-pack/plugins/code/public/components/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap b/x-pack/plugins/code/public/components/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap
index 1488a046833e..9d7be6b3ab4c 100644
--- a/x-pack/plugins/code/public/components/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap
+++ b/x-pack/plugins/code/public/components/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap
@@ -165,29 +165,21 @@ exports[`render full suggestions component 1`] = `
-
-
+ />
+
@@ -254,30 +246,21 @@ exports[`render full suggestions component 1`] = `
-
-
+ />
+
@@ -338,29 +321,21 @@ exports[`render full suggestions component 1`] = `
-
-
+ />
+
@@ -464,30 +439,21 @@ exports[`render full suggestions component 1`] = `
-
-
+ />
+
diff --git a/x-pack/plugins/code/public/components/symbol_tree/__test__/__snapshots__/symbol_tree.test.tsx.snap b/x-pack/plugins/code/public/components/symbol_tree/__test__/__snapshots__/symbol_tree.test.tsx.snap
index 454a51c2d503..445bbb65adda 100644
--- a/x-pack/plugins/code/public/components/symbol_tree/__test__/__snapshots__/symbol_tree.test.tsx.snap
+++ b/x-pack/plugins/code/public/components/symbol_tree/__test__/__snapshots__/symbol_tree.test.tsx.snap
@@ -19,25 +19,14 @@ exports[`render symbol tree correctly 1`] = `
/>
+ />
produce(state, draft => {
draft.currentPath = action.payload.path;
- draft.fileTreeLoading = true;
+ draft.fileTreeLoadingPaths.push(action.payload!.path);
}),
[String(fetchRepoTreeSuccess)]: (state: FileState, action: Action
) =>
produce(state, (draft: FileState) => {
- draft.fileTreeLoading = false;
- draft.rootFileTreeLoading = false;
draft.notFoundDirs = draft.notFoundDirs.filter(dir => dir !== action.payload!.path);
+ draft.fileTreeLoadingPaths = draft.fileTreeLoadingPaths.filter(
+ p => p !== action.payload!.path && p !== ''
+ );
const { tree, path, withParents } = action.payload!;
if (withParents || path === '/' || path === '') {
draft.tree = mergeNode(draft.tree, tree);
@@ -142,12 +141,12 @@ export const file = handleActions(
}),
[String(fetchRootRepoTreeSuccess)]: (state: FileState, action: Action) =>
produce(state, (draft: FileState) => {
- draft.rootFileTreeLoading = false;
+ draft.fileTreeLoadingPaths = draft.fileTreeLoadingPaths.filter(p => p !== '/' && p !== '');
draft.tree = mergeNode(draft.tree, action.payload!);
}),
[String(fetchRootRepoTreeFailed)]: (state: FileState, action: Action) =>
produce(state, (draft: FileState) => {
- draft.rootFileTreeLoading = false;
+ draft.fileTreeLoadingPaths = draft.fileTreeLoadingPaths.filter(p => p !== '/' && p !== '');
}),
[String(dirNotFound)]: (state: FileState, action: any) =>
produce(state, (draft: FileState) => {
@@ -158,10 +157,11 @@ export const file = handleActions(
draft.tree = initialState.tree;
draft.openedPaths = initialState.openedPaths;
}),
- [String(fetchRepoTreeFailed)]: (state: FileState) =>
+ [String(fetchRepoTreeFailed)]: (state: FileState, action: Action) =>
produce(state, draft => {
- draft.fileTreeLoading = false;
- draft.rootFileTreeLoading = false;
+ draft.fileTreeLoadingPaths = draft.fileTreeLoadingPaths.filter(
+ p => p !== action.payload!.path && p !== ''
+ );
}),
[String(openTreePath)]: (state: FileState, action: Action) =>
produce(state, (draft: FileState) => {
diff --git a/x-pack/plugins/code/public/reducers/symbol.ts b/x-pack/plugins/code/public/reducers/symbol.ts
index b85b7ba36d0f..0dfb6e1f93be 100644
--- a/x-pack/plugins/code/public/reducers/symbol.ts
+++ b/x-pack/plugins/code/public/reducers/symbol.ts
@@ -73,10 +73,11 @@ const generateStructureTree: (symbols: SymbolInformation[]) => any = symbols =>
if (result) {
return result;
} else {
- const subTree = tree
- .filter(s => s.members)
- .map(s => s.members)
- .flat();
+ // TODO: Use Array.flat once supported
+ const subTree = tree.reduce(
+ (s, t) => (t.members ? s.concat(t.members) : s),
+ [] as SymbolWithMembers[]
+ );
if (subTree.length > 0) {
return findContainer(subTree, containerName);
} else {
diff --git a/x-pack/plugins/code/public/sagas/editor.ts b/x-pack/plugins/code/public/sagas/editor.ts
index 85a0039ecaa3..46eace8f51e2 100644
--- a/x-pack/plugins/code/public/sagas/editor.ts
+++ b/x-pack/plugins/code/public/sagas/editor.ts
@@ -43,6 +43,7 @@ import {
refUrlSelector,
repoScopeSelector,
urlQueryStringSelector,
+ createTreeSelector,
} from '../selectors';
import { history } from '../utils/url';
import { mainRoutePattern } from './patterns';
@@ -203,15 +204,27 @@ function* handleMainRouteChange(action: Action) {
.slice(0, -1)
.join('/');
yield put(openTreePath(openPath || ''));
- yield put(
- fetchRepoTree({
- uri: repoUri,
- revision,
- path: file || '',
- parents: getPathOfTree(tree, (file || '').split('/')) === null,
- isDir,
- })
- );
+ function isTreeLoaded(isDirectory: boolean, targetTree: FileTree | null) {
+ if (!isDirectory) {
+ return !!targetTree;
+ } else if (!targetTree) {
+ return false;
+ } else {
+ return targetTree.children && targetTree.children.length > 0;
+ }
+ }
+ const targetTree: FileTree | null = yield select(createTreeSelector(file || ''));
+ if (!isTreeLoaded(isDir, targetTree)) {
+ yield put(
+ fetchRepoTree({
+ uri: repoUri,
+ revision,
+ path: file || '',
+ parents: getPathOfTree(tree, (file || '').split('/')) === null,
+ isDir,
+ })
+ );
+ }
const uri = toCanonicalUrl({
repoUri,
file,
diff --git a/x-pack/plugins/code/public/sagas/file.ts b/x-pack/plugins/code/public/sagas/file.ts
index be82da15438c..8a6a9c17f046 100644
--- a/x-pack/plugins/code/public/sagas/file.ts
+++ b/x-pack/plugins/code/public/sagas/file.ts
@@ -10,7 +10,6 @@ import { kfetch } from 'ui/kfetch';
import Url from 'url';
import { call, put, select, takeEvery, takeLatest } from 'redux-saga/effects';
-import { FileTree } from '../../model';
import {
fetchDirectory,
fetchDirectoryFailed,
@@ -45,51 +44,37 @@ import {
dirNotFound,
} from '../actions';
import { RootState } from '../reducers';
-import { treeCommitsSelector, createTreeSelector } from '../selectors';
+import { treeCommitsSelector } from '../selectors';
import { repoRoutePattern } from './patterns';
+import { FileTree } from '../../model';
function* handleFetchRepoTree(action: Action) {
try {
- const { uri, revision, path, parents, isDir } = action.payload!;
- if (path && isDir) {
- const tree = yield select(createTreeSelector(path));
- if (tree) {
- const { children } = tree;
- // do not request file tree if this tree exists and its children are not empty
- if (!children || children.length === 0) {
- yield call(fetchPath, { uri, revision, path, parents, isDir });
- }
+ const tree = yield call(requestRepoTree, action.payload!);
+ (tree.children || []).sort((a: FileTree, b: FileTree) => {
+ const typeDiff = a.type - b.type;
+ if (typeDiff === 0) {
+ return a.name > b.name ? 1 : -1;
} else {
- yield call(fetchPath, { uri, revision, path, parents, isDir });
+ return -typeDiff;
}
- } else {
- yield call(fetchPath, action.payload!);
- }
+ });
+ tree.repoUri = action.payload!.uri;
+ yield put(
+ fetchRepoTreeSuccess({
+ tree,
+ path: action.payload!.path,
+ withParents: action.payload!.parents,
+ })
+ );
} catch (err) {
if (action.payload!.isDir && err.body && err.body.statusCode === 404) {
yield put(dirNotFound(action.payload!.path));
}
- yield put(fetchRepoTreeFailed(err));
+ yield put(fetchRepoTreeFailed({ ...err, path: action.payload!.path }));
}
}
-function* fetchPath(payload: FetchRepoTreePayload) {
- const update: FileTree = yield call(requestRepoTree, payload);
- (update.children || []).sort((a, b) => {
- const typeDiff = a.type - b.type;
- if (typeDiff === 0) {
- return a.name > b.name ? 1 : -1;
- } else {
- return -typeDiff;
- }
- });
- update.repoUri = payload.uri;
- yield put(
- fetchRepoTreeSuccess({ tree: update, path: payload.path, withParents: payload.parents })
- );
- return update;
-}
-
interface FileTreeQuery {
parents?: boolean;
limit: number;
diff --git a/x-pack/plugins/code/public/sagas/project_status.ts b/x-pack/plugins/code/public/sagas/project_status.ts
index c01238dc8763..cbd9c10b5e7b 100644
--- a/x-pack/plugins/code/public/sagas/project_status.ts
+++ b/x-pack/plugins/code/public/sagas/project_status.ts
@@ -134,7 +134,9 @@ function* handleReposStatusLoaded(action: Action) {
// Load current repository status on main page
const currentUri = yield select(repoUriSelector);
const status = allStatuses[currentUri];
- yield triggerPollRepoStatus(status.state, currentUri);
+ if (status) {
+ yield triggerPollRepoStatus(status.state, currentUri);
+ }
}
}
diff --git a/x-pack/plugins/code/server/__tests__/clone_worker.ts b/x-pack/plugins/code/server/__tests__/clone_worker.ts
index a7ee674cd3ff..cd0fc1d81f2f 100644
--- a/x-pack/plugins/code/server/__tests__/clone_worker.ts
+++ b/x-pack/plugins/code/server/__tests__/clone_worker.ts
@@ -15,8 +15,8 @@ import sinon from 'sinon';
import { Repository } from '../../model';
import { EsClient, Esqueue } from '../lib/esqueue';
import { Logger } from '../log';
-import { CloneWorker } from '../queue';
-import { IndexWorker } from '../queue';
+import { CloneWorker, IndexWorker } from '../queue';
+import { CancellationSerivce } from '../queue/cancellation_service';
import { RepositoryServiceFactory } from '../repository_service_factory';
import { createTestServerOption, emptyAsyncFunc } from '../test_utils';
import { ConsoleLoggerFactory } from '../utils/console_logger_factory';
@@ -93,13 +93,24 @@ describe('clone_worker_tests', () => {
const newInstanceSpy = sinon.fake.returns(repoService);
repoServiceFactory.newInstance = newInstanceSpy;
+ // Setup CancellationService
+ const cancelCloneJobSpy = sinon.spy();
+ const registerCloneJobTokenSpy = sinon.spy();
+ const cancellationService: any = {
+ cancelCloneJob: emptyAsyncFunc,
+ registerCloneJobToken: emptyAsyncFunc,
+ };
+ cancellationService.cancelCloneJob = cancelCloneJobSpy;
+ cancellationService.registerCloneJobToken = registerCloneJobTokenSpy;
+
const cloneWorker = new CloneWorker(
esQueue as Esqueue,
log,
{} as EsClient,
serverOptions,
{} as IndexWorker,
- (repoServiceFactory as any) as RepositoryServiceFactory
+ (repoServiceFactory as any) as RepositoryServiceFactory,
+ cancellationService as CancellationSerivce
);
await cloneWorker.executeJob({
@@ -129,13 +140,24 @@ describe('clone_worker_tests', () => {
};
esClient.update = updateSpy;
+ // Setup CancellationService
+ const cancelCloneJobSpy = sinon.spy();
+ const registerCloneJobTokenSpy = sinon.spy();
+ const cancellationService: any = {
+ cancelCloneJob: emptyAsyncFunc,
+ registerCloneJobToken: emptyAsyncFunc,
+ };
+ cancellationService.cancelCloneJob = cancelCloneJobSpy;
+ cancellationService.registerCloneJobToken = registerCloneJobTokenSpy;
+
const cloneWorker = new CloneWorker(
esQueue as Esqueue,
log,
esClient as EsClient,
serverOptions,
(indexWorker as any) as IndexWorker,
- {} as RepositoryServiceFactory
+ {} as RepositoryServiceFactory,
+ cancellationService as CancellationSerivce
);
await cloneWorker.onJobCompleted(
@@ -173,13 +195,24 @@ describe('clone_worker_tests', () => {
};
esClient.index = indexSpy;
+ // Setup CancellationService
+ const cancelCloneJobSpy = sinon.spy();
+ const registerCloneJobTokenSpy = sinon.spy();
+ const cancellationService: any = {
+ cancelCloneJob: emptyAsyncFunc,
+ registerCloneJobToken: emptyAsyncFunc,
+ };
+ cancellationService.cancelCloneJob = cancelCloneJobSpy;
+ cancellationService.registerCloneJobToken = registerCloneJobTokenSpy;
+
const cloneWorker = new CloneWorker(
esQueue as Esqueue,
log,
(esClient as any) as EsClient,
serverOptions,
{} as IndexWorker,
- {} as RepositoryServiceFactory
+ {} as RepositoryServiceFactory,
+ cancellationService as CancellationSerivce
);
await cloneWorker.onJobEnqueued({
@@ -209,13 +242,24 @@ describe('clone_worker_tests', () => {
const newInstanceSpy = sinon.fake.returns(repoService);
repoServiceFactory.newInstance = newInstanceSpy;
+ // Setup CancellationService
+ const cancelCloneJobSpy = sinon.spy();
+ const registerCloneJobTokenSpy = sinon.spy();
+ const cancellationService: any = {
+ cancelCloneJob: emptyAsyncFunc,
+ registerCloneJobToken: emptyAsyncFunc,
+ };
+ cancellationService.cancelCloneJob = cancelCloneJobSpy;
+ cancellationService.registerCloneJobToken = registerCloneJobTokenSpy;
+
const cloneWorker = new CloneWorker(
esQueue as Esqueue,
log,
{} as EsClient,
serverOptions,
{} as IndexWorker,
- (repoServiceFactory as any) as RepositoryServiceFactory
+ (repoServiceFactory as any) as RepositoryServiceFactory,
+ cancellationService as CancellationSerivce
);
const result1 = await cloneWorker.executeJob({
diff --git a/x-pack/plugins/code/server/__tests__/repository_service.ts b/x-pack/plugins/code/server/__tests__/repository_service.ts
index 7eaec9af646d..beae4a306dcf 100644
--- a/x-pack/plugins/code/server/__tests__/repository_service.ts
+++ b/x-pack/plugins/code/server/__tests__/repository_service.ts
@@ -17,7 +17,6 @@ import { ConsoleLogger } from '../utils/console_logger';
describe('repository service test', () => {
const log = new ConsoleLogger();
const baseDir = fs.mkdtempSync(path.join(os.tmpdir(), 'code_test'));
- log.debug(baseDir);
const repoDir = path.join(baseDir, 'repo');
const credsDir = path.join(baseDir, 'credentials');
// @ts-ignore
diff --git a/x-pack/plugins/code/server/init.ts b/x-pack/plugins/code/server/init.ts
index 376a259987b5..62d05da535e4 100644
--- a/x-pack/plugins/code/server/init.ts
+++ b/x-pack/plugins/code/server/init.ts
@@ -181,6 +181,7 @@ async function initCodeNode(server: Server, serverOptions: ServerOptions, log: L
repoConfigController
);
server.events.on('stop', async () => {
+ log.debug('shutdown lsp process');
await lspService.shutdown();
});
// Initialize indexing factories.
@@ -216,7 +217,8 @@ async function initCodeNode(server: Server, serverOptions: ServerOptions, log: L
esClient,
serverOptions,
indexWorker,
- repoServiceFactory
+ repoServiceFactory,
+ cancellationService
).bind();
const deleteWorker = new DeleteWorker(
queue,
@@ -232,7 +234,8 @@ async function initCodeNode(server: Server, serverOptions: ServerOptions, log: L
log,
esClient,
serverOptions,
- repoServiceFactory
+ repoServiceFactory,
+ cancellationService
).bind();
// Initialize schedulers.
diff --git a/x-pack/plugins/code/server/lsp/abstract_launcher.test.ts b/x-pack/plugins/code/server/lsp/abstract_launcher.test.ts
index f3b465a00298..73ba48c7119f 100644
--- a/x-pack/plugins/code/server/lsp/abstract_launcher.test.ts
+++ b/x-pack/plugins/code/server/lsp/abstract_launcher.test.ts
@@ -58,6 +58,16 @@ class MockLauncher extends AbstractLauncher {
childProcess.send('listen');
return childProcess;
}
+
+ protected killProcess(child: ChildProcess, log: Logger): Promise {
+ // don't kill the process so fast, otherwise no normal exit can happen
+ return new Promise(resolve => {
+ setTimeout(async () => {
+ const killed = await super.killProcess(child, log);
+ resolve(killed);
+ }, 100);
+ });
+ }
}
class PassiveMockLauncher extends MockLauncher {
diff --git a/x-pack/plugins/code/server/lsp/abstract_launcher.ts b/x-pack/plugins/code/server/lsp/abstract_launcher.ts
index 5a946f812622..54053467e1dd 100644
--- a/x-pack/plugins/code/server/lsp/abstract_launcher.ts
+++ b/x-pack/plugins/code/server/lsp/abstract_launcher.ts
@@ -52,9 +52,11 @@ export abstract class AbstractLauncher implements ILanguageServerLauncher {
this._currentPid = child.pid;
this._startTime = Date.now();
this.running = true;
- this.onProcessExit(child, () => this.reconnect(proxy, installationPath, port, log));
+ this.onProcessExit(child, () => {
+ if (!proxy.isClosed) this.reconnect(proxy, installationPath, port, log);
+ });
proxy.onDisconnected(async () => {
- this._proxyConnected = true;
+ this._proxyConnected = false;
if (!proxy.isClosed) {
log.debug('proxy disconnected, reconnecting');
setTimeout(async () => {
@@ -70,12 +72,7 @@ export abstract class AbstractLauncher implements ILanguageServerLauncher {
log.debug('proxy exited, is the process running? ' + this.running);
if (this.child && this.running) {
const p = this.child!;
- setTimeout(async () => {
- if (!p.killed) {
- log.debug('killing the process after 1s');
- await this.killProcess(p, log);
- }
- }, 1000);
+ this.killProcess(p, log);
}
});
proxy.listen();
@@ -164,7 +161,7 @@ export abstract class AbstractLauncher implements ILanguageServerLauncher {
log: Logger
): Promise;
- private killProcess(child: ChildProcess, log: Logger) {
+ protected killProcess(child: ChildProcess, log: Logger) {
if (!child.killed) {
return new Promise((resolve, reject) => {
// if not killed within 1s
diff --git a/x-pack/plugins/code/server/lsp/proxy.ts b/x-pack/plugins/code/server/lsp/proxy.ts
index 7b26bc350f50..23703cd4df8a 100644
--- a/x-pack/plugins/code/server/lsp/proxy.ts
+++ b/x-pack/plugins/code/server/lsp/proxy.ts
@@ -159,19 +159,17 @@ export class LanguageServerProxy implements ILanguageServerHandler {
* https://microsoft.github.io/language-server-protocol/specification#exit
*/
public async exit() {
+ this.closed = true; // stop the socket reconnect
if (this.clientConnection) {
this.logger.info('sending `shutdown` request to language server.');
const clientConn = this.clientConnection;
- await clientConn.sendRequest('shutdown').then(() => {
- this.logger.info('sending `exit` notification to language server.');
-
- // @ts-ignore
- // TODO fix this
- clientConn.sendNotification(ExitNotification.type);
- this.conn.dispose(); // stop listening
+ clientConn.sendRequest('shutdown').then(() => {
+ this.conn.dispose();
});
+ this.logger.info('sending `exit` notification to language server.');
+ // @ts-ignore
+ clientConn.sendNotification(ExitNotification.type);
}
- this.closed = true; // stop the socket reconnect
this.eventEmitter.emit('exit');
}
@@ -263,9 +261,6 @@ export class LanguageServerProxy implements ILanguageServerHandler {
}
private onSocketClosed() {
- if (this.clientConnection) {
- this.clientConnection.dispose();
- }
this.clientConnection = null;
this.connectingPromise = null;
this.eventEmitter.emit('close');
diff --git a/x-pack/plugins/code/server/lsp/request_expander.ts b/x-pack/plugins/code/server/lsp/request_expander.ts
index df32c2813d8c..337d7896b863 100644
--- a/x-pack/plugins/code/server/lsp/request_expander.ts
+++ b/x-pack/plugins/code/server/lsp/request_expander.ts
@@ -41,8 +41,9 @@ export class RequestExpander implements ILanguageServerHandler {
private jobQueue: Job[] = [];
// a map for workspacePath -> Workspace
private workspaces: Map = new Map();
- private workspaceRoot: string;
+ private readonly workspaceRoot: string;
private running = false;
+ private exited = false;
constructor(
proxy: LanguageServerProxy,
@@ -62,6 +63,9 @@ export class RequestExpander implements ILanguageServerHandler {
public handleRequest(request: LspRequest): Promise {
this.lastAccess = Date.now();
return new Promise((resolve, reject) => {
+ if (this.exited) {
+ reject(new Error('proxy is exited.'));
+ }
this.jobQueue.push({
request,
resolve,
@@ -76,6 +80,7 @@ export class RequestExpander implements ILanguageServerHandler {
}
public async exit() {
+ this.exited = true;
return this.proxy.exit();
}
@@ -152,7 +157,7 @@ export class RequestExpander implements ILanguageServerHandler {
private handle() {
const job = this.jobQueue.shift();
- if (job) {
+ if (job && !this.exited) {
const { request, resolve, reject } = job;
this.expand(request, job.startTime).then(
value => {
diff --git a/x-pack/plugins/code/server/lsp/workspace_handler.ts b/x-pack/plugins/code/server/lsp/workspace_handler.ts
index 45b37210eeff..03556a4ace4f 100644
--- a/x-pack/plugins/code/server/lsp/workspace_handler.ts
+++ b/x-pack/plugins/code/server/lsp/workspace_handler.ts
@@ -116,10 +116,19 @@ export class WorkspaceHandler {
public async listWorkspaceFolders(repoUri: string) {
const workspaceDir = await this.workspaceDir(repoUri);
const isDir = (source: string) => fs.lstatSync(source).isDirectory();
- return fs
- .readdirSync(workspaceDir)
- .map(name => path.join(workspaceDir, name))
- .filter(isDir);
+ try {
+ return fs
+ .readdirSync(workspaceDir)
+ .map(name => path.join(workspaceDir, name))
+ .filter(isDir);
+ } catch (error) {
+ if (error.code === 'ENOENT') {
+ this.log.debug('Cannot find workspace dirs');
+ return [];
+ } else {
+ throw error;
+ }
+ }
}
public async clearWorkspace(repoUri: string) {
diff --git a/x-pack/plugins/code/server/queue/abstract_git_worker.ts b/x-pack/plugins/code/server/queue/abstract_git_worker.ts
index d644952dcbf8..86f5cd0b048f 100644
--- a/x-pack/plugins/code/server/queue/abstract_git_worker.ts
+++ b/x-pack/plugins/code/server/queue/abstract_git_worker.ts
@@ -34,6 +34,10 @@ export abstract class AbstractGitWorker extends AbstractWorker {
}
public async onJobCompleted(job: Job, res: CloneWorkerResult) {
+ if (res.cancelled) {
+ // Skip updating job progress if the job is done because of cancellation.
+ return;
+ }
await super.onJobCompleted(job, res);
// Update the default branch.
@@ -85,9 +89,9 @@ export abstract class AbstractGitWorker extends AbstractWorker {
try {
return await this.objectClient.updateRepositoryGitStatus(uri, p);
} catch (err) {
- // This is a warning since it's not blocking anything.
- this.log.warn(`Update git clone progress error.`);
- this.log.warn(err);
+ // Do nothing here since it's not blocking anything.
+ // this.log.warn(`Update git clone progress error.`);
+ // this.log.warn(err);
}
}
}
diff --git a/x-pack/plugins/code/server/queue/abstract_worker.ts b/x-pack/plugins/code/server/queue/abstract_worker.ts
index 8bb16b8d36e0..b1b1d6b243f1 100644
--- a/x-pack/plugins/code/server/queue/abstract_worker.ts
+++ b/x-pack/plugins/code/server/queue/abstract_worker.ts
@@ -106,12 +106,16 @@ export abstract class AbstractWorker implements Worker {
return await this.updateProgress(job, WorkerReservedProgress.INIT);
}
- public async onJobCompleted(job: Job, res: any) {
+ public async onJobCompleted(job: Job, res: WorkerResult) {
this.log.info(
`${this.id} job completed with result ${JSON.stringify(
res
)} in ${this.workerTaskDurationSeconds(job)} seconds.`
);
+ if (res.cancelled) {
+ // Skip updating job progress if the job is done because of cancellation.
+ return;
+ }
return await this.updateProgress(job, WorkerReservedProgress.COMPLETED);
}
diff --git a/x-pack/plugins/code/server/queue/cancellation_service.ts b/x-pack/plugins/code/server/queue/cancellation_service.ts
index 4cee75e8cd28..c9f9fc454a76 100644
--- a/x-pack/plugins/code/server/queue/cancellation_service.ts
+++ b/x-pack/plugins/code/server/queue/cancellation_service.ts
@@ -8,13 +8,32 @@ import { RepositoryUri } from '../../model';
import { CancellationToken } from '../lib/esqueue';
export class CancellationSerivce {
- // TODO: Add clone/update cancellation map.
+ private cloneCancellationMap: Map;
+ private updateCancellationMap: Map;
private indexCancellationMap: Map;
constructor() {
+ this.cloneCancellationMap = new Map();
+ this.updateCancellationMap = new Map();
this.indexCancellationMap = new Map();
}
+ public cancelCloneJob(repoUri: RepositoryUri) {
+ const token = this.cloneCancellationMap.get(repoUri);
+ if (token) {
+ token.cancel();
+ this.cloneCancellationMap.delete(repoUri);
+ }
+ }
+
+ public cancelUpdateJob(repoUri: RepositoryUri) {
+ const token = this.updateCancellationMap.get(repoUri);
+ if (token) {
+ token.cancel();
+ this.updateCancellationMap.delete(repoUri);
+ }
+ }
+
public cancelIndexJob(repoUri: RepositoryUri) {
const token = this.indexCancellationMap.get(repoUri);
if (token) {
@@ -23,6 +42,22 @@ export class CancellationSerivce {
}
}
+ public registerCloneJobToken(repoUri: RepositoryUri, cancellationToken: CancellationToken) {
+ const token = this.cloneCancellationMap.get(repoUri);
+ if (token) {
+ token.cancel();
+ }
+ this.cloneCancellationMap.set(repoUri, cancellationToken);
+ }
+
+ public registerUpdateJobToken(repoUri: RepositoryUri, cancellationToken: CancellationToken) {
+ const token = this.updateCancellationMap.get(repoUri);
+ if (token) {
+ token.cancel();
+ }
+ this.updateCancellationMap.set(repoUri, cancellationToken);
+ }
+
public registerIndexJobToken(repoUri: RepositoryUri, cancellationToken: CancellationToken) {
const token = this.indexCancellationMap.get(repoUri);
if (token) {
diff --git a/x-pack/plugins/code/server/queue/clone_worker.ts b/x-pack/plugins/code/server/queue/clone_worker.ts
index 4786c885fb3a..efbf2847ee8a 100644
--- a/x-pack/plugins/code/server/queue/clone_worker.ts
+++ b/x-pack/plugins/code/server/queue/clone_worker.ts
@@ -19,6 +19,7 @@ import { Logger } from '../log';
import { RepositoryServiceFactory } from '../repository_service_factory';
import { ServerOptions } from '../server_options';
import { AbstractGitWorker } from './abstract_git_worker';
+import { CancellationSerivce } from './cancellation_service';
import { IndexWorker } from './index_worker';
import { Job } from './job';
@@ -31,13 +32,15 @@ export class CloneWorker extends AbstractGitWorker {
protected readonly client: EsClient,
protected readonly serverOptions: ServerOptions,
private readonly indexWorker: IndexWorker,
- private readonly repoServiceFactory: RepositoryServiceFactory
+ private readonly repoServiceFactory: RepositoryServiceFactory,
+ private readonly cancellationService: CancellationSerivce
) {
super(queue, log, client, serverOptions);
}
public async executeJob(job: Job) {
- const { url } = job.payload;
+ const { payload, cancellationToken } = job;
+ const { url } = payload;
try {
validateGitUrl(
url,
@@ -62,15 +65,36 @@ export class CloneWorker extends AbstractGitWorker {
this.serverOptions.security.enableGitCertCheck
);
const repo = RepositoryUtils.buildRepository(url);
+
+ // Try to cancel any existing clone job for this repository.
+ this.cancellationService.cancelCloneJob(repo.uri);
+
+ let cancelled = false;
+ if (cancellationToken) {
+ cancellationToken.on(() => {
+ cancelled = true;
+ });
+ this.cancellationService.registerCloneJobToken(repo.uri, cancellationToken);
+ }
+
return await repoService.clone(repo, (progress: number, cloneProgress?: CloneProgress) => {
+ if (cancelled) {
+ // return false to stop the clone progress
+ return false;
+ }
// For clone job payload, it only has the url. Populate back the
// repository uri before update progress.
job.payload.uri = repo.uri;
this.updateProgress(job, progress, undefined, cloneProgress);
+ return true;
});
}
public async onJobCompleted(job: Job, res: CloneWorkerResult) {
+ if (res.cancelled) {
+ // Skip updating job progress if the job is done because of cancellation.
+ return;
+ }
this.log.info(`Clone job done for ${res.repo.uri}`);
// For clone job payload, it only has the url. Populate back the
// repository uri.
diff --git a/x-pack/plugins/code/server/queue/delete_worker.test.ts b/x-pack/plugins/code/server/queue/delete_worker.test.ts
index fc8285cb46fb..9f5f02bb49b0 100644
--- a/x-pack/plugins/code/server/queue/delete_worker.test.ts
+++ b/x-pack/plugins/code/server/queue/delete_worker.test.ts
@@ -41,10 +41,16 @@ test('Execute delete job.', async () => {
// Setup CancellationService
const cancelIndexJobSpy = sinon.spy();
+ const cancelCloneJobSpy = sinon.spy();
+ const cancelUpdateJobSpy = sinon.spy();
const cancellationService = {
+ cancelCloneJob: emptyAsyncFunc,
+ cancelUpdateJob: emptyAsyncFunc,
cancelIndexJob: emptyAsyncFunc,
};
cancellationService.cancelIndexJob = cancelIndexJobSpy;
+ cancellationService.cancelCloneJob = cancelCloneJobSpy;
+ cancellationService.cancelUpdateJob = cancelUpdateJobSpy;
// Setup EsClient
const deleteSpy = sinon.fake.returns(Promise.resolve());
@@ -85,6 +91,8 @@ test('Execute delete job.', async () => {
});
expect(cancelIndexJobSpy.calledOnce).toBeTruthy();
+ expect(cancelCloneJobSpy.calledOnce).toBeTruthy();
+ expect(cancelUpdateJobSpy.calledOnce).toBeTruthy();
expect(newInstanceSpy.calledOnce).toBeTruthy();
expect(removeSpy.calledOnce).toBeTruthy();
diff --git a/x-pack/plugins/code/server/queue/delete_worker.ts b/x-pack/plugins/code/server/queue/delete_worker.ts
index 0b306f1ecc83..1e7438eac9d4 100644
--- a/x-pack/plugins/code/server/queue/delete_worker.ts
+++ b/x-pack/plugins/code/server/queue/delete_worker.ts
@@ -40,7 +40,8 @@ export class DeleteWorker extends AbstractWorker {
const { uri } = job.payload;
// 1. Cancel running workers
- // TODO: Add support for clone/update worker.
+ this.cancellationService.cancelCloneJob(uri);
+ this.cancellationService.cancelUpdateJob(uri);
this.cancellationService.cancelIndexJob(uri);
// 2. Delete repository on local fs.
diff --git a/x-pack/plugins/code/server/queue/index_worker.ts b/x-pack/plugins/code/server/queue/index_worker.ts
index 37c049eb1b46..a7ed181a82a4 100644
--- a/x-pack/plugins/code/server/queue/index_worker.ts
+++ b/x-pack/plugins/code/server/queue/index_worker.ts
@@ -84,6 +84,7 @@ export class IndexWorker extends AbstractWorker {
}
// Binding the index cancellation logic
+ let cancelled = false;
this.cancellationService.cancelIndexJob(uri);
const indexPromises: Array> = this.indexerFactories.map(
async (indexerFactory: IndexerFactory, index: number) => {
@@ -96,6 +97,7 @@ export class IndexWorker extends AbstractWorker {
if (cancellationToken) {
cancellationToken.on(() => {
indexer.cancel();
+ cancelled = true;
});
this.cancellationService.registerIndexJobToken(uri, cancellationToken);
}
@@ -108,6 +110,7 @@ export class IndexWorker extends AbstractWorker {
uri,
revision,
stats: aggregateIndexStats(stats),
+ cancelled,
};
this.log.info(`Index worker finished with stats: ${JSON.stringify([...res.stats])}`);
return res;
diff --git a/x-pack/plugins/code/server/queue/update_worker.test.ts b/x-pack/plugins/code/server/queue/update_worker.test.ts
index 9eceef62a287..15f657b86c52 100644
--- a/x-pack/plugins/code/server/queue/update_worker.test.ts
+++ b/x-pack/plugins/code/server/queue/update_worker.test.ts
@@ -5,12 +5,14 @@
*/
import sinon from 'sinon';
+
import { EsClient, Esqueue } from '../lib/esqueue';
import { Logger } from '../log';
import { RepositoryServiceFactory } from '../repository_service_factory';
import { ServerOptions } from '../server_options';
import { emptyAsyncFunc } from '../test_utils';
import { ConsoleLoggerFactory } from '../utils/console_logger_factory';
+import { CancellationSerivce } from './cancellation_service';
import { UpdateWorker } from './update_worker';
const log: Logger = new ConsoleLoggerFactory().getLogger(['test']);
@@ -37,6 +39,16 @@ test('Execute update job', async () => {
const newInstanceSpy = sinon.fake.returns(repoService);
repoServiceFactory.newInstance = newInstanceSpy;
+ // Setup CancellationService
+ const cancelUpdateJobSpy = sinon.spy();
+ const registerUpdateJobTokenSpy = sinon.spy();
+ const cancellationService: any = {
+ cancelUpdateJob: emptyAsyncFunc,
+ registerUpdateJobToken: emptyAsyncFunc,
+ };
+ cancellationService.cancelUpdateJob = cancelUpdateJobSpy;
+ cancellationService.registerUpdateJobToken = registerUpdateJobTokenSpy;
+
const updateWorker = new UpdateWorker(
esQueue as Esqueue,
log,
@@ -46,7 +58,8 @@ test('Execute update job', async () => {
enableGitCertCheck: false,
},
} as ServerOptions,
- (repoServiceFactory as any) as RepositoryServiceFactory
+ (repoServiceFactory as any) as RepositoryServiceFactory,
+ cancellationService as CancellationSerivce
);
await updateWorker.executeJob({
diff --git a/x-pack/plugins/code/server/queue/update_worker.ts b/x-pack/plugins/code/server/queue/update_worker.ts
index c5be67439989..e9d3432a6fef 100644
--- a/x-pack/plugins/code/server/queue/update_worker.ts
+++ b/x-pack/plugins/code/server/queue/update_worker.ts
@@ -10,6 +10,7 @@ import { Logger } from '../log';
import { RepositoryServiceFactory } from '../repository_service_factory';
import { ServerOptions } from '../server_options';
import { AbstractGitWorker } from './abstract_git_worker';
+import { CancellationSerivce } from './cancellation_service';
import { Job } from './job';
export class UpdateWorker extends AbstractGitWorker {
@@ -20,13 +21,15 @@ export class UpdateWorker extends AbstractGitWorker {
protected readonly log: Logger,
protected readonly client: EsClient,
protected readonly serverOptions: ServerOptions,
- protected readonly repoServiceFactory: RepositoryServiceFactory
+ protected readonly repoServiceFactory: RepositoryServiceFactory,
+ private readonly cancellationService: CancellationSerivce
) {
super(queue, log, client, serverOptions);
}
public async executeJob(job: Job) {
- const repo: Repository = job.payload;
+ const { payload, cancellationToken } = job;
+ const repo: Repository = payload;
this.log.info(`Execute update job for ${repo.uri}`);
const repoService = this.repoServiceFactory.newInstance(
this.serverOptions.repoPath,
@@ -34,7 +37,25 @@ export class UpdateWorker extends AbstractGitWorker {
this.log,
this.serverOptions.security.enableGitCertCheck
);
- return await repoService.update(repo);
+
+ // Try to cancel any existing update job for this repository.
+ this.cancellationService.cancelUpdateJob(repo.uri);
+
+ let cancelled = false;
+ if (cancellationToken) {
+ cancellationToken.on(() => {
+ cancelled = true;
+ });
+ this.cancellationService.registerUpdateJobToken(repo.uri, cancellationToken);
+ }
+
+ return await repoService.update(repo, () => {
+ if (cancelled) {
+ // return false to stop the clone progress
+ return false;
+ }
+ return true;
+ });
}
public async onJobCompleted(job: Job, res: CloneWorkerResult) {
diff --git a/x-pack/plugins/code/server/repository_service.ts b/x-pack/plugins/code/server/repository_service.ts
index 8ac7408c5a45..99aa39dc02d5 100644
--- a/x-pack/plugins/code/server/repository_service.ts
+++ b/x-pack/plugins/code/server/repository_service.ts
@@ -8,7 +8,9 @@ import Git, { RemoteCallbacks } from '@elastic/nodegit';
import del from 'del';
import fs from 'fs';
import mkdirp from 'mkdirp';
+import moment from 'moment';
import path from 'path';
+
import { RepositoryUtils } from '../common/repository_utils';
import {
CloneProgress,
@@ -19,10 +21,24 @@ import {
} from '../model';
import { Logger } from './log';
-export type CloneProgressHandler = (progress: number, cloneProgress?: CloneProgress) => void;
+// Return false to stop the clone progress. Return true to keep going;
+export type CloneProgressHandler = (progress: number, cloneProgress?: CloneProgress) => boolean;
+export type UpdateProgressHandler = () => boolean;
+const GIT_FETCH_PROGRESS_CANCEL = -1;
+// TODO: Cannot directly access Git.Error.CODE.EUSER (-7). Investigate why.
+const NODEGIT_CALLBACK_RETURN_VALUE_ERROR = -7;
+const GIT_INDEXER_PROGRESS_CALLBACK_RETURN_VALUE_ERROR_MSG = `indexer progress callback returned ${GIT_FETCH_PROGRESS_CANCEL}`;
const SSH_AUTH_ERROR = new Error('Failed to authenticate SSH session');
+function isCancelled(error: any) {
+ return (
+ error &&
+ (error.message.includes(GIT_INDEXER_PROGRESS_CALLBACK_RETURN_VALUE_ERROR_MSG) ||
+ error.errno === NODEGIT_CALLBACK_RETURN_VALUE_ERROR)
+ );
+}
+
// This is the service for any kind of repository handling, e.g. clone, update, delete, etc.
export class RepositoryService {
constructor(
@@ -92,18 +108,34 @@ export class RepositoryService {
throw error;
}
}
- public async update(repo: Repository): Promise {
+ public async update(
+ repo: Repository,
+ handler?: UpdateProgressHandler
+ ): Promise {
if (repo.protocol === 'ssh') {
- return await this.tryWithKeys(key => this.doUpdate(repo.uri, key));
+ return await this.tryWithKeys(key => this.doUpdate(repo.uri, key, handler));
} else {
- return await this.doUpdate(repo.uri);
+ return await this.doUpdate(repo.uri, /* key */ undefined, handler);
}
}
- public async doUpdate(uri: string, key?: string): Promise {
+ public async doUpdate(
+ uri: string,
+ key?: string,
+ handler?: UpdateProgressHandler
+ ): Promise {
const localPath = RepositoryUtils.repositoryLocalPath(this.repoVolPath, uri);
try {
const repo = await Git.Repository.open(localPath);
const cbs: RemoteCallbacks = {
+ transferProgress: (_: any) => {
+ if (handler) {
+ const resumeUpdate = handler();
+ if (!resumeUpdate) {
+ return GIT_FETCH_PROGRESS_CANCEL;
+ }
+ }
+ return 0;
+ },
credentials: this.credentialFunc(key),
};
// Ignore cert check on testing environment.
@@ -133,7 +165,19 @@ export class RepositoryService {
revision: headCommit.sha(),
};
} catch (error) {
- if (error.message && error.message.startsWith(SSH_AUTH_ERROR.message)) {
+ if (isCancelled(error)) {
+ // Update job was cancelled intentionally. Do not throw this error.
+ this.log.info(`Update repository job for ${uri} was cancelled.`);
+ this.log.debug(
+ `Update repository job cancellation error: ${JSON.stringify(error, null, 2)}`
+ );
+ return {
+ uri,
+ branch: '',
+ revision: '',
+ cancelled: true,
+ };
+ } else if (error.message && error.message.startsWith(SSH_AUTH_ERROR.message)) {
throw SSH_AUTH_ERROR;
} else {
const msg = `update repository ${uri} error: ${error}`;
@@ -177,30 +221,37 @@ export class RepositoryService {
keyFile?: string
) {
try {
+ let lastProgressUpdate = moment();
const cbs: RemoteCallbacks = {
- transferProgress: {
- // Make the progress update less frequent to avoid too many
- // concurrently update of git status in elasticsearch.
- throttle: 1000,
- callback: (stats: any) => {
- if (handler) {
- const progress =
- (100 * (stats.receivedObjects() + stats.indexedObjects())) /
- (stats.totalObjects() * 2);
- const cloneProgress = {
- isCloned: false,
- receivedObjects: stats.receivedObjects(),
- indexedObjects: stats.indexedObjects(),
- totalObjects: stats.totalObjects(),
- localObjects: stats.localObjects(),
- totalDeltas: stats.totalDeltas(),
- indexedDeltas: stats.indexedDeltas(),
- receivedBytes: stats.receivedBytes(),
- };
- handler(progress, cloneProgress);
+ transferProgress: (stats: any) => {
+ // Clone progress update throttling.
+ const now = moment();
+ if (now.diff(lastProgressUpdate) < 1000) {
+ return 0;
+ }
+ lastProgressUpdate = now;
+
+ if (handler) {
+ const progress =
+ (100 * (stats.receivedObjects() + stats.indexedObjects())) /
+ (stats.totalObjects() * 2);
+ const cloneProgress = {
+ isCloned: false,
+ receivedObjects: stats.receivedObjects(),
+ indexedObjects: stats.indexedObjects(),
+ totalObjects: stats.totalObjects(),
+ localObjects: stats.localObjects(),
+ totalDeltas: stats.totalDeltas(),
+ indexedDeltas: stats.indexedDeltas(),
+ receivedBytes: stats.receivedBytes(),
+ };
+ const resumeClone = handler(progress, cloneProgress);
+ if (!resumeClone) {
+ return GIT_FETCH_PROGRESS_CANCEL;
}
- },
- } as any,
+ }
+ return 0;
+ },
credentials: this.credentialFunc(keyFile),
};
// Ignore cert check on testing environment.
@@ -234,7 +285,18 @@ export class RepositoryService {
},
};
} catch (error) {
- if (error.message && error.message.startsWith(SSH_AUTH_ERROR.message)) {
+ if (isCancelled(error)) {
+ // Clone job was cancelled intentionally. Do not throw this error.
+ this.log.info(`Clone repository job for ${repo.uri} was cancelled.`);
+ this.log.debug(
+ `Clone repository job cancellation error: ${JSON.stringify(error, null, 2)}`
+ );
+ return {
+ uri: repo.uri,
+ repo,
+ cancelled: true,
+ };
+ } else if (error.message && error.message.startsWith(SSH_AUTH_ERROR.message)) {
throw SSH_AUTH_ERROR;
} else {
const msg = `Clone repository from ${repo.url} error.`;
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap b/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap
index 4132c02df863..c4bf2e9374dc 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap
@@ -287,31 +287,23 @@ exports[`ilm summary extension should return extension when index has lifecycle
size="m"
type="cross"
>
-
-
+ />
+
+ />
@@ -113,18 +105,13 @@ exports[`policy table should show empty state when there are not any policies 1`
>
+ />
diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap
index 4784586c9208..1443151323bb 100644
--- a/x-pack/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap
+++ b/x-pack/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap
@@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`LicenseStatus component should display display warning is expired 1`] = `"Your Platinum license has expired
"`;
+exports[`LicenseStatus component should display display warning is expired 1`] = `"Your Platinum license has expired
"`;
-exports[`LicenseStatus component should display normally when license is active 1`] = `"Your Gold license is active
Your license will expire on October 12, 2099 7:00 PM EST
"`;
+exports[`LicenseStatus component should display normally when license is active 1`] = `"Your Gold license is active
Your license will expire on October 12, 2099 7:00 PM EST
"`;
diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap
index 7ce269bab189..ffe8054c912a 100644
--- a/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap
+++ b/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap
@@ -201,17 +201,13 @@ exports[`UploadLicense should display a modal when license requires acknowledgem
>
+ />
+ />
+ />
-
-
+ />
+
@@ -928,31 +908,23 @@ exports[`UploadLicense should display a modal when license requires acknowledgem
size="l"
type="importAction"
>
-
-
+ />
+
-
-
+
-
-
+
-
-
+ />
+
-
-
+
@@ -541,30 +532,21 @@ exports[`UpgradeFailure component passes expected text for not manual upgrade 1`
size="xl"
type="alert"
>
-
-
+ />
+
@@ -899,30 +881,21 @@ exports[`UpgradeFailure component passes expected text for not new pipeline 1`]
size="xl"
type="alert"
>
-
-
+ />
+
diff --git a/x-pack/plugins/ml/public/components/nav_menu/nav_menu.js b/x-pack/plugins/ml/public/components/nav_menu/nav_menu.js
index 9e09cb9d8353..97abaa3589cf 100644
--- a/x-pack/plugins/ml/public/components/nav_menu/nav_menu.js
+++ b/x-pack/plugins/ml/public/components/nav_menu/nav_menu.js
@@ -30,6 +30,7 @@ module.directive('mlNavMenu', function () {
scope.name === 'datavisualizer' ||
scope.name === 'filedatavisualizer' ||
scope.name === 'timeseriesexplorer' ||
+ scope.name === 'access-denied' ||
scope.name === 'explorer') {
scope.showTabs = true;
}
diff --git a/x-pack/plugins/ml/public/data_frame/components/define_pivot/common.ts b/x-pack/plugins/ml/public/data_frame/components/define_pivot/common.ts
index fa2b1eea71b4..5d8b1c662565 100644
--- a/x-pack/plugins/ml/public/data_frame/components/define_pivot/common.ts
+++ b/x-pack/plugins/ml/public/data_frame/components/define_pivot/common.ts
@@ -80,32 +80,36 @@ export function getPivotDropdownOptions(indexPattern: IndexPattern) {
fields.forEach(field => {
// Group by
const availableGroupByAggs = pivotGroupByFieldSupport[field.type];
- availableGroupByAggs.forEach(groupByAgg => {
- // Aggregation name for the group-by is the plain field name. Illegal characters will be removed.
- const aggName = field.name.replace(illegalEsAggNameChars, '').trim();
- // Option name in the dropdown for the group-by is in the form of `sum(fieldname)`.
- const dropDownName = `${groupByAgg}(${field.name})`;
- const groupByOption: DropDownLabel = { label: dropDownName };
- groupByOptions.push(groupByOption);
- groupByOptionsData[dropDownName] = getDefaultGroupByConfig(
- aggName,
- dropDownName,
- field.name,
- groupByAgg
- );
- });
+ if (availableGroupByAggs !== undefined) {
+ availableGroupByAggs.forEach(groupByAgg => {
+ // Aggregation name for the group-by is the plain field name. Illegal characters will be removed.
+ const aggName = field.name.replace(illegalEsAggNameChars, '').trim();
+ // Option name in the dropdown for the group-by is in the form of `sum(fieldname)`.
+ const dropDownName = `${groupByAgg}(${field.name})`;
+ const groupByOption: DropDownLabel = { label: dropDownName };
+ groupByOptions.push(groupByOption);
+ groupByOptionsData[dropDownName] = getDefaultGroupByConfig(
+ aggName,
+ dropDownName,
+ field.name,
+ groupByAgg
+ );
+ });
+ }
// Aggregations
const aggOption: DropDownOption = { label: field.name, options: [] };
const availableAggs = pivotAggsFieldSupport[field.type];
- availableAggs.forEach(agg => {
- // Aggregation name is formatted like `fieldname.sum`. Illegal characters will be removed.
- const aggName = `${field.name.replace(illegalEsAggNameChars, '').trim()}.${agg}`;
- // Option name in the dropdown for the aggregation is in the form of `sum(fieldname)`.
- const dropDownName = `${agg}(${field.name})`;
- aggOption.options.push({ label: dropDownName });
- aggOptionsData[dropDownName] = { agg, field: field.name, aggName, dropDownName };
- });
+ if (availableAggs !== undefined) {
+ availableAggs.forEach(agg => {
+ // Aggregation name is formatted like `fieldname.sum`. Illegal characters will be removed.
+ const aggName = `${field.name.replace(illegalEsAggNameChars, '').trim()}.${agg}`;
+ // Option name in the dropdown for the aggregation is in the form of `sum(fieldname)`.
+ const dropDownName = `${agg}(${field.name})`;
+ aggOption.options.push({ label: dropDownName });
+ aggOptionsData[dropDownName] = { agg, field: field.name, aggName, dropDownName };
+ });
+ }
aggOptions.push(aggOption);
});
diff --git a/x-pack/plugins/ml/public/explorer/explorer.js b/x-pack/plugins/ml/public/explorer/explorer.js
index aaf4b77b66d3..375040301a0a 100644
--- a/x-pack/plugins/ml/public/explorer/explorer.js
+++ b/x-pack/plugins/ml/public/explorer/explorer.js
@@ -12,7 +12,7 @@ import _ from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
-import DragSelect from 'dragselect';
+import DragSelect from 'dragselect/dist/ds.min.js';
import { map } from 'rxjs/operators';
import {
diff --git a/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_single_metric.test.js b/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_single_metric.test.js
index 3398eb2e168e..1f010d01f47b 100644
--- a/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_single_metric.test.js
+++ b/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_single_metric.test.js
@@ -128,7 +128,7 @@ describe('ExplorerChart', () => {
expect(paths[0].getAttribute('class')).toBe('domain');
expect(paths[1].getAttribute('class')).toBe('domain');
expect(paths[2].getAttribute('class')).toBe('values-line');
- expect(paths[2].getAttribute('d')).toBe('MNaN,159.33024504444444MNaN,9.166257955555556LNaN,169.60736875555557');
+ expect(paths[2].getAttribute('d')).toBe('MNaN,159.33024504444444ZMNaN,9.166257955555556LNaN,169.60736875555557');
const dots = wrapper.getDOMNode().querySelector('.values-dots').querySelectorAll('circle');
expect([...dots]).toHaveLength(1);
diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/watch.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/watch.js
index 26b9710fbd4a..536b0b3b7504 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/watch.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/watch.js
@@ -81,7 +81,7 @@ export const watch = {
start: {
script: {
lang: 'painless',
- source: `LocalDateTime.ofEpochSecond((doc["timestamp"].date.getMillis()-((doc["bucket_span"].value * 1000)
+ source: `LocalDateTime.ofEpochSecond((doc["timestamp"].value.getMillis()-((doc["bucket_span"].value * 1000)
* params.padding)) / 1000, 0, ZoneOffset.UTC).toString()+\":00.000Z\"`,
params: {
'padding': 10
@@ -91,7 +91,7 @@ export const watch = {
end: {
script: {
lang: 'painless',
- source: `LocalDateTime.ofEpochSecond((doc["timestamp"].date.getMillis()+((doc["bucket_span"].value * 1000)
+ source: `LocalDateTime.ofEpochSecond((doc["timestamp"].value.getMillis()+((doc["bucket_span"].value * 1000)
* params.padding)) / 1000, 0, ZoneOffset.UTC).toString()+\":00.000Z\"`,
params: {
'padding': 10
@@ -101,13 +101,13 @@ export const watch = {
timestamp_epoch: {
script: {
lang: 'painless',
- source: 'doc["timestamp"].date.getMillis()/1000'
+ source: 'doc["timestamp"].value.getMillis()/1000'
}
},
timestamp_iso8601: {
script: {
lang: 'painless',
- source: 'doc["timestamp"].date'
+ source: 'doc["timestamp"].value'
}
},
score: {
diff --git a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js
index d4bd8c488b32..bc688c07cab2 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js
@@ -16,7 +16,11 @@ import { checkLicenseExpired, checkBasicLicense } from 'plugins/ml/license/check
import { getCreateJobBreadcrumbs, getDataVisualizerIndexOrSearchBreadcrumbs } from 'plugins/ml/jobs/breadcrumbs';
import { getDataFrameIndexOrSearchBreadcrumbs } from 'plugins/ml/data_frame/breadcrumbs';
import { preConfiguredJobRedirect } from 'plugins/ml/jobs/new_job/wizard/preconfigured_job_redirect';
-import { checkCreateJobsPrivilege, checkFindFileStructurePrivilege } from 'plugins/ml/privilege/check_privilege';
+import {
+ checkCreateJobsPrivilege,
+ checkFindFileStructurePrivilege,
+ checkCreateDataFrameJobsPrivilege
+} from 'plugins/ml/privilege/check_privilege';
import { loadIndexPatterns, getIndexPatterns } from 'plugins/ml/util/index_utils';
import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes';
import template from './index_or_search.html';
@@ -66,7 +70,7 @@ uiRoutes
k7Breadcrumbs: getDataFrameIndexOrSearchBreadcrumbs,
resolve: {
CheckLicense: checkBasicLicense,
- privileges: checkFindFileStructurePrivilege,
+ privileges: checkCreateDataFrameJobsPrivilege,
indexPatterns: loadIndexPatterns,
nextStepPath: () => '#data_frames/new_job/step/pivot',
}
diff --git a/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/no_data.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/no_data.test.js.snap
index a4ed9a6fa987..b7c4d4cd0381 100644
--- a/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/no_data.test.js.snap
+++ b/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/no_data.test.js.snap
@@ -12,21 +12,13 @@ exports[`NoData should show a default message if reason is unknown 1`] = `
class="euiPanel euiPanel--paddingLarge euiPageContent eui-textCenter euiPageContent--verticalCenter euiPageContent--horizontalCenter"
>
+ />
@@ -84,21 +76,13 @@ exports[`NoData should show text next to the spinner while checking a setting 1`
class="euiPanel euiPanel--paddingLarge euiPageContent eui-textCenter euiPageContent--verticalCenter euiPageContent--horizontalCenter"
>
+ />
diff --git a/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap b/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap
index dd897ac82965..52354124e9ec 100644
--- a/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap
+++ b/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap
@@ -257,30 +257,21 @@ Array [
class="euiSwitch__track"
>
+ />
+ />