diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bd7868adb511ec..aec6d44ad4abfb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -391,9 +391,9 @@ Note that for VSCode, to enable "live" linting of TypeScript (and other) file ty All user-facing labels and info texts in Kibana should be internationalized. Please take a look at the [readme](packages/kbn-i18n/README.md) and the [guideline](packages/kbn-i18n/GUIDELINE.md) of the i18n package on how to do so. -In order to enable translations in the React parts of the application, the top most component of every `ReactDOM.render` call should be an `I18nContext`: +In order to enable translations in the React parts of the application, the top most component of every `ReactDOM.render` call should be the `Context` component from the `i18n` core service: ```jsx -import { I18nContext } from 'ui/i18n'; +const I18nContext = coreStart.i18n.Context; ReactDOM.render( diff --git a/docs/apm/advanced-queries.asciidoc b/docs/apm/advanced-queries.asciidoc index 942882f8c4dfb3..971d543bbb4452 100644 --- a/docs/apm/advanced-queries.asciidoc +++ b/docs/apm/advanced-queries.asciidoc @@ -5,7 +5,7 @@ When querying in the APM app, you're simply searching and selecting data from fi Queries entered into the query bar are also added as parameters to the URL, so it's easy to share a specific query or view with others. -In the screenshot below, you can begin to see some of the transaction fields available for filtering on: +In the screenshot below, you can begin to see some of the transaction fields available for filtering on: [role="screenshot"] image::apm/images/apm-query-bar.png[Example of the Kibana Query bar in APM app in Kibana] @@ -25,7 +25,7 @@ TIP: Read the {kibana-ref}/kuery-query.html[Kibana Query Language Enhancements] It may also be helpful to view your APM data in the {kibana-ref}/discover.html[Discover app]. Querying documents in Discover works the same way as querying in the APM app, -and all of the example queries listed above can also be used in the Discover app. +and all of the example APM app queries can also be used in the Discover app. [float] ==== Example Discover app query diff --git a/docs/canvas/canvas-function-reference.asciidoc b/docs/canvas/canvas-function-reference.asciidoc index 85e9d224904971..16aaf55802b170 100644 --- a/docs/canvas/canvas-function-reference.asciidoc +++ b/docs/canvas/canvas-function-reference.asciidoc @@ -3,13 +3,13 @@ == Canvas function reference Behind the scenes, Canvas is driven by a powerful expression language, -with dozens of functions and other capabilities, including table transforms, +with dozens of functions and other capabilities, including table transforms, type casting, and sub-expressions. The Canvas expression language also supports <>, which perform complex math calculations. -A *** denotes a required argument. +A *** denotes a required argument. A † denotes an argument can be passed multiple times. @@ -184,7 +184,7 @@ filters ---- `as` casts any primitive value (`string`, `number`, `date`, `null`) into a `datatable` with a single row and a single column with the given name (or defaults to `"value"` if no name is provided). This is useful when piping a primitive value into a function that only takes `datatable` as an input. -In the example above, `ply` expects each `fn` subexpression to return a `datatable` in order to merge the results of each `fn` back into a `datatable`, but using a `math` aggregation in the subexpressions returns a single `math` value, which is then cast into a `datatable` using `as`. +In the example, `ply` expects each `fn` subexpression to return a `datatable` in order to merge the results of each `fn` back into a `datatable`, but using a `math` aggregation in the subexpressions returns a single `math` value, which is then cast into a `datatable` using `as`. *Accepts:* `string`, `boolean`, `number`, `null` @@ -496,14 +496,14 @@ containerStyle backgroundImage={asset id=asset-f40d2292-cf9e-4f2c-8c6f-a504a25e9 *Code example* [source,text] ---- -shape "star" fill="#E61D35" maintainAspect=true -| render containerStyle={ - containerStyle backgroundColor="#F8D546" - borderRadius="200px" - border="4px solid #05509F" - padding="0px" - opacity="0.9" - overflow="hidden" +shape "star" fill="#E61D35" maintainAspect=true +| render containerStyle={ + containerStyle backgroundColor="#F8D546" + borderRadius="200px" + border="4px solid #05509F" + padding="0px" + opacity="0.9" + overflow="hidden" } ---- @@ -1437,8 +1437,8 @@ Aliases: `dataurl`, `url` |`string`, `null` |The HTTP(S) URL or `base64` data URL of an image. -Example value for the _Unnamed_ argument, formatted as a `base64` data URL: -[source, url] +Example value for the _Unnamed_ argument, formatted as a `base64` data URL: +[source, url] ------------ data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+ ------------ @@ -2052,8 +2052,8 @@ Default: `null` |`string`, `null` |The image to repeat. Provide an image asset as a `base64` data URL, or pass in a sub-expression. -Example value for the `image` argument, formatted as a `base64` data URL: -[source, url] +Example value for the `image` argument, formatted as a `base64` data URL: +[source, url] ------------ data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%0A%3Csvg%20viewBox%3D%22-3.948730230331421%20-1.7549896240234375%20245.25946044921875%20241.40370178222656%22%20width%3D%22245.25946044921875%22%20height%3D%22241.40370178222656%22%20style%3D%22enable-background%3Anew%200%200%20686.2%20235.7%3B%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cdefs%3E%0A%20%20%20%20%3Cstyle%20type%3D%22text%2Fcss%22%3E%0A%09.st0%7Bfill%3A%232D2D2D%3B%7D%0A%3C%2Fstyle%3E%0A%20%20%3C%2Fdefs%3E%0A%20%20%3Cg%20transform%3D%22matrix%281%2C%200%2C%200%2C%201%2C%200%2C%200%29%22%3E%0A%20%20%20%20%3Cg%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M329.4%2C160.3l4.7-0.5l0.3%2C9.6c-12.4%2C1.7-23%2C2.6-31.8%2C2.6c-11.7%2C0-20-3.4-24.9-10.2%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-4.9-6.8-7.3-17.4-7.3-31.7c0-28.6%2C11.4-42.9%2C34.1-42.9c11%2C0%2C19.2%2C3.1%2C24.6%2C9.2c5.4%2C6.1%2C8.1%2C15.8%2C8.1%2C28.9l-0.7%2C9.3h-53.8%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc0%2C9%2C1.6%2C15.7%2C4.9%2C20c3.3%2C4.3%2C8.9%2C6.5%2C17%2C6.5C312.8%2C161.2%2C321.1%2C160.9%2C329.4%2C160.3z%20M325%2C124.9c0-10-1.6-17.1-4.8-21.2%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-3.2-4.1-8.4-6.2-15.6-6.2c-7.2%2C0-12.7%2C2.2-16.3%2C6.5c-3.6%2C4.3-5.5%2C11.3-5.6%2C20.9H325z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M354.3%2C171.4V64h12.2v107.4H354.3z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M443.5%2C113.5v41.1c0%2C4.1%2C10.1%2C3.9%2C10.1%2C3.9l-0.6%2C10.8c-8.6%2C0-15.7%2C0.7-20-3.4c-9.8%2C4.3-19.5%2C6.1-29.3%2C6.1%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-7.5%2C0-13.2-2.1-17.1-6.4c-3.9-4.2-5.9-10.3-5.9-18.3c0-7.9%2C2-13.8%2C6-17.5c4-3.7%2C10.3-6.1%2C18.9-6.9l25.6-2.4v-7%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc0-5.5-1.2-9.5-3.6-11.9c-2.4-2.4-5.7-3.6-9.8-3.6l-32.1%2C0V87.2h31.3c9.2%2C0%2C15.9%2C2.1%2C20.1%2C6.4C441.4%2C97.8%2C443.5%2C104.5%2C443.5%2C113.5%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bz%20M393.3%2C146.7c0%2C10%2C4.1%2C15%2C12.4%2C15c7.4%2C0%2C14.7-1.2%2C21.8-3.7l3.7-1.3v-26.9l-24.1%2C2.3c-4.9%2C0.4-8.4%2C1.8-10.6%2C4.2%26%2310%3B%26%239%3B%26%239%3B%26%239%3BC394.4%2C138.7%2C393.3%2C142.2%2C393.3%2C146.7z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M491.2%2C98.2c-11.8%2C0-17.8%2C4.1-17.8%2C12.4c0%2C3.8%2C1.4%2C6.5%2C4.1%2C8.1c2.7%2C1.6%2C8.9%2C3.2%2C18.6%2C4.9%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc9.7%2C1.7%2C16.5%2C4%2C20.5%2C7.1c4%2C3%2C6%2C8.7%2C6%2C17.1c0%2C8.4-2.7%2C14.5-8.1%2C18.4c-5.4%2C3.9-13.2%2C5.9-23.6%2C5.9c-6.7%2C0-29.2-2.5-29.2-2.5%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bl0.7-10.6c12.9%2C1.2%2C22.3%2C2.2%2C28.6%2C2.2c6.3%2C0%2C11.1-1%2C14.4-3c3.3-2%2C5-5.4%2C5-10.1c0-4.7-1.4-7.9-4.2-9.6c-2.8-1.7-9-3.3-18.6-4.8%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-9.6-1.5-16.4-3.7-20.4-6.7c-4-2.9-6-8.4-6-16.3c0-7.9%2C2.8-13.8%2C8.4-17.6c5.6-3.8%2C12.6-5.7%2C20.9-5.7c6.6%2C0%2C29.6%2C1.7%2C29.6%2C1.7%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bv10.7C508.1%2C99%2C498.2%2C98.2%2C491.2%2C98.2z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M581.7%2C99.5h-25.9v39c0%2C9.3%2C0.7%2C15.5%2C2%2C18.4c1.4%2C2.9%2C4.6%2C4.4%2C9.7%2C4.4l14.5-1l0.8%2C10.1%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-7.3%2C1.2-12.8%2C1.8-16.6%2C1.8c-8.5%2C0-14.3-2.1-17.6-6.2c-3.3-4.1-4.9-12-4.9-23.6V99.5h-11.6V88.9h11.6V63.9h12.1v24.9h25.9V99.5z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M598.7%2C78.4V64.3h12.2v14.2H598.7z%20M598.7%2C171.4V88.9h12.2v82.5H598.7z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M663.8%2C87.2c3.6%2C0%2C9.7%2C0.7%2C18.3%2C2l3.9%2C0.5l-0.5%2C9.9c-8.7-1-15.1-1.5-19.2-1.5c-9.2%2C0-15.5%2C2.2-18.8%2C6.6%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-3.3%2C4.4-5%2C12.6-5%2C24.5c0%2C11.9%2C1.5%2C20.2%2C4.6%2C24.9c3.1%2C4.7%2C9.5%2C7%2C19.3%2C7l19.2-1.5l0.5%2C10.1c-10.1%2C1.5-17.7%2C2.3-22.7%2C2.3%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-12.7%2C0-21.5-3.3-26.3-9.8c-4.8-6.5-7.3-17.5-7.3-33c0-15.5%2C2.6-26.4%2C7.8-32.6C643%2C90.4%2C651.7%2C87.2%2C663.8%2C87.2z%22%2F%3E%0A%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M236.6%2C123.5c0-19.8-12.3-37.2-30.8-43.9c0.8-4.2%2C1.2-8.4%2C1.2-12.7C207%2C30%2C177%2C0%2C140.2%2C0%26%2310%3B%26%239%3B%26%239%3BC118.6%2C0%2C98.6%2C10.3%2C86%2C27.7c-6.2-4.8-13.8-7.4-21.7-7.4c-19.6%2C0-35.5%2C15.9-35.5%2C35.5c0%2C4.3%2C0.8%2C8.5%2C2.2%2C12.4%26%2310%3B%26%239%3B%26%239%3BC12.6%2C74.8%2C0%2C92.5%2C0%2C112.2c0%2C19.9%2C12.4%2C37.3%2C30.9%2C44c-0.8%2C4.1-1.2%2C8.4-1.2%2C12.7c0%2C36.8%2C29.9%2C66.7%2C66.7%2C66.7%26%2310%3B%26%239%3B%26%239%3Bc21.6%2C0%2C41.6-10.4%2C54.1-27.8c6.2%2C4.9%2C13.8%2C7.6%2C21.7%2C7.6c19.6%2C0%2C35.5-15.9%2C35.5-35.5c0-4.3-0.8-8.5-2.2-12.4%26%2310%3B%26%239%3B%26%239%3BC223.9%2C160.9%2C236.6%2C143.2%2C236.6%2C123.5z%20M91.6%2C34.8c10.9-15.9%2C28.9-25.4%2C48.1-25.4c32.2%2C0%2C58.4%2C26.2%2C58.4%2C58.4%26%2310%3B%26%239%3B%26%239%3Bc0%2C3.9-0.4%2C7.7-1.1%2C11.5l-52.2%2C45.8L93%2C101.5L82.9%2C79.9L91.6%2C34.8z%20M65.4%2C29c6.2%2C0%2C12.1%2C2%2C17%2C5.7l-7.8%2C40.3l-35.5-8.4%26%2310%3B%26%239%3B%26%239%3Bc-1.1-3.1-1.7-6.3-1.7-9.7C37.4%2C41.6%2C49.9%2C29%2C65.4%2C29z%20M9.1%2C112.3c0-16.7%2C11-31.9%2C26.9-37.2L75%2C84.4l9.1%2C19.5l-49.8%2C45%26%2310%3B%26%239%3B%26%239%3BC19.2%2C143.1%2C9.1%2C128.6%2C9.1%2C112.3z%20M145.2%2C200.9c-10.9%2C16.1-29%2C25.6-48.4%2C25.6c-32.3%2C0-58.6-26.3-58.6-58.5c0-4%2C0.4-7.9%2C1.1-11.7%26%2310%3B%26%239%3B%26%239%3Bl50.9-46l52%2C23.7l11.5%2C22L145.2%2C200.9z%20M171.2%2C206.6c-6.1%2C0-12-2-16.9-5.8l7.7-40.2l35.4%2C8.3c1.1%2C3.1%2C1.7%2C6.3%2C1.7%2C9.7%26%2310%3B%26%239%3B%26%239%3BC199.2%2C194.1%2C186.6%2C206.6%2C171.2%2C206.6z%20M200.5%2C160.5l-39-9.1l-10.4-19.8l51-44.7c15.1%2C5.7%2C25.2%2C20.2%2C25.2%2C36.5%26%2310%3B%26%239%3B%26%239%3BC227.4%2C140.1%2C216.4%2C155.3%2C200.5%2C160.5z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E ------------ @@ -2132,8 +2132,8 @@ Default: `null` |`string`, `null` |The image to reveal. Provide an image asset as a `base64` data URL, or pass in a sub-expression. -Example value for the `image` argument, formatted as a `base64` data URL: -[source, url] +Example value for the `image` argument, formatted as a `base64` data URL: +[source, url] ------------ data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%0A%3Csvg%20viewBox%3D%22-3.948730230331421%20-1.7549896240234375%20245.25946044921875%20241.40370178222656%22%20width%3D%22245.25946044921875%22%20height%3D%22241.40370178222656%22%20style%3D%22enable-background%3Anew%200%200%20686.2%20235.7%3B%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cdefs%3E%0A%20%20%20%20%3Cstyle%20type%3D%22text%2Fcss%22%3E%0A%09.st0%7Bfill%3A%232D2D2D%3B%7D%0A%3C%2Fstyle%3E%0A%20%20%3C%2Fdefs%3E%0A%20%20%3Cg%20transform%3D%22matrix%281%2C%200%2C%200%2C%201%2C%200%2C%200%29%22%3E%0A%20%20%20%20%3Cg%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M329.4%2C160.3l4.7-0.5l0.3%2C9.6c-12.4%2C1.7-23%2C2.6-31.8%2C2.6c-11.7%2C0-20-3.4-24.9-10.2%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-4.9-6.8-7.3-17.4-7.3-31.7c0-28.6%2C11.4-42.9%2C34.1-42.9c11%2C0%2C19.2%2C3.1%2C24.6%2C9.2c5.4%2C6.1%2C8.1%2C15.8%2C8.1%2C28.9l-0.7%2C9.3h-53.8%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc0%2C9%2C1.6%2C15.7%2C4.9%2C20c3.3%2C4.3%2C8.9%2C6.5%2C17%2C6.5C312.8%2C161.2%2C321.1%2C160.9%2C329.4%2C160.3z%20M325%2C124.9c0-10-1.6-17.1-4.8-21.2%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-3.2-4.1-8.4-6.2-15.6-6.2c-7.2%2C0-12.7%2C2.2-16.3%2C6.5c-3.6%2C4.3-5.5%2C11.3-5.6%2C20.9H325z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M354.3%2C171.4V64h12.2v107.4H354.3z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M443.5%2C113.5v41.1c0%2C4.1%2C10.1%2C3.9%2C10.1%2C3.9l-0.6%2C10.8c-8.6%2C0-15.7%2C0.7-20-3.4c-9.8%2C4.3-19.5%2C6.1-29.3%2C6.1%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-7.5%2C0-13.2-2.1-17.1-6.4c-3.9-4.2-5.9-10.3-5.9-18.3c0-7.9%2C2-13.8%2C6-17.5c4-3.7%2C10.3-6.1%2C18.9-6.9l25.6-2.4v-7%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc0-5.5-1.2-9.5-3.6-11.9c-2.4-2.4-5.7-3.6-9.8-3.6l-32.1%2C0V87.2h31.3c9.2%2C0%2C15.9%2C2.1%2C20.1%2C6.4C441.4%2C97.8%2C443.5%2C104.5%2C443.5%2C113.5%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bz%20M393.3%2C146.7c0%2C10%2C4.1%2C15%2C12.4%2C15c7.4%2C0%2C14.7-1.2%2C21.8-3.7l3.7-1.3v-26.9l-24.1%2C2.3c-4.9%2C0.4-8.4%2C1.8-10.6%2C4.2%26%2310%3B%26%239%3B%26%239%3B%26%239%3BC394.4%2C138.7%2C393.3%2C142.2%2C393.3%2C146.7z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M491.2%2C98.2c-11.8%2C0-17.8%2C4.1-17.8%2C12.4c0%2C3.8%2C1.4%2C6.5%2C4.1%2C8.1c2.7%2C1.6%2C8.9%2C3.2%2C18.6%2C4.9%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc9.7%2C1.7%2C16.5%2C4%2C20.5%2C7.1c4%2C3%2C6%2C8.7%2C6%2C17.1c0%2C8.4-2.7%2C14.5-8.1%2C18.4c-5.4%2C3.9-13.2%2C5.9-23.6%2C5.9c-6.7%2C0-29.2-2.5-29.2-2.5%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bl0.7-10.6c12.9%2C1.2%2C22.3%2C2.2%2C28.6%2C2.2c6.3%2C0%2C11.1-1%2C14.4-3c3.3-2%2C5-5.4%2C5-10.1c0-4.7-1.4-7.9-4.2-9.6c-2.8-1.7-9-3.3-18.6-4.8%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-9.6-1.5-16.4-3.7-20.4-6.7c-4-2.9-6-8.4-6-16.3c0-7.9%2C2.8-13.8%2C8.4-17.6c5.6-3.8%2C12.6-5.7%2C20.9-5.7c6.6%2C0%2C29.6%2C1.7%2C29.6%2C1.7%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bv10.7C508.1%2C99%2C498.2%2C98.2%2C491.2%2C98.2z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M581.7%2C99.5h-25.9v39c0%2C9.3%2C0.7%2C15.5%2C2%2C18.4c1.4%2C2.9%2C4.6%2C4.4%2C9.7%2C4.4l14.5-1l0.8%2C10.1%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-7.3%2C1.2-12.8%2C1.8-16.6%2C1.8c-8.5%2C0-14.3-2.1-17.6-6.2c-3.3-4.1-4.9-12-4.9-23.6V99.5h-11.6V88.9h11.6V63.9h12.1v24.9h25.9V99.5z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M598.7%2C78.4V64.3h12.2v14.2H598.7z%20M598.7%2C171.4V88.9h12.2v82.5H598.7z%22%2F%3E%0A%20%20%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M663.8%2C87.2c3.6%2C0%2C9.7%2C0.7%2C18.3%2C2l3.9%2C0.5l-0.5%2C9.9c-8.7-1-15.1-1.5-19.2-1.5c-9.2%2C0-15.5%2C2.2-18.8%2C6.6%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-3.3%2C4.4-5%2C12.6-5%2C24.5c0%2C11.9%2C1.5%2C20.2%2C4.6%2C24.9c3.1%2C4.7%2C9.5%2C7%2C19.3%2C7l19.2-1.5l0.5%2C10.1c-10.1%2C1.5-17.7%2C2.3-22.7%2C2.3%26%2310%3B%26%239%3B%26%239%3B%26%239%3Bc-12.7%2C0-21.5-3.3-26.3-9.8c-4.8-6.5-7.3-17.5-7.3-33c0-15.5%2C2.6-26.4%2C7.8-32.6C643%2C90.4%2C651.7%2C87.2%2C663.8%2C87.2z%22%2F%3E%0A%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3Cpath%20class%3D%22st0%22%20d%3D%22M236.6%2C123.5c0-19.8-12.3-37.2-30.8-43.9c0.8-4.2%2C1.2-8.4%2C1.2-12.7C207%2C30%2C177%2C0%2C140.2%2C0%26%2310%3B%26%239%3B%26%239%3BC118.6%2C0%2C98.6%2C10.3%2C86%2C27.7c-6.2-4.8-13.8-7.4-21.7-7.4c-19.6%2C0-35.5%2C15.9-35.5%2C35.5c0%2C4.3%2C0.8%2C8.5%2C2.2%2C12.4%26%2310%3B%26%239%3B%26%239%3BC12.6%2C74.8%2C0%2C92.5%2C0%2C112.2c0%2C19.9%2C12.4%2C37.3%2C30.9%2C44c-0.8%2C4.1-1.2%2C8.4-1.2%2C12.7c0%2C36.8%2C29.9%2C66.7%2C66.7%2C66.7%26%2310%3B%26%239%3B%26%239%3Bc21.6%2C0%2C41.6-10.4%2C54.1-27.8c6.2%2C4.9%2C13.8%2C7.6%2C21.7%2C7.6c19.6%2C0%2C35.5-15.9%2C35.5-35.5c0-4.3-0.8-8.5-2.2-12.4%26%2310%3B%26%239%3B%26%239%3BC223.9%2C160.9%2C236.6%2C143.2%2C236.6%2C123.5z%20M91.6%2C34.8c10.9-15.9%2C28.9-25.4%2C48.1-25.4c32.2%2C0%2C58.4%2C26.2%2C58.4%2C58.4%26%2310%3B%26%239%3B%26%239%3Bc0%2C3.9-0.4%2C7.7-1.1%2C11.5l-52.2%2C45.8L93%2C101.5L82.9%2C79.9L91.6%2C34.8z%20M65.4%2C29c6.2%2C0%2C12.1%2C2%2C17%2C5.7l-7.8%2C40.3l-35.5-8.4%26%2310%3B%26%239%3B%26%239%3Bc-1.1-3.1-1.7-6.3-1.7-9.7C37.4%2C41.6%2C49.9%2C29%2C65.4%2C29z%20M9.1%2C112.3c0-16.7%2C11-31.9%2C26.9-37.2L75%2C84.4l9.1%2C19.5l-49.8%2C45%26%2310%3B%26%239%3B%26%239%3BC19.2%2C143.1%2C9.1%2C128.6%2C9.1%2C112.3z%20M145.2%2C200.9c-10.9%2C16.1-29%2C25.6-48.4%2C25.6c-32.3%2C0-58.6-26.3-58.6-58.5c0-4%2C0.4-7.9%2C1.1-11.7%26%2310%3B%26%239%3B%26%239%3Bl50.9-46l52%2C23.7l11.5%2C22L145.2%2C200.9z%20M171.2%2C206.6c-6.1%2C0-12-2-16.9-5.8l7.7-40.2l35.4%2C8.3c1.1%2C3.1%2C1.7%2C6.3%2C1.7%2C9.7%26%2310%3B%26%239%3B%26%239%3BC199.2%2C194.1%2C186.6%2C206.6%2C171.2%2C206.6z%20M200.5%2C160.5l-39-9.1l-10.4-19.8l51-44.7c15.1%2C5.7%2C25.2%2C20.2%2C25.2%2C36.5%26%2310%3B%26%239%3B%26%239%3BC227.4%2C140.1%2C216.4%2C155.3%2C200.5%2C160.5z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E ------------ diff --git a/docs/dev-tools/console/console.asciidoc b/docs/dev-tools/console/console.asciidoc index 26620688499af6..caffef7995fbfc 100644 --- a/docs/dev-tools/console/console.asciidoc +++ b/docs/dev-tools/console/console.asciidoc @@ -18,8 +18,8 @@ NOTE: You are unable to interact with the REST API of {kib} with the Console. [[console-api]] === Write requests -Console understands commands in a cURL-like syntax. -For example, the following is a `GET` request to the {es} `_search` API. +Console understands commands in a cURL-like syntax. +For example, the following is a `GET` request to the {es} `_search` API. [source,js] ---------------------------------- @@ -43,23 +43,23 @@ curl -XGET "http://localhost:9200/_search" -d' }' ---------------------------------- -If you paste the above command into Console, {kib} automatically converts it +When you paste the command into Console, {kib} automatically converts it to Console syntax. Alternatively, if you want to want to see Console syntax in cURL, -click the action icon (image:dev-tools/console/images/wrench.png[]) and select *Copy as cURL*. +click the action icon (image:dev-tools/console/images/wrench.png[]) and select *Copy as cURL*. [float] [[console-autocomplete]] ==== Autocomplete When you're typing a command, Console makes context-sensitive suggestions. -These suggestions show you the parameters for each API and speed up your typing. -To configure your preferences for autocomplete, go to -<>. +These suggestions show you the parameters for each API and speed up your typing. +To configure your preferences for autocomplete, go to +<>. [float] [[auto-formatting]] ==== Auto-formatting -The auto-formatting +The auto-formatting capability can help you format requests. Select one or more requests that you want to format, click the action icon (image:dev-tools/console/images/wrench.png[]), and then select *Auto indent*. @@ -69,27 +69,27 @@ For example, you might have a request formatted like this: [role="screenshot"] image::dev-tools/console/images/copy-curl.png["Console close-up"] -Console adjusts the JSON body of the request to apply the indents. +Console adjusts the JSON body of the request to apply the indents. [role="screenshot"] image::dev-tools/console/images/request.png["Console close-up"] -If you select *Auto indent* on a request that is already well formatted, -Console collapses the request body to a single line per document. +If you select *Auto indent* on a request that is already well formatted, +Console collapses the request body to a single line per document. This is helpful when working with the {es} {ref}/docs-bulk.html[bulk APIs]. [float] [[console-request]] -=== Submit requests +=== Submit requests -When you're ready to submit the request to {es}, click the +When you're ready to submit the request to {es}, click the green triangle. You can select multiple requests and submit them together. -Console sends the requests to {es} one by one and shows the output -in the response pane. Submitting multiple request is helpful when you're debugging an issue or trying query +Console sends the requests to {es} one by one and shows the output +in the response pane. Submitting multiple request is helpful when you're debugging an issue or trying query combinations in multiple scenarios. @@ -105,7 +105,7 @@ the action icon (image:dev-tools/console/images/wrench.png[]) and select [[console-history]] === Get your request history -Console maintains a list of the last 500 requests that {es} successfully executed. +Console maintains a list of the last 500 requests that {es} successfully executed. To view your most recent requests, click *History*. If you select a request and click *Apply*, {kib} adds it to the editor at the current cursor position. @@ -113,7 +113,7 @@ and click *Apply*, {kib} adds it to the editor at the current cursor position. [[configuring-console]] === Configure Console settings -You can configure the Console font size, JSON syntax, +You can configure the Console font size, JSON syntax, and autocomplete suggestions in *Settings*. [role="screenshot"] @@ -130,9 +130,7 @@ shortcuts, click *Help*. [[console-settings]] === Disable Console -If you don’t want to use Console, you can disable it by setting `console.enabled` -to `false` in your `kibana.yml` configuration file. Changing this setting -causes the server to regenerate assets on the next startup, +If you don’t want to use Console, you can disable it by setting `console.enabled` +to `false` in your `kibana.yml` configuration file. Changing this setting +causes the server to regenerate assets on the next startup, which might cause a delay before pages start being served. - - diff --git a/docs/dev-tools/searchprofiler/more-complicated.asciidoc b/docs/dev-tools/searchprofiler/more-complicated.asciidoc index bd74a1095083f6..a0771f4a0f240d 100644 --- a/docs/dev-tools/searchprofiler/more-complicated.asciidoc +++ b/docs/dev-tools/searchprofiler/more-complicated.asciidoc @@ -25,7 +25,7 @@ POST test/_bulk // CONSOLE -- -. From the {searchprofiler}, enter "test" in the Index field above the query editor to restrict profiled +. From the {searchprofiler}, enter "test" in the *Index* field to restrict profiled queries to the `test` index. . Replace the default `match_all` query in the query editor with a query that has two sub-query @@ -66,7 +66,7 @@ components and includes a simple aggregation, like the example below. // NOTCONSOLE -- -. Click *Profile* to profile the query and visualize the results. +. Click *Profile* to profile the query and visualize the results. . Select the shard to view the query details. + [role="screenshot"] @@ -100,5 +100,5 @@ Select the name of the shard to view the aggregation details and timing breakdow image::dev-tools/searchprofiler/images/gs10.png["Drilling into the first shard's details"] For more information about how the {searchprofiler} works, how timings are calculated, and -how to interpret various results, see +how to interpret various results, see {ref}/search-profile.html#profiling-queries[Profiling queries]. diff --git a/docs/developer/core/development-dependencies.asciidoc b/docs/developer/core/development-dependencies.asciidoc index d430667449afa5..285d338a23a0dc 100644 --- a/docs/developer/core/development-dependencies.asciidoc +++ b/docs/developer/core/development-dependencies.asciidoc @@ -96,8 +96,8 @@ module.exports = window.angular; What this shim does is fairly simple if you go line by line: -. makes sure that jQuery is loaded before angular (which actually runs the shim above) +. makes sure that jQuery is loaded before angular (which actually runs the shim) . load the angular.js file from the node_modules directory . load the angular-elastic plugin, a plugin we want to always be included whenever we import angular . use the `ui/modules` module to add the module exported by angular-elastic as a dependency to the `kibana` angular module -. finally, export the window.angular variable. This means that writing `import angular from 'angular';` will properly set the angular variable to the angular library, rather than undefined which is the default behavior. \ No newline at end of file +. finally, export the window.angular variable. This means that writing `import angular from 'angular';` will properly set the angular variable to the angular library, rather than undefined which is the default behavior. diff --git a/docs/developer/core/development-modules.asciidoc b/docs/developer/core/development-modules.asciidoc index b36be6bbb5d25b..cc5cd69ed8cb98 100644 --- a/docs/developer/core/development-modules.asciidoc +++ b/docs/developer/core/development-modules.asciidoc @@ -20,7 +20,7 @@ certain components. Here is a breakdown of those modules: the required modules and import them were they are actually necessary. - *`import 'ui/autoload/all'`* - Imports all of the above modules + Imports all of the modules [float] ==== Resolving Require Paths @@ -60,4 +60,4 @@ Here is how import/require statements are resolved to a file: ** path/index + '.js' ** path/index + '.json' ** path/index - * if none of the above paths matches then an error is thrown \ No newline at end of file + * if none of the paths matches then an error is thrown diff --git a/docs/developer/plugin/development-plugin-feature-registration.asciidoc b/docs/developer/plugin/development-plugin-feature-registration.asciidoc index f9078440cff2b7..2c686964d369aa 100644 --- a/docs/developer/plugin/development-plugin-feature-registration.asciidoc +++ b/docs/developer/plugin/development-plugin-feature-registration.asciidoc @@ -175,7 +175,7 @@ init(server) { } ----------- -Unlike the Canvas example above, Dev Tools does not require access to any saved objects to function. Dev Tools does specify an API endpoint, however. When this is configured, the Security plugin will automatically authorize access to any server API route that is tagged with `access:console`, similar to the following: +Unlike the Canvas example, Dev Tools does not require access to any saved objects to function. Dev Tools does specify an API endpoint, however. When this is configured, the Security plugin will automatically authorize access to any server API route that is tagged with `access:console`, similar to the following: ["source","javascript"] ----------- diff --git a/docs/developer/plugin/development-plugin-localization.asciidoc b/docs/developer/plugin/development-plugin-localization.asciidoc index ff497ec40e30eb..78ee933f681f48 100644 --- a/docs/developer/plugin/development-plugin-localization.asciidoc +++ b/docs/developer/plugin/development-plugin-localization.asciidoc @@ -68,7 +68,7 @@ This outputs a `en.json` file inside the `translations` directory. To localize o Checking i18n does the following: * Checks all existing labels for violations. -* Takes translations from `.i18nrc.json` and compares them to the messages extracted and validated at the step above and: +* Takes translations from `.i18nrc.json` and compares them to the messages extracted and validated. ** Checks for unused translations. If you remove a label that has a corresponding translation, you must also remove the label from the translations file. ** Checks for incompatible translations. If you add or remove a new parameter from an existing string, you must also remove the label from the translations file. @@ -86,7 +86,7 @@ node scripts/i18n_check --fix --include-config ../kibana-extra/myPlugin/.i18nrc. Kibana relies on several UI frameworks (ReactJS and AngularJS) and requires localization in different environments (browser and NodeJS). The internationalization engine is framework agnostic and consumable in -all parts of Kibana (ReactJS, AngularJS and NodeJS). +all parts of Kibana (ReactJS, AngularJS and NodeJS). To simplify internationalization in UI frameworks, additional abstractions are @@ -112,7 +112,7 @@ export const HELLO_WORLD = i18n.translate('hello.wonderful.world', { Full details are {repo}tree/master/packages/kbn-i18n#vanilla-js[here]. [float] -===== i18n for React +===== i18n for React To localize strings in React, use either `FormattedMessage` or `i18n.translate`. @@ -138,7 +138,7 @@ Full details are {repo}tree/master/packages/kbn-i18n#react[here]. [float] -===== i18n for Angular +===== i18n for Angular You are encouraged to use `i18n.translate()` by statically importing `i18n` from `@kbn/i18n` wherever possible in your Angular code. Angular wrappers use the translation `service` with the i18n engine under the hood. diff --git a/docs/developer/pr-review.asciidoc b/docs/developer/pr-review.asciidoc index dee40f51186725..304718e437dc57 100644 --- a/docs/developer/pr-review.asciidoc +++ b/docs/developer/pr-review.asciidoc @@ -67,7 +67,7 @@ Enhancements are pretty much always going to have extensive unit tests as a base [float] === Product level review -Reviewers are not simply evaluating the code itself, they are also evaluating the quality of the user-facing change in the product. This generally means they need to check out the branch locally and "play around" with it. In addition to the "do we want this change in the product" details from above, the reviewer should be looking for bugs and evaluating how approachable and useful the feature is as implemented. Special attention should be given to error scenarios and edge cases to ensure they are all handled well within the product. +Reviewers are not simply evaluating the code itself, they are also evaluating the quality of the user-facing change in the product. This generally means they need to check out the branch locally and "play around" with it. In addition to the "do we want this change in the product" details, the reviewer should be looking for bugs and evaluating how approachable and useful the feature is as implemented. Special attention should be given to error scenarios and edge cases to ensure they are all handled well within the product. [float] @@ -107,7 +107,7 @@ Conflicting opinions between reviewers and authors happen, and sometimes it is h Whether or not a bit of feedback is appropriate for a pull request is often dependent on the motivation for giving the feedback in the first place. -_Demanding_ an author make changes based primarily on the mindset of "how would I write this code?" isn't appropriate. The reviewer didn't write the code, and their critical purpose in the review process is not to craft the contribution into a form that is simply whatever they would have written if they had. If a reviewer wants to provide this type of feedback, they should qualify it as a "nit" as mentioned in the nitpicking section above to make it clear that the author can take it or leave it. +_Demanding_ an author make changes based primarily on the mindset of "how would I write this code?" isn't appropriate. The reviewer didn't write the code, and their critical purpose in the review process is not to craft the contribution into a form that is simply whatever they would have written if they had. If a reviewer wants to provide this type of feedback, they should qualify it as a "nit" as mentioned in the nitpicking section to make it clear that the author can take it or leave it. Inflammatory feedback such as "this is crap" isn't feedback at all. It's both mean and unhelpful, and it is never appropriate. diff --git a/docs/infrastructure/metrics-explorer.asciidoc b/docs/infrastructure/metrics-explorer.asciidoc index c20718dac1c7ac..d47581ffe720ac 100644 --- a/docs/infrastructure/metrics-explorer.asciidoc +++ b/docs/infrastructure/metrics-explorer.asciidoc @@ -44,7 +44,7 @@ In this step we'll leave the aggregation dropdown set to *Average* but you can t 4. In the *graph per* dropdown, enter `host.name` and select this field. You will see a separate graph for each host you are monitoring. -If you are collecting metrics for multiple hosts, you will see something like the screenshot above. +If you are collecting metrics for multiple hosts, multiple graphics are displayed. If you only have metrics for a single host, you will see a single graph. Congratulations! Either way, you've explored your first metric. diff --git a/docs/logs/using.asciidoc b/docs/logs/using.asciidoc index d84a9260521c7e..8074cc4a8026d4 100644 --- a/docs/logs/using.asciidoc +++ b/docs/logs/using.asciidoc @@ -31,9 +31,7 @@ If so, <> to change the Click image:images/time-filter-calendar.png[time filter calendar], then choose the time range for the logs. -Log entries for the specified time appear in the middle of the page, with the earlier entries above and the later entries below. - -To quickly jump to a nearby point in time, click the minimap timeline to the right. +Log entries for the specified time appear in the middle of the page. To quickly jump to a nearby point in time, click the minimap timeline to the right. // ++ what's this thing called? It's minimap in the UI. Would timeline be better? [float] diff --git a/docs/management/numeral.asciidoc b/docs/management/numeral.asciidoc index 861277fd184783..65dfdab3abd3c5 100644 --- a/docs/management/numeral.asciidoc +++ b/docs/management/numeral.asciidoc @@ -145,7 +145,7 @@ with multiple forms, such as German. [float] === Complete number pattern reference -These number formats, combined with the patterns described above, +These number formats, combined with the previously described patterns, produce the complete set of options for numeral formatting. The output here is all for the `en` locale. @@ -180,5 +180,3 @@ The output here is all for the `en` locale. | 1e-27 | 000 | 1e-27 | -1e-27 | 000 | -1e-27 |=== - - diff --git a/docs/management/rollups/create_and_manage_rollups.asciidoc b/docs/management/rollups/create_and_manage_rollups.asciidoc index b07f075f880322..83e1b7c16f8b47 100644 --- a/docs/management/rollups/create_and_manage_rollups.asciidoc +++ b/docs/management/rollups/create_and_manage_rollups.asciidoc @@ -128,7 +128,7 @@ rollup index, or you can remove or archive it using <> file to proxy EMS requests through the Kibana server. -. Update your firewall rules to whitelist connections from your Kibana server to the EMS domains listed above. +. Update your firewall rules to whitelist connections from your Kibana server to the EMS domains. NOTE: Coordinate map and region map visualizations do not support `map.proxyElasticMapsServiceInMaps` and will not proxy EMS requests through the Kibana server. diff --git a/docs/setup/docker.asciidoc b/docs/setup/docker.asciidoc index 8fd7b0490e194a..ddabce3d5b8425 100644 --- a/docs/setup/docker.asciidoc +++ b/docs/setup/docker.asciidoc @@ -7,11 +7,11 @@ A list of all published Docker images and tags is available at https://www.docker.elastic.co[www.docker.elastic.co]. The source code is in https://github.com/elastic/dockerfiles/tree/{branch}/kibana[GitHub]. -These images are free to use under the Elastic license. They contain open source -and free commercial features and access to paid commercial features. -{stack-ov}/license-management.html[Start a 30-day trial] to try out all of the -paid commercial features. See the -https://www.elastic.co/subscriptions[Subscriptions] page for information about +These images are free to use under the Elastic license. They contain open source +and free commercial features and access to paid commercial features. +{stack-ov}/license-management.html[Start a 30-day trial] to try out all of the +paid commercial features. See the +https://www.elastic.co/subscriptions[Subscriptions] page for information about Elastic license levels. [float] @@ -35,8 +35,8 @@ ifeval::["{release-state}"!="unreleased"] docker pull {docker-repo}:{version} -------------------------------------------- -Alternatively, you can download other Docker images that contain only features -available under the Apache 2.0 license. To download the images, go to +Alternatively, you can download other Docker images that contain only features +available under the Apache 2.0 license. To download the images, go to https://www.docker.elastic.co[www.docker.elastic.co]. [float] @@ -96,7 +96,7 @@ Some example translations are shown here: `KIBANA_DEFAULTAPPID`:: `kibana.defaultAppId` `XPACK_MONITORING_ENABLED`:: `xpack.monitoring.enabled` -In general, any setting listed in <> can be +In general, any setting listed in <> can be configured with this technique. These variables can be set with +docker-compose+ like this: @@ -135,5 +135,5 @@ with a <> or via <>. IMPORTANT: If replacing `kibana.yml` with a custom version, be sure to copy the -above defaults to the custom file if you want to retain them. If not, they will +defaults to the custom file if you want to retain them. If not, they will be "masked" by the new file. diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 3d99e7298755f6..80d04c260e25f3 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -234,7 +234,8 @@ FeatureCollection. The file must use the https://en.wikipedia.org/wiki/World_Geodetic_System[WGS84 coordinate reference system (ESPG:4326)] and only include polygons. If the file is hosted on a separate domain from Kibana, the server needs to be CORS-enabled so Kibana can download the file. -The following example shows a valid regionmap configuration. +[[region-map-configuration-example]] +The following example shows a valid region map configuration. + -- map @@ -262,7 +263,7 @@ References the originating source of the geojson file. Supported on {ece}. [[regionmap-fields]]`map.regionmap.layers[].fields[]:`:: Mandatory. Each layer can contain multiple fields to indicate what properties from the geojson -features you wish to expose. The example above shows how to define multiple +features you wish to expose. This <> shows how to define multiple properties. Supported on {ece}. [[regionmap-field-description]]`map.regionmap.layers[].fields[].description:`:: diff --git a/docs/siem/index.asciidoc b/docs/siem/index.asciidoc index a15d860d76775b..9d17b5209304f0 100644 --- a/docs/siem/index.asciidoc +++ b/docs/siem/index.asciidoc @@ -4,7 +4,6 @@ [partintro] -- -beta[] The SIEM app in Kibana provides an interactive workspace for security teams to triage events and perform initial investigations. It enables analysis of diff --git a/docs/siem/siem-ui.asciidoc b/docs/siem/siem-ui.asciidoc index f01575a21b9f67..85253daaf29330 100644 --- a/docs/siem/siem-ui.asciidoc +++ b/docs/siem/siem-ui.asciidoc @@ -35,7 +35,7 @@ image::siem/images/network-ui.png[] [float] [[detections-ui]] -=== Detections +=== Detections (Beta) The Detections feature automatically searches for threats and creates signals when they are detected. Signal detection rules define the conditions diff --git a/docs/user/introduction.asciidoc b/docs/user/introduction.asciidoc index bbaf22b4978682..8b987f81779e37 100644 --- a/docs/user/introduction.asciidoc +++ b/docs/user/introduction.asciidoc @@ -85,7 +85,7 @@ image::images/intro-dashboard.png[] * <> allows you to display your data in line charts, bar graphs, pie charts, histograms, and tables -(just to name a few). It's also home to *Lens*, mentioned above. +(just to name a few). It's also home to *Lens*, the drag-and-drop interface. *Visualize* supports the ability to add interactive controls to your dashboard, and filter dashboard content in real time. diff --git a/docs/user/reporting/development/pdf-integration.asciidoc b/docs/user/reporting/development/pdf-integration.asciidoc index dc9e63f34b25eb..af5ba5be1636e3 100644 --- a/docs/user/reporting/development/pdf-integration.asciidoc +++ b/docs/user/reporting/development/pdf-integration.asciidoc @@ -51,8 +51,7 @@ should have their screenshot taken and when the Visualizations are done renderin The print layout takes a screenshot of every element with the `data-shared-item` attribute and includes the individual screenshots in the PDF. The print layout also uses the `data-title` and `data-description` -attributes on the same HTMLElement as the `data-shared-item` to specify the title and description -that appears right above the individual screenshots. +attributes on the same HTMLElement as the `data-shared-item` to specify the title and description. The preserve layout takes a screenshot of the element with the `data-shared-items-container` attribute. Additionally, reporting will resize the element with the `data-shared-items-container` to be the size specified in the layout dimensions. @@ -63,4 +62,4 @@ Reporting needs to determine when all of the visualizations have completed rende If there are multiple visualizations, the `data-shared-items-count` attribute should be specified to let Reporting know how many Visualizations to look for. Reporting will look at every element with the `data-shared-item` attribute and use the corresponding `data-render-complete` attribute and `renderComplete` events to listen for rendering to complete. When rendering is complete for a visualization -the `data-render-complete` attribute should be set to "true" and it should dispatch a custom DOM `renderComplete` event. \ No newline at end of file +the `data-render-complete` attribute should be set to "true" and it should dispatch a custom DOM `renderComplete` event. diff --git a/docs/user/security/securing-communications/elasticsearch-mutual-tls.asciidoc b/docs/user/security/securing-communications/elasticsearch-mutual-tls.asciidoc index 8d64a0e6e0c113..f5192f4641d4df 100644 --- a/docs/user/security/securing-communications/elasticsearch-mutual-tls.asciidoc +++ b/docs/user/security/securing-communications/elasticsearch-mutual-tls.asciidoc @@ -63,7 +63,7 @@ you have hostname verification enabled on {es}. -- {es} needs the appropriate CA certificate chain to properly establish trust when receiving connections from {kib}. -If you followed the instructions above to generate a client certificate, then you will have a PKCS#12 file for {kib}. You can extract the CA +If you followed the instructions to generate a client certificate, then you will have a PKCS#12 file for {kib}. You can extract the CA certificate chain from this file. For example: [source,sh] @@ -165,6 +165,6 @@ attempt to use them to authenticate to {es} via the native realm. . Restart {kib}. -NOTE: The steps above enable {kib} to authenticate to {es} using a certificate. However, end users will only be able to authenticate to +These steps enable {kib} to authenticate to {es} using a certificate. However, end users will only be able to authenticate to {kib} with a username and password. To allow end users to authenticate to {kib} using a client certificate, see <>. diff --git a/docs/user/security/securing-communications/index.asciidoc b/docs/user/security/securing-communications/index.asciidoc index 2ac08a4fab5ee5..97313c19f44cb9 100644 --- a/docs/user/security/securing-communications/index.asciidoc +++ b/docs/user/security/securing-communications/index.asciidoc @@ -150,7 +150,7 @@ elasticsearch.ssl.certificateAuthorities: ["/path/to/elasticsearch-ca.pem"] + -- WARNING: You should not use a PKCS#12 file that contains a private key. This is an unnecessary security risk. If you only have a PKCS#12 -file that contains a private key, a safer approach is to extract the CA certificate chain in PEM format as described above. +file that contains a private key, a safer approach is to extract the CA certificate chain in PEM format. Specify your PKCS#12 file in `kibana.yml`: @@ -188,5 +188,5 @@ verification. For more information about this setting, see <>. +. Optional: <>. . Optional: <>. @@ -103,8 +103,8 @@ You can manage privileges on the *Management / Security / Roles* page in {kib}. If you're using the native realm with Basic Authentication, you can assign roles using the *Management / Security / Users* page in {kib} or the -{ref}/security-api.html#security-user-apis[user management APIs]. For example, -the following creates a user named `jacknich` and assigns it the `kibana_admin` +{ref}/security-api.html#security-user-apis[user management APIs]. For example, +the following creates a user named `jacknich` and assigns it the `kibana_admin` role: [source,js] @@ -131,8 +131,8 @@ on specific index patterns. For more information, see . Verify that you can log in as a user. If you are running {kib} locally, go to `https://localhost:5601` and enter the credentials for a -user you've assigned a {kib} user role. For example, you could log in as the -`jacknich` user created above. +user you've assigned a {kib} user role. For example, you could log in as the user +`jacknich`. + -- diff --git a/docs/visualize/vega.asciidoc b/docs/visualize/vega.asciidoc index d5b7ccb12f48c3..c9cf1e7aeb8205 100644 --- a/docs/visualize/vega.asciidoc +++ b/docs/visualize/vega.asciidoc @@ -18,47 +18,47 @@ NOTE: In Vega it is possible to load data dynamically, e.g. by setting signals a * To experiment using sample data, first click the {kib} logo in the upper left hand corner and then click the link next to *Sample Data*. -* Once you have data loaded, go to *Visualize*, click *+*, and select *Vega* to see an example graph. -*Note*: The default graph is written in Vega-Lite, but you can build visualizations -in either language. See <> for more information. +* Once you have data loaded, go to *Visualize*, click *+*, and select *Vega* to see an example graph. +*Note*: The default graph is written in Vega-Lite, but you can build visualizations +in either language. See <> for more information. * Try changing `mark` from `line` to `point`, `area`, `bar`, `circle`, -or `square`. Check out the +or `square`. Check out the https://vega.github.io/vega-lite/docs/mark.html#mark-def[Vega-Lite docs] for more information. * Explore other available https://vega.github.io/vega/examples/[Vega] or -https://vega.github.io/vega-lite/examples/[Vega-Lite] visualizations. +https://vega.github.io/vega-lite/examples/[Vega-Lite] visualizations. *Note*: You might need to make URLs absolute, for example, replace `"url": "data/world-110m.json"` with -`"url": "https://vega.github.io/editor/data/world-110m.json"`. +`"url": "https://vega.github.io/editor/data/world-110m.json"`. See <>. -* For more information on getting started, check out this https://www.elastic.co/blog/getting-started-with-vega-visualizations-in-kibana[blog post]. +* For more information on getting started, check out this https://www.elastic.co/blog/getting-started-with-vega-visualizations-in-kibana[blog post]. [[vega-vs-vegalite]] === Vega vs Vega-Lite -The Vega visualization in {kib} supports both Vega and Vega-Lite. You can use the -`schema` value to define which language you would like to use and its minimum +The Vega visualization in {kib} supports both Vega and Vega-Lite. You can use the +`schema` value to define which language you would like to use and its minimum required version. - -For example: + +For example: * Vega-Lite v2: `$schema: https://vega.github.io/schema/vega-lite/v2.json` * Vega v4: `$schema: https://vega.github.io/schema/vega/v4.json` - + The `schema` URL is only used for identification, and does not need to be accessible by {kib}. -Vega-Lite is a simplified version of Vega; it automates some constructions and has -much shorter specifications than Vega. Vega-Lite is automatically converted into +Vega-Lite is a simplified version of Vega; it automates some constructions and has +much shorter specifications than Vega. Vega-Lite is automatically converted into Vega before rendering, but it has some limitations, and there are some visualizations that can be expressed in Vega that cannot be expressed in Vega-Lite. You can learn more in the https://vega.github.io/vega-lite/[Vega-Lite documentation]. You can use https://vega.github.io/editor/[this editor] to convert Vega-Lite into -Vega. +Vega. -When you create a Vega visualization in {kib}, you can edit the `schema` -value in the dev tools to the left of the graph to define which of the two expression -languages you would like to use (see examples above). +When you create a Vega visualization in {kib}, you can edit the `schema` +value in the dev tools to the left of the graph to define which of the two expression +languages you would like to use. [[vega-querying-elasticsearch]] @@ -176,7 +176,7 @@ except that the timerange is shifted back by 10 minutes: ---- The `"%timefilter%"` can also be used to specify a single min or max -value. As shown above, the date_histogram's `extended_bounds` can be set +value. The date_histogram's `extended_bounds` can be set with two values - min and max. Instead of hardcoding a value, you may use `"min": {"%timefilter%": "min"}`, which will be replaced with the beginning of the current time range. The `shift` and `unit` values are @@ -234,7 +234,7 @@ the graph must specify `type=map` in the host configuration: // defaults to true, shows +/- buttons to zoom in/out "zoomControl": false, - // Defaults to 'false', disables mouse wheel zoom. If set to + // Defaults to 'false', disables mouse wheel zoom. If set to // 'true', map may zoom unexpectedly while scrolling dashboard "scrollWheelZoom": false, @@ -295,7 +295,7 @@ to your kibana.yml file. === Useful Links ==== Vega Editor -The https://vega.github.io/editor/[Vega Editor] includes examples for Vega & Vega-Lite, but does not support any +The https://vega.github.io/editor/[Vega Editor] includes examples for Vega & Vega-Lite, but does not support any {kib}-specific features like {es} requests and interactive base maps. ==== Vega-Lite resources @@ -303,14 +303,14 @@ The https://vega.github.io/editor/[Vega Editor] includes examples for Vega & Veg * https://vega.github.io/vega-lite/docs/[Docs] * https://vega.github.io/vega-lite/examples/[Examples] -==== Vega resources +==== Vega resources * https://vega.github.io/vega/tutorials/[Tutorials] * https://vega.github.io/vega/docs/[Docs] * https://vega.github.io/vega/examples/[Examples] ==== Elastic blog posts * https://www.elastic.co/blog/getting-started-with-vega-visualizations-in-kibana[Getting Started with Vega Visualizations in Kibana] -* https://www.elastic.co/blog/custom-vega-visualizations-in-kibana[Custom Vega Visualizations in Kibana] +* https://www.elastic.co/blog/custom-vega-visualizations-in-kibana[Custom Vega Visualizations in Kibana] * https://www.elastic.co/blog/sankey-visualization-with-vega-in-kibana[Sankey Visualization with Vega in Kibana] diff --git a/src/core/public/http/types.ts b/src/core/public/http/types.ts index 6370ae165282b0..c40ad74893ead7 100644 --- a/src/core/public/http/types.ts +++ b/src/core/public/http/types.ts @@ -205,7 +205,12 @@ export interface HttpRequestInit { /** @public */ export interface HttpFetchQuery { - [key: string]: string | number | boolean | undefined; + [key: string]: + | string + | number + | boolean + | undefined + | Array; } /** diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index cd956eb17531a9..f71a50e2927d88 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -610,7 +610,7 @@ export interface HttpFetchOptionsWithPath extends HttpFetchOptions { // @public (undocumented) export interface HttpFetchQuery { // (undocumented) - [key: string]: string | number | boolean | undefined; + [key: string]: string | number | boolean | undefined | Array; } // @public diff --git a/x-pack/legacy/plugins/maps/common/constants.ts b/x-pack/legacy/plugins/maps/common/constants.ts index 53289fbbc9005a..a4afae0b9e077d 100644 --- a/x-pack/legacy/plugins/maps/common/constants.ts +++ b/x-pack/legacy/plugins/maps/common/constants.ts @@ -165,6 +165,7 @@ export const COLOR_MAP_TYPE = { export const COLOR_PALETTE_MAX_SIZE = 10; export const CATEGORICAL_DATA_TYPES = ['string', 'ip', 'boolean']; +export const ORDINAL_DATA_TYPES = ['number', 'date']; export const SYMBOLIZE_AS_TYPES = { CIRCLE: 'circle', diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts index f03f828200bbd9..ce0743ba2baedf 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts @@ -35,11 +35,11 @@ export type AggDescriptor = { type: AGG_TYPE; }; -export type AbstractESAggDescriptor = AbstractESSourceDescriptor & { +export type AbstractESAggSourceDescriptor = AbstractESSourceDescriptor & { metrics: AggDescriptor[]; }; -export type ESGeoGridSourceDescriptor = AbstractESAggDescriptor & { +export type ESGeoGridSourceDescriptor = AbstractESAggSourceDescriptor & { requestType?: RENDER_AS; resolution?: GRID_RESOLUTION; }; @@ -54,12 +54,12 @@ export type ESSearchSourceDescriptor = AbstractESSourceDescriptor & { topHitsSize?: number; }; -export type ESPewPewSourceDescriptor = AbstractESAggDescriptor & { +export type ESPewPewSourceDescriptor = AbstractESAggSourceDescriptor & { sourceGeoField: string; destGeoField: string; }; -export type ESTermSourceDescriptor = AbstractESAggDescriptor & { +export type ESTermSourceDescriptor = AbstractESAggSourceDescriptor & { indexPatternTitle: string; term: string; // term field name }; diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js b/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js index 0b90dbe47c6e9f..ea7641ed5e8dd6 100644 --- a/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js +++ b/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js @@ -57,11 +57,6 @@ export class ESDocField extends AbstractField { async getCategoricalFieldMetaRequest() { const field = await this._getField(); - if (field.type !== 'string') { - //UX does not support categorical styling for number/date fields - return null; - } - const topTerms = { size: COLOR_PALETTE_MAX_SIZE - 1, //need additional color for the "other"-value }; diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js index b76f1ebce15d21..71e5d7b95e44fd 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/layer.js @@ -332,18 +332,6 @@ export class AbstractLayer { return []; } - async getDateFields() { - return []; - } - - async getNumberFields() { - return []; - } - - async getCategoricalFields() { - return []; - } - async getFields() { return []; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.d.ts index a91bb4a8bb1a7b..99ee1ec652b542 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.d.ts @@ -7,13 +7,19 @@ import { IESSource } from './es_source'; import { AbstractESSource } from './es_source'; import { AGG_TYPE } from '../../../common/constants'; +import { IESAggField } from '../fields/es_agg_field'; +import { AbstractESAggSourceDescriptor } from '../../../common/descriptor_types'; export interface IESAggSource extends IESSource { getAggKey(aggType: AGG_TYPE, fieldName: string): string; getAggLabel(aggType: AGG_TYPE, fieldName: string): string; + getMetricFields(): IESAggField[]; } export class AbstractESAggSource extends AbstractESSource implements IESAggSource { + constructor(sourceDescriptor: AbstractESAggSourceDescriptor, inspectorAdapters: object); + getAggKey(aggType: AGG_TYPE, fieldName: string): string; getAggLabel(aggType: AGG_TYPE, fieldName: string): string; + getMetricFields(): IESAggField[]; } 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 index 62f3369ceb3a36..9f4b89cadc7773 100644 --- 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 @@ -78,6 +78,10 @@ export class AbstractESAggSource extends AbstractESSource { } } + async getFields() { + return this.getMetricFields(); + } + getValueAggsDsl(indexPattern) { const valueAggsDsl = {}; this.getMetricFields().forEach(esAggMetric => { @@ -89,10 +93,6 @@ export class AbstractESAggSource extends AbstractESSource { return valueAggsDsl; } - async getNumberFields() { - return this.getMetricFields(); - } - async filterAndFormatPropertiesToHtmlForMetricFields(properties) { const metricFields = this.getMetricFields(); const tooltipPropertiesPromises = []; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.test.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.test.ts new file mode 100644 index 00000000000000..848091586eb9cb --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.test.ts @@ -0,0 +1,82 @@ +/* + * 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 { AbstractESAggSource } from './es_agg_source'; +import { IField } from '../fields/field'; +import { IESAggField } from '../fields/es_agg_field'; +import _ from 'lodash'; +import { AGG_TYPE } from '../../../common/constants'; +import { AggDescriptor } from '../../../common/descriptor_types'; + +jest.mock('ui/new_platform'); + +const sumFieldName = 'myFieldGettingSummed'; +const metricExamples = [ + { + type: AGG_TYPE.SUM, + field: sumFieldName, + label: 'my custom label', + }, + { + // metric config is invalid beause field is missing + type: AGG_TYPE.MAX, + }, + { + // metric config is valid because "count" metric does not need to provide field + type: AGG_TYPE.COUNT, + label: '', // should ignore empty label fields + }, +]; + +class TestESAggSource extends AbstractESAggSource { + constructor(metrics: AggDescriptor[]) { + super({ type: 'test', id: 'foobar', indexPatternId: 'foobarid', metrics }, []); + } +} + +describe('getMetricFields', () => { + it('should add default "count" metric when no metrics are provided', async () => { + const source = new TestESAggSource([]); + const metrics = source.getMetricFields(); + expect(metrics.length).toBe(1); + + expect(metrics[0].getName()).toEqual('doc_count'); + expect(await metrics[0].getLabel()).toEqual('count'); + }); + + it('should remove incomplete metric configurations', async () => { + const source = new TestESAggSource(metricExamples); + const metrics = source.getMetricFields(); + expect(metrics.length).toBe(2); + + expect(metrics[0].getRootName()).toEqual(sumFieldName); + expect(metrics[0].getName()).toEqual('sum_of_myFieldGettingSummed'); + expect(await metrics[0].getLabel()).toEqual('my custom label'); + + expect(metrics[1].getName()).toEqual('doc_count'); + expect(await metrics[1].getLabel()).toEqual('count'); + }); + + it('getMetrics should be identical to getFields', async () => { + const source = new TestESAggSource(metricExamples); + const metrics = source.getMetricFields(); + const fields = await source.getFields(); + + const getFieldMeta = async (field: IField) => { + const esAggField = field as IESAggField; // this ensures we can downcast correctly. + return { + name: esAggField.getName(), + label: await esAggField.getLabel(), + esDoc: esAggField.getRootName(), + }; + }; + + const metricsFieldMeta = await Promise.all(metrics.map(getFieldMeta)); + const fieldsFieldMeta = await Promise.all(fields.map(getFieldMeta)); + + expect(_.isEqual(metricsFieldMeta, fieldsFieldMeta)).toEqual(true); + }); +}); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts index 652409b61fd722..48e90b6c41d51a 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -6,7 +6,10 @@ import { AbstractESAggSource } from '../es_agg_source'; import { ESGeoGridSourceDescriptor } from '../../../../common/descriptor_types'; +import { GRID_RESOLUTION } from '../../../../common/constants'; export class ESGeoGridSource extends AbstractESAggSource { constructor(sourceDescriptor: ESGeoGridSourceDescriptor, inspectorAdapters: unknown); + getGridResolution(): GRID_RESOLUTION; + getGeoGridPrecision(zoom: number): number; } 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 4987d052b8ab70..3b3e8004ded053 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 @@ -35,7 +35,7 @@ import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_sty import { StaticStyleProperty } from '../../styles/vector/properties/static_style_property'; import { DataRequestAbortError } from '../../util/data_request'; -const MAX_GEOTILE_LEVEL = 29; +export const MAX_GEOTILE_LEVEL = 29; export class ESGeoGridSource extends AbstractESAggSource { static type = ES_GEO_GRID; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.test.ts new file mode 100644 index 00000000000000..727435c3cbfef1 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.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. + */ +jest.mock('../../../kibana_services', () => {}); +jest.mock('ui/new_platform'); + +import { ESGeoGridSource } from './es_geo_grid_source'; +import { ES_GEO_GRID, GRID_RESOLUTION, RENDER_AS } from '../../../../common/constants'; + +describe('ESGeoGridSource', () => { + const geogridSource = new ESGeoGridSource( + { + id: 'foobar', + indexPatternId: 'fooIp', + geoField: 'bar', + metrics: [], + resolution: GRID_RESOLUTION.COARSE, + type: ES_GEO_GRID, + requestType: RENDER_AS.HEATMAP, + }, + {} + ); + + describe('getGridResolution', () => { + it('should echo gridResoltuion', () => { + expect(geogridSource.getGridResolution()).toBe(GRID_RESOLUTION.COARSE); + }); + }); + + describe('getGeoGridPrecision', () => { + it('should clamp geo-grid derived zoom to max geotile level supported by ES', () => { + expect(geogridSource.getGeoGridPrecision(29)).toBe(29); + }); + + it('should use heuristic to derive precision', () => { + expect(geogridSource.getGeoGridPrecision(10)).toBe(12); + }); + }); +}); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js index 35332824361393..7f0e8707605120 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js @@ -19,7 +19,6 @@ import { ES_GEO_FIELD_TYPE, DEFAULT_MAX_BUCKETS_LIMIT, SORT_ORDER, - CATEGORICAL_DATA_TYPES, } from '../../../../common/constants'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; @@ -135,49 +134,6 @@ export class ESSearchSource extends AbstractESSource { ); } - async getNumberFields() { - try { - const indexPattern = await this.getIndexPattern(); - return indexPattern.fields.getByType('number').map(field => { - return this.createField({ fieldName: field.name }); - }); - } catch (error) { - return []; - } - } - - async getDateFields() { - try { - const indexPattern = await this.getIndexPattern(); - return indexPattern.fields.getByType('date').map(field => { - return this.createField({ fieldName: field.name }); - }); - } catch (error) { - return []; - } - } - - async getCategoricalFields() { - try { - const indexPattern = await this.getIndexPattern(); - - const aggFields = []; - CATEGORICAL_DATA_TYPES.forEach(dataType => { - indexPattern.fields.getByType(dataType).forEach(field => { - if (field.aggregatable) { - aggFields.push(field); - } - }); - }); - return aggFields.map(field => { - return this.createField({ fieldName: field.name }); - }); - } catch (error) { - //error surfaces in the LayerTOC UI - return []; - } - } - async getFields() { try { const indexPattern = await this.getIndexPattern(); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js index d6f9f6d2911e91..890b1e3aaac1f0 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js @@ -31,36 +31,27 @@ const metricExamples = [ ]; describe('getMetricFields', () => { - it('should add default "count" metric when no metrics are provided', async () => { + it('should override name and label of count metric', async () => { const source = new ESTermSource({ indexPatternTitle: indexPatternTitle, term: termFieldName, }); const metrics = source.getMetricFields(); - expect(metrics.length).toBe(1); - - expect(metrics[0].getAggType()).toEqual('count'); expect(metrics[0].getName()).toEqual('__kbnjoin__count_groupby_myIndex.myTermField'); expect(await metrics[0].getLabel()).toEqual('Count of myIndex'); }); - it('should remove incomplete metric configurations', async () => { + it('should override name and label of sum metric', async () => { const source = new ESTermSource({ indexPatternTitle: indexPatternTitle, term: termFieldName, metrics: metricExamples, }); const metrics = source.getMetricFields(); - expect(metrics.length).toBe(2); - - expect(metrics[0].getAggType()).toEqual('sum'); - expect(metrics[0].getRootName()).toEqual(sumFieldName); expect(metrics[0].getName()).toEqual( '__kbnjoin__sum_of_myFieldGettingSummed_groupby_myIndex.myTermField' ); expect(await metrics[0].getLabel()).toEqual('my custom label'); - - expect(metrics[1].getAggType()).toEqual('count'); expect(metrics[1].getName()).toEqual('__kbnjoin__count_groupby_myIndex.myTermField'); expect(await metrics[1].getLabel()).toEqual('Count of myIndex'); }); 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 8369ca562e14b3..0f74dd605c8f1b 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 @@ -111,19 +111,7 @@ export class AbstractVectorSource extends AbstractSource { return null; } - async getDateFields() { - return []; - } - - async getNumberFields() { - return []; - } - async getFields() { - return [...(await this.getDateFields()), ...(await this.getNumberFields())]; - } - - async getCategoricalFields() { return []; } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js index 436a92b6199090..0d4cf322d2a406 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js @@ -6,10 +6,11 @@ import React, { Component, Fragment } from 'react'; -import { EuiSuperSelect, EuiSpacer } from '@elastic/eui'; +import { EuiSpacer, EuiSelect, EuiSuperSelect, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { ColorStopsOrdinal } from './color_stops_ordinal'; import { COLOR_MAP_TYPE } from '../../../../../../common/constants'; import { ColorStopsCategorical } from './color_stops_categorical'; +import { i18n } from '@kbn/i18n'; const CUSTOM_COLOR_MAP = 'CUSTOM_COLOR_MAP'; @@ -27,6 +28,43 @@ export class ColorMapSelect extends Component { }; } + _renderColorMapToggle() { + const options = [ + { + value: COLOR_MAP_TYPE.ORDINAL, + text: i18n.translate('xpack.maps.styles.dynamicColorSelect.quantitativeLabel', { + defaultMessage: 'As number', + }), + }, + { + value: COLOR_MAP_TYPE.CATEGORICAL, + text: i18n.translate('xpack.maps.styles.dynamicColorSelect.qualitativeLabel', { + defaultMessage: 'As category', + }), + }, + ]; + + const selectedValue = this.props.styleProperty.isOrdinal() + ? COLOR_MAP_TYPE.ORDINAL + : COLOR_MAP_TYPE.CATEGORICAL; + + return ( + + ); + } + _onColorMapSelect = selectedValue => { const useCustomColorMap = selectedValue === CUSTOM_COLOR_MAP; this.props.onChange({ @@ -55,32 +93,32 @@ export class ColorMapSelect extends Component { return null; } + let colorStopEditor; if (this.props.colorMapType === COLOR_MAP_TYPE.ORDINAL) { - return ( - - - - + colorStopEditor = ( + ); - } - - return ( - - + } else + colorStopEditor = ( - + ); + + return ( + + {colorStopEditor} + ); } - render() { + _renderColorMapSelections() { const colorMapOptionsWithCustom = [ { value: CUSTOM_COLOR_MAP, @@ -98,15 +136,31 @@ export class ColorMapSelect extends Component { : ''; } + const toggle = this.props.showColorMapTypeToggle ? ( + {this._renderColorMapToggle()} + ) : null; + + return ( + + {toggle} + + + + + ); + } + + render() { return ( - + {this._renderColorMapSelections()} + {this._renderColorStopsInput()} ); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js index 3dc356c31cf30b..c6b68b7e944099 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js @@ -40,21 +40,44 @@ export function DynamicColorForm({ }; const onFieldChange = async ({ field }) => { - const { name, origin, type } = field; + const { name, origin, type: fieldType } = field; + const defaultColorMapType = CATEGORICAL_DATA_TYPES.includes(fieldType) + ? COLOR_MAP_TYPE.CATEGORICAL + : COLOR_MAP_TYPE.ORDINAL; onDynamicStyleChange(styleProperty.getStyleName(), { ...styleOptions, field: { name, origin }, - type: CATEGORICAL_DATA_TYPES.includes(type) - ? COLOR_MAP_TYPE.CATEGORICAL - : COLOR_MAP_TYPE.ORDINAL, + type: defaultColorMapType, + }); + }; + + const onColorMapTypeChange = async e => { + const colorMapType = e.target.value; + onDynamicStyleChange(styleProperty.getStyleName(), { + ...styleOptions, + type: colorMapType, + }); + }; + + const getField = () => { + const fieldName = styleProperty.getFieldName(); + if (!fieldName) { + return null; + } + + return fields.find(field => { + return field.name === fieldName; }); }; const renderColorMapSelect = () => { - if (!styleOptions.field || !styleOptions.field.name) { + const field = getField(); + if (!field) { return null; } + const showColorMapTypeToggle = !CATEGORICAL_DATA_TYPES.includes(field.type); + if (styleProperty.isOrdinal()) { return ( + ); + } else if (styleProperty.isCategorical()) { + return ( + ); } - - return ( - - ); }; return ( diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js index 7daf85b68dd8e1..7ad36bd2ae33d1 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js @@ -26,13 +26,14 @@ import { VECTOR_SHAPE_TYPES } from '../../../sources/vector_feature_types'; import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiButtonGroup, EuiFormRow, EuiSwitch } from '@elastic/eui'; +import { CATEGORICAL_DATA_TYPES, ORDINAL_DATA_TYPES } from '../../../../../common/constants'; export class VectorStyleEditor extends Component { state = { dateFields: [], numberFields: [], - categoricalFields: [], fields: [], + ordinalAndCategoricalFields: [], defaultDynamicProperties: getDefaultDynamicProperties(), defaultStaticProperties: getDefaultStaticProperties(), supportedFeatures: undefined, @@ -64,33 +65,24 @@ export class VectorStyleEditor extends Component { }; }; - const dateFields = await this.props.layer.getDateFields(); - const dateFieldPromises = dateFields.map(getFieldMeta); - const dateFieldsArray = await Promise.all(dateFieldPromises); - if (this._isMounted && !_.isEqual(dateFieldsArray, this.state.dateFields)) { - this.setState({ dateFields: dateFieldsArray }); - } - - const numberFields = await this.props.layer.getNumberFields(); - const numberFieldPromises = numberFields.map(getFieldMeta); - const numberFieldsArray = await Promise.all(numberFieldPromises); - if (this._isMounted && !_.isEqual(numberFieldsArray, this.state.numberFields)) { - this.setState({ numberFields: numberFieldsArray }); - } - - const categoricalFields = await this.props.layer.getCategoricalFields(); - const categoricalFieldMeta = categoricalFields.map(getFieldMeta); - const categoricalFieldsArray = await Promise.all(categoricalFieldMeta); - if (this._isMounted && !_.isEqual(categoricalFieldsArray, this.state.categoricalFields)) { - this.setState({ categoricalFields: categoricalFieldsArray }); - } - + //These are all fields (only used for text labeling) const fields = await this.props.layer.getFields(); const fieldPromises = fields.map(getFieldMeta); - const fieldsArray = await Promise.all(fieldPromises); - if (this._isMounted && !_.isEqual(fieldsArray, this.state.fields)) { - this.setState({ fields: fieldsArray }); + const fieldsArrayAll = await Promise.all(fieldPromises); + if (!this._isMounted || _.isEqual(fieldsArrayAll, this.state.fields)) { + return; } + + this.setState({ + fields: fieldsArrayAll, + ordinalAndCategoricalFields: fieldsArrayAll.filter(field => { + return ( + CATEGORICAL_DATA_TYPES.includes(field.type) || ORDINAL_DATA_TYPES.includes(field.type) + ); + }), + dateFields: fieldsArrayAll.filter(field => field.type === 'date'), + numberFields: fieldsArrayAll.filter(field => field.type === 'number'), + }); } async _loadSupportedFeatures() { @@ -118,10 +110,6 @@ export class VectorStyleEditor extends Component { return [...this.state.dateFields, ...this.state.numberFields]; } - _getOrdinalAndCategoricalFields() { - return [...this.state.dateFields, ...this.state.numberFields, ...this.state.categoricalFields]; - } - _handleSelectedFeatureChange = selectedFeature => { this.setState({ selectedFeature }); }; @@ -172,7 +160,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.FILL_COLOR]} - fields={this._getOrdinalAndCategoricalFields()} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.FILL_COLOR].options } @@ -193,7 +181,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.LINE_COLOR]} - fields={this._getOrdinalAndCategoricalFields()} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.LINE_COLOR].options } @@ -249,7 +237,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_COLOR]} - fields={this._getOrdinalAndCategoricalFields()} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.LABEL_COLOR].options } @@ -282,7 +270,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_BORDER_COLOR]} - fields={this._getOrdinalAndCategoricalFields()} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.LABEL_BORDER_COLOR].options } @@ -335,7 +323,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.ICON]} - fields={this.state.categoricalFields} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.ICON].options } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js index c2f7a1313d02ae..5b286e4ba120ec 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js @@ -236,3 +236,33 @@ test('Should pluck the categorical style-meta from fieldmeta', async () => { ], }); }); + +test('isCategorical should return true when type is categorical', async () => { + const categoricalColorStyle = makeProperty({ + type: COLOR_MAP_TYPE.CATEGORICAL, + colorCategory: 'palette_0', + }); + + expect(categoricalColorStyle.isOrdinal()).toEqual(false); + expect(categoricalColorStyle.isCategorical()).toEqual(true); +}); + +test('isOrdinal should return true when type is ordinal', async () => { + const ordinalColorStyle = makeProperty({ + type: undefined, + color: 'Blues', + }); + + expect(ordinalColorStyle.isOrdinal()).toEqual(true); + expect(ordinalColorStyle.isCategorical()).toEqual(false); +}); + +test('Should read out ordinal type correctly', async () => { + const ordinalColorStyle2 = makeProperty({ + type: COLOR_MAP_TYPE.ORDINAL, + colorCategory: 'palette_0', + }); + + expect(ordinalColorStyle2.isOrdinal()).toEqual(true); + expect(ordinalColorStyle2.isCategorical()).toEqual(false); +}); 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 32fdbcf9654147..70bba3d91c7237 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -197,19 +197,6 @@ export class VectorLayer extends AbstractLayer { return joinFields; } - async getDateFields() { - return await this._source.getDateFields(); - } - - async getNumberFields() { - const numberFieldOptions = await this._source.getNumberFields(); - return [...numberFieldOptions, ...this._getJoinFields()]; - } - - async getCategoricalFields() { - return await this._source.getCategoricalFields(); - } - async getFields() { const sourceFields = await this._source.getFields(); return [...sourceFields, ...this._getJoinFields()]; diff --git a/x-pack/plugins/endpoint/common/schema/README.md b/x-pack/plugins/endpoint/common/schema/README.md new file mode 100644 index 00000000000000..42abedd647e6b0 --- /dev/null +++ b/x-pack/plugins/endpoint/common/schema/README.md @@ -0,0 +1,6 @@ +# Schemas + +These schemas are used to validate, coerce, and provide types for the comms between the client, server, and ES. + +# Future work +In the future, we may be able to locate these under 'server'. diff --git a/x-pack/plugins/endpoint/server/routes/alerts/list/schemas.ts b/x-pack/plugins/endpoint/common/schema/alert_index.ts similarity index 81% rename from x-pack/plugins/endpoint/server/routes/alerts/list/schemas.ts rename to x-pack/plugins/endpoint/common/schema/alert_index.ts index ce2163ac96dd1c..e8e2e1af102d63 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/list/schemas.ts +++ b/x-pack/plugins/endpoint/common/schema/alert_index.ts @@ -3,13 +3,17 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { decode } from 'rison-node'; + +import { schema, Type } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; -import { schema } from '@kbn/config-schema'; -import { esKuery } from '../../../../../../../src/plugins/data/server'; -import { EndpointAppConstants } from '../../../../common/types'; +import { decode } from 'rison-node'; +import { fromKueryExpression } from '../../../../../src/plugins/data/common'; +import { EndpointAppConstants } from '../types'; -export const alertListReqSchema = schema.object( +/** + * Used to validate GET requests against the index of the alerting APIs. + */ +export const alertingIndexGetQuerySchema = schema.object( { page_size: schema.maybe( schema.number({ @@ -26,31 +30,21 @@ export const alertListReqSchema = schema.object( schema.arrayOf(schema.string(), { minSize: 2, maxSize: 2, - }) + }) as Type<[string, string]> // Cast this to a string tuple. `@kbn/config-schema` doesn't do this automatically ), before: schema.maybe( schema.arrayOf(schema.string(), { minSize: 2, maxSize: 2, - }) + }) as Type<[string, string]> // Cast this to a string tuple. `@kbn/config-schema` doesn't do this automatically ), sort: schema.maybe(schema.string()), - order: schema.maybe( - schema.string({ - validate(value) { - if (value !== 'asc' && value !== 'desc') { - return i18n.translate('xpack.endpoint.alerts.errors.bad_sort_direction', { - defaultMessage: 'must be `asc` or `desc`', - }); - } - }, - }) - ), + order: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), query: schema.maybe( schema.string({ validate(value) { try { - esKuery.fromKueryExpression(value); + fromKueryExpression(value); } catch (err) { return i18n.translate('xpack.endpoint.alerts.errors.bad_kql', { defaultMessage: 'must be valid KQL', diff --git a/x-pack/plugins/endpoint/common/types.ts b/x-pack/plugins/endpoint/common/types.ts index b1e5ab015aa5fd..edcd2d7841b120 100644 --- a/x-pack/plugins/endpoint/common/types.ts +++ b/x-pack/plugins/endpoint/common/types.ts @@ -5,6 +5,9 @@ */ import { SearchResponse } from 'elasticsearch'; +import { TypeOf } from '@kbn/config-schema'; +import * as kbnConfigSchemaTypes from '@kbn/config-schema/target/types/types'; +import { alertingIndexGetQuerySchema } from './schema/alert_index'; /** * A deep readonly type that will make all children of a given object readonly recursively @@ -24,10 +27,7 @@ export type ImmutableMap = ReadonlyMap, Immutable>; export type ImmutableSet = ReadonlySet>; export type ImmutableObject = { readonly [K in keyof T]: Immutable }; -export enum Direction { - asc = 'asc', - desc = 'desc', -} +export type Direction = 'asc' | 'desc'; export class EndpointAppConstants { static BASE_API_URL = '/api/endpoint'; @@ -45,7 +45,6 @@ export class EndpointAppConstants { **/ static ALERT_LIST_DEFAULT_PAGE_SIZE = 10; static ALERT_LIST_DEFAULT_SORT = '@timestamp'; - static ALERT_LIST_DEFAULT_ORDER = Direction.desc; } export interface AlertResultList { @@ -336,3 +335,72 @@ export type ResolverEvent = EndpointEvent | LegacyEndpointEvent; * The PageId type is used for the payload when firing userNavigatedToPage actions */ export type PageId = 'alertsPage' | 'managementPage' | 'policyListPage'; + +/** + * Takes a @kbn/config-schema 'schema' type and returns a type that represents valid inputs. + * Similar to `TypeOf`, but allows strings as input for `schema.number()` (which is inline + * with the behavior of the validator.) Also, for `schema.object`, when a value is a `schema.maybe` + * the key will be marked optional (via `?`) so that you can omit keys for optional values. + * + * Use this when creating a value that will be passed to the schema. + * e.g. + * ```ts + * const input: KbnConfigSchemaInputTypeOf = value + * schema.validate(input) // should be valid + * ``` + */ +type KbnConfigSchemaInputTypeOf< + T extends kbnConfigSchemaTypes.Type +> = T extends kbnConfigSchemaTypes.ObjectType + ? KbnConfigSchemaInputObjectTypeOf< + T + > /** `schema.number()` accepts strings, so this type should accept them as well. */ + : kbnConfigSchemaTypes.Type extends T + ? TypeOf | string + : TypeOf; + +/** + * Works like ObjectResultType, except that 'maybe' schema will create an optional key. + * This allows us to avoid passing 'maybeKey: undefined' when constructing such an object. + * + * Instead of using this directly, use `InputTypeOf`. + */ +type KbnConfigSchemaInputObjectTypeOf< + T extends kbnConfigSchemaTypes.ObjectType +> = T extends kbnConfigSchemaTypes.ObjectType + ? { + /** Use ? to make the field optional if the prop accepts undefined. + * This allows us to avoid writing `field: undefined` for optional fields. + */ + [K in Exclude< + keyof P, + keyof KbnConfigSchemaNonOptionalProps

+ >]?: KbnConfigSchemaInputTypeOf; + } & + { [K in keyof KbnConfigSchemaNonOptionalProps

]: KbnConfigSchemaInputTypeOf } + : never; + +/** + * Takes the props of a schema.object type, and returns a version that excludes + * optional values. Used by `InputObjectTypeOf`. + * + * Instead of using this directly, use `InputTypeOf`. + */ +type KbnConfigSchemaNonOptionalProps = Pick< + Props, + { + [Key in keyof Props]: undefined extends TypeOf ? never : Key; + }[keyof Props] +>; + +/** + * Query params to pass to the alert API when fetching new data. + */ +export type AlertingIndexGetQueryInput = KbnConfigSchemaInputTypeOf< + typeof alertingIndexGetQuerySchema +>; + +/** + * Result of the validated query params when handling alert index requests. + */ +export type AlertingIndexGetQueryResult = TypeOf; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts index 2cb381e901b4ed..339be7a4ec7f10 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts @@ -8,6 +8,7 @@ import { AlertResultList, AlertData } from '../../../../../common/types'; import { AppAction } from '../action'; import { MiddlewareFactory, AlertListState } from '../../types'; import { isOnAlertPage, apiQueryParams, hasSelectedAlert, uiQueryParams } from './selectors'; +import { cloneHttpFetchQuery } from '../../../../common/clone_http_fetch_query'; export const alertMiddlewareFactory: MiddlewareFactory = coreStart => { return api => next => async (action: AppAction) => { @@ -15,7 +16,7 @@ export const alertMiddlewareFactory: MiddlewareFactory = coreSta const state = api.getState(); if (action.type === 'userChangedUrl' && isOnAlertPage(state)) { const response: AlertResultList = await coreStart.http.get(`/api/endpoint/alerts`, { - query: apiQueryParams(state), + query: cloneHttpFetchQuery(apiQueryParams(state)), }); api.dispatch({ type: 'serverReturnedAlertsData', payload: response }); } diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts index 7ce7c2d08691ee..ca836f8b62bd20 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts @@ -9,15 +9,11 @@ import { createSelector, createStructuredSelector as createStructuredSelectorWithBadType, } from 'reselect'; -import { - AlertListState, - AlertingIndexUIQueryParams, - AlertsAPIQueryParams, - CreateStructuredSelector, -} from '../../types'; -import { Immutable } from '../../../../../common/types'; +import { AlertListState, AlertingIndexUIQueryParams, CreateStructuredSelector } from '../../types'; +import { Immutable, AlertingIndexGetQueryInput } from '../../../../../common/types'; const createStructuredSelector: CreateStructuredSelector = createStructuredSelectorWithBadType; + /** * Returns the Alert Data array from state */ @@ -82,7 +78,7 @@ export const uiQueryParams: ( */ export const apiQueryParams: ( state: AlertListState -) => Immutable = createSelector( +) => Immutable = createSelector( uiQueryParams, ({ page_size, page_index }) => ({ page_size, @@ -90,6 +86,10 @@ export const apiQueryParams: ( }) ); +/** + * True if the user has selected an alert to see details about. + * Populated via the browsers query params. + */ export const hasSelectedAlert: (state: AlertListState) => boolean = createSelector( uiQueryParams, ({ selected_alert: selectedAlert }) => selectedAlert !== undefined diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts index 6adb3d6adc2603..4ceb4cec23d0b8 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts @@ -5,7 +5,6 @@ */ import { Dispatch, MiddlewareAPI } from 'redux'; -import { CoreStart } from 'kibana/public'; import { EndpointMetadata, AlertData, @@ -14,6 +13,7 @@ import { ImmutableArray, } from '../../../common/types'; import { AppAction } from './store/action'; +import { CoreStart } from '../../../../../../src/core/public'; export { AppAction }; export type MiddlewareFactory = ( @@ -140,17 +140,3 @@ export interface AlertingIndexUIQueryParams { */ selected_alert?: string; } - -/** - * Query params to pass to the alert API when fetching new data. - */ -export interface AlertsAPIQueryParams { - /** - * Number of results to return. - */ - page_size?: string; - /** - * 0-based index of 'page' to return. - */ - page_index?: string; -} diff --git a/x-pack/plugins/endpoint/public/common/clone_http_fetch_query.test.ts b/x-pack/plugins/endpoint/public/common/clone_http_fetch_query.test.ts new file mode 100644 index 00000000000000..9ac6b8b29f462b --- /dev/null +++ b/x-pack/plugins/endpoint/public/common/clone_http_fetch_query.test.ts @@ -0,0 +1,32 @@ +/* + * 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 { cloneHttpFetchQuery } from './clone_http_fetch_query'; +import { Immutable } from '../../common/types'; +import { HttpFetchQuery } from '../../../../../src/core/public'; + +describe('cloneHttpFetchQuery', () => { + it('can clone complex queries', () => { + const query: Immutable = { + a: 'a', + '1': 1, + undefined, + array: [1, 2, undefined], + }; + expect(cloneHttpFetchQuery(query)).toMatchInlineSnapshot(` + Object { + "1": 1, + "a": "a", + "array": Array [ + 1, + 2, + undefined, + ], + "undefined": undefined, + } + `); + }); +}); diff --git a/x-pack/plugins/endpoint/public/common/clone_http_fetch_query.ts b/x-pack/plugins/endpoint/public/common/clone_http_fetch_query.ts new file mode 100644 index 00000000000000..fdf1d6603830a8 --- /dev/null +++ b/x-pack/plugins/endpoint/public/common/clone_http_fetch_query.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 { Immutable } from '../../common/types'; + +import { HttpFetchQuery } from '../../../../../src/core/public'; + +export function cloneHttpFetchQuery(query: Immutable): HttpFetchQuery { + const clone: HttpFetchQuery = {}; + for (const [key, value] of Object.entries(query)) { + if (Array.isArray(value)) { + clone[key] = [...value]; + } else { + // Array.isArray is not removing ImmutableArray from the union. + clone[key] = value as string | number | boolean; + } + } + return clone; +} diff --git a/x-pack/plugins/endpoint/server/routes/alerts/alerts.test.ts b/x-pack/plugins/endpoint/server/routes/alerts/alerts.test.ts index adf686381f9677..5f5e4be4ecd0a1 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/alerts.test.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/alerts.test.ts @@ -9,9 +9,9 @@ import { httpServiceMock, loggingServiceMock, } from '../../../../../../src/core/server/mocks'; -import { alertListReqSchema } from './list/schemas'; import { registerAlertRoutes } from './index'; import { EndpointConfigSchema } from '../../config'; +import { alertingIndexGetQuerySchema } from '../../../common/schema/alert_index'; describe('test alerts route', () => { let routerMock: jest.Mocked; @@ -31,7 +31,7 @@ describe('test alerts route', () => { it('should fail to validate when `page_size` is not a number', async () => { const validate = () => { - alertListReqSchema.validate({ + alertingIndexGetQuerySchema.validate({ page_size: 'abc', }); }; @@ -40,7 +40,7 @@ describe('test alerts route', () => { it('should validate when `page_size` is a number', async () => { const validate = () => { - alertListReqSchema.validate({ + alertingIndexGetQuerySchema.validate({ page_size: 25, }); }; @@ -49,7 +49,7 @@ describe('test alerts route', () => { it('should validate when `page_size` can be converted to a number', async () => { const validate = () => { - alertListReqSchema.validate({ + alertingIndexGetQuerySchema.validate({ page_size: '50', }); }; @@ -58,7 +58,7 @@ describe('test alerts route', () => { it('should allow either `page_index` or `after`, but not both', async () => { const validate = () => { - alertListReqSchema.validate({ + alertingIndexGetQuerySchema.validate({ page_index: 1, after: [123, 345], }); @@ -68,7 +68,7 @@ describe('test alerts route', () => { it('should allow either `page_index` or `before`, but not both', async () => { const validate = () => { - alertListReqSchema.validate({ + alertingIndexGetQuerySchema.validate({ page_index: 1, before: 'abc', }); @@ -78,7 +78,7 @@ describe('test alerts route', () => { it('should allow either `before` or `after`, but not both', async () => { const validate = () => { - alertListReqSchema.validate({ + alertingIndexGetQuerySchema.validate({ before: ['abc', 'def'], after: [123, 345], }); diff --git a/x-pack/plugins/endpoint/server/routes/alerts/details/lib/pagination.ts b/x-pack/plugins/endpoint/server/routes/alerts/details/lib/pagination.ts index 94aff64e75f017..16328587597f24 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/details/lib/pagination.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/details/lib/pagination.ts @@ -5,7 +5,6 @@ */ import { GetResponse, SearchResponse } from 'elasticsearch'; -import { RequestHandlerContext } from 'src/core/server'; import { AlertEvent, AlertHits, @@ -16,6 +15,7 @@ import { EndpointConfigType } from '../../../../config'; import { searchESForAlerts, Pagination } from '../../lib'; import { AlertSearchQuery, SearchCursor, AlertDetailsRequestParams } from '../../types'; import { BASE_ALERTS_ROUTE } from '../..'; +import { RequestHandlerContext } from '../../../../../../../../src/core/server'; /** * Pagination class for alert details. @@ -40,10 +40,10 @@ export class AlertDetailsPagination extends Pagination< const reqData: AlertSearchQuery = { pageSize: 1, sort: EndpointAppConstants.ALERT_LIST_DEFAULT_SORT, - order: EndpointAppConstants.ALERT_LIST_DEFAULT_ORDER, + order: 'desc', }; - if (direction === Direction.asc) { + if (direction === 'asc') { reqData.searchAfter = cursor; } else { reqData.searchBefore = cursor; @@ -67,7 +67,7 @@ export class AlertDetailsPagination extends Pagination< * Gets the next alert after this one. */ async getNextUrl(): Promise { - const response = await this.doSearch(Direction.asc, [ + const response = await this.doSearch('asc', [ this.data._source['@timestamp'].toString(), this.data._source.event.id, ]); @@ -78,7 +78,7 @@ export class AlertDetailsPagination extends Pagination< * Gets the alert before this one. */ async getPrevUrl(): Promise { - const response = await this.doSearch(Direction.desc, [ + const response = await this.doSearch('desc', [ this.data._source['@timestamp'].toString(), this.data._source.event.id, ]); diff --git a/x-pack/plugins/endpoint/server/routes/alerts/index.ts b/x-pack/plugins/endpoint/server/routes/alerts/index.ts index 2a4a127fb41bc2..09de11897813b5 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/index.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/index.ts @@ -6,8 +6,9 @@ import { IRouter } from 'kibana/server'; import { EndpointAppContext } from '../../types'; import { EndpointAppConstants } from '../../../common/types'; -import { alertListHandlerWrapper, alertListReqSchema } from './list'; +import { alertListHandlerWrapper } from './list'; import { alertDetailsHandlerWrapper, alertDetailsReqSchema } from './details'; +import { alertingIndexGetQuerySchema } from '../../../common/schema/alert_index'; export const BASE_ALERTS_ROUTE = `${EndpointAppConstants.BASE_API_URL}/alerts`; @@ -16,7 +17,7 @@ export function registerAlertRoutes(router: IRouter, endpointAppContext: Endpoin { path: BASE_ALERTS_ROUTE, validate: { - query: alertListReqSchema, + query: alertingIndexGetQuerySchema, }, options: { authRequired: true }, }, diff --git a/x-pack/plugins/endpoint/server/routes/alerts/lib/index.ts b/x-pack/plugins/endpoint/server/routes/alerts/lib/index.ts index ff5b33a978b2cb..39067e9c27709a 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/lib/index.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/lib/index.ts @@ -18,10 +18,10 @@ import { export { Pagination } from './pagination'; function reverseSortDirection(order: Direction): Direction { - if (order === Direction.asc) { - return Direction.desc; + if (order === 'asc') { + return 'desc'; } - return Direction.asc; + return 'asc'; } function buildQuery(query: AlertSearchQuery): JsonObject { diff --git a/x-pack/plugins/endpoint/server/routes/alerts/lib/pagination.ts b/x-pack/plugins/endpoint/server/routes/alerts/lib/pagination.ts index e8218fcfb0ed2d..fc408878f8956c 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/lib/pagination.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/lib/pagination.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestHandlerContext } from 'src/core/server'; import { EndpointConfigType } from '../../../config'; +import { RequestHandlerContext } from '../../../../../../../src/core/server'; /** * Abstract Pagination class for determining next/prev urls, diff --git a/x-pack/plugins/endpoint/server/routes/alerts/list/handlers.ts b/x-pack/plugins/endpoint/server/routes/alerts/list/handlers.ts index 4fece65a65bfe0..93ec8d7aa3e679 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/list/handlers.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/list/handlers.ts @@ -3,18 +3,18 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { KibanaRequest, RequestHandler } from 'kibana/server'; +import { RequestHandler } from 'kibana/server'; import { EndpointAppContext } from '../../../types'; import { searchESForAlerts } from '../lib'; import { getRequestData, mapToAlertResultList } from './lib'; -import { AlertListRequestQuery } from '../types'; +import { AlertingIndexGetQueryResult } from '../../../../common/types'; export const alertListHandlerWrapper = function( endpointAppContext: EndpointAppContext -): RequestHandler { - const alertListHandler: RequestHandler = async ( +): RequestHandler { + const alertListHandler: RequestHandler = async ( ctx, - req: KibanaRequest, + req, res ) => { try { diff --git a/x-pack/plugins/endpoint/server/routes/alerts/list/index.ts b/x-pack/plugins/endpoint/server/routes/alerts/list/index.ts index 43a0745365c9b0..cf72ea4d199de1 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/list/index.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/list/index.ts @@ -4,5 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { alertListReqSchema } from './schemas'; export { alertListHandlerWrapper } from './handlers'; diff --git a/x-pack/plugins/endpoint/server/routes/alerts/list/lib/index.ts b/x-pack/plugins/endpoint/server/routes/alerts/list/lib/index.ts index fa083229100913..1c7a157a988ae3 100644 --- a/x-pack/plugins/endpoint/server/routes/alerts/list/lib/index.ts +++ b/x-pack/plugins/endpoint/server/routes/alerts/list/lib/index.ts @@ -15,13 +15,14 @@ import { AlertHits, EndpointAppConstants, ESTotal, + AlertingIndexGetQueryResult, } from '../../../../../common/types'; import { EndpointAppContext } from '../../../../types'; -import { AlertSearchQuery, AlertListRequestQuery } from '../../types'; +import { AlertSearchQuery } from '../../types'; import { AlertListPagination } from './pagination'; export const getRequestData = async ( - request: KibanaRequest, + request: KibanaRequest, endpointAppContext: EndpointAppContext ): Promise => { const config = await endpointAppContext.config(); @@ -29,7 +30,7 @@ export const getRequestData = async ( // Defaults not enforced by schema pageSize: request.query.page_size || EndpointAppConstants.ALERT_LIST_DEFAULT_PAGE_SIZE, sort: request.query.sort || EndpointAppConstants.ALERT_LIST_DEFAULT_SORT, - order: request.query.order || EndpointAppConstants.ALERT_LIST_DEFAULT_ORDER, + order: request.query.order || 'desc', dateRange: ((request.query.date_range !== undefined ? decode(request.query.date_range) : config.alertResultListDefaultDateRange) as unknown) as TimeRange, diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx index 741ad40f7d1cbf..827fea7021eb46 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx @@ -35,7 +35,7 @@ const appDependencies = { core: coreMock.createSetup(), services, config: { - slmUi: { enabled: true }, + slm_ui: { enabled: true }, }, plugins: {}, }; diff --git a/x-pack/plugins/snapshot_restore/public/application/app.tsx b/x-pack/plugins/snapshot_restore/public/application/app.tsx index 5f240a7335ecc7..77ef697814b2c4 100644 --- a/x-pack/plugins/snapshot_restore/public/application/app.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/app.tsx @@ -24,7 +24,7 @@ import { useConfig } from './app_context'; import { AuthorizationContext, WithPrivileges, NotAuthorizedSection } from './lib/authorization'; export const App: React.FunctionComponent = () => { - const { slmUi } = useConfig(); + const { slm_ui: slmUi } = useConfig(); const { apiError } = useContext(AuthorizationContext); const sections: Section[] = ['repositories', 'snapshots', 'restore_status']; diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/home.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/home.tsx index 81e7cb895297e5..1d9f2ca5e9e4f5 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/home.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/home.tsx @@ -41,7 +41,7 @@ export const SnapshotRestoreHome: React.FunctionComponent { - const { slmUi } = useConfig(); + const { slm_ui: slmUi } = useConfig(); const tabs: Array<{ id: Section; diff --git a/x-pack/plugins/snapshot_restore/public/types.ts b/x-pack/plugins/snapshot_restore/public/types.ts index 82fecd8c40ecb2..f7003aa6a8e2ca 100644 --- a/x-pack/plugins/snapshot_restore/public/types.ts +++ b/x-pack/plugins/snapshot_restore/public/types.ts @@ -5,5 +5,5 @@ */ export interface ClientConfigType { - slmUi: { enabled: boolean }; + slm_ui: { enabled: boolean }; } diff --git a/x-pack/plugins/snapshot_restore/server/config.ts b/x-pack/plugins/snapshot_restore/server/config.ts index db8c0735ae2d55..0ed3392b553347 100644 --- a/x-pack/plugins/snapshot_restore/server/config.ts +++ b/x-pack/plugins/snapshot_restore/server/config.ts @@ -8,7 +8,7 @@ import { schema, TypeOf } from '@kbn/config-schema'; export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), - slmUi: schema.object({ + slm_ui: schema.object({ enabled: schema.boolean({ defaultValue: true }), }), }); diff --git a/x-pack/plugins/snapshot_restore/server/index.ts b/x-pack/plugins/snapshot_restore/server/index.ts index cc77aa13163a5f..1bbf482b4d4965 100644 --- a/x-pack/plugins/snapshot_restore/server/index.ts +++ b/x-pack/plugins/snapshot_restore/server/index.ts @@ -12,6 +12,6 @@ export const plugin = (ctx: PluginInitializerContext) => new SnapshotRestoreServ export const config: PluginConfigDescriptor = { schema: configSchema, exposeToBrowser: { - slmUi: true, + slm_ui: true, }, }; diff --git a/x-pack/plugins/snapshot_restore/server/plugin.ts b/x-pack/plugins/snapshot_restore/server/plugin.ts index a6daa12767c7cf..00ff3db976d661 100644 --- a/x-pack/plugins/snapshot_restore/server/plugin.ts +++ b/x-pack/plugins/snapshot_restore/server/plugin.ts @@ -86,7 +86,7 @@ export class SnapshotRestoreServerPlugin implements Plugin config: { isSecurityEnabled: security !== undefined, isCloudEnabled: cloud !== undefined && cloud.isCloudEnabled, - isSlmEnabled: pluginConfig.slmUi.enabled, + isSlmEnabled: pluginConfig.slm_ui.enabled, }, lib: { isEsError, diff --git a/x-pack/test/api_integration/apis/ml/bucket_span_estimator.ts b/x-pack/test/api_integration/apis/ml/bucket_span_estimator.ts index 1c7245234b089f..a50d65a48c2bb3 100644 --- a/x-pack/test/api_integration/apis/ml/bucket_span_estimator.ts +++ b/x-pack/test/api_integration/apis/ml/bucket_span_estimator.ts @@ -16,6 +16,7 @@ const COMMON_HEADERS = { // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); + const esSupertest = getService('esSupertest'); const supertest = getService('supertestWithoutAuth'); const mlSecurity = getService('mlSecurity'); @@ -97,8 +98,39 @@ export default ({ getService }: FtrProviderContext) => { await esArchiver.unload('ml/ecommerce'); }); - for (const testData of testDataList) { - it(`estimates the bucket span ${testData.testTitleSuffix}`, async () => { + describe('with default settings', function() { + for (const testData of testDataList) { + it(`estimates the bucket span ${testData.testTitleSuffix}`, async () => { + const { body } = await supertest + .post('/api/ml/validate/estimate_bucket_span') + .auth(testData.user, mlSecurity.getPasswordForUser(testData.user)) + .set(COMMON_HEADERS) + .send(testData.requestBody) + .expect(testData.expected.responseCode); + + expect(body).to.eql(testData.expected.responseBody); + }); + } + }); + + describe('with transient search.max_buckets setting', function() { + before(async () => { + await esSupertest + .put('/_cluster/settings') + .send({ transient: { 'search.max_buckets': 9000 } }) + .expect(200); + }); + + after(async () => { + await esSupertest + .put('/_cluster/settings') + .send({ transient: { 'search.max_buckets': null } }) + .expect(200); + }); + + const testData = testDataList[0]; + + it(`estimates the bucket span`, async () => { const { body } = await supertest .post('/api/ml/validate/estimate_bucket_span') .auth(testData.user, mlSecurity.getPasswordForUser(testData.user)) @@ -108,6 +140,35 @@ export default ({ getService }: FtrProviderContext) => { expect(body).to.eql(testData.expected.responseBody); }); - } + }); + + describe('with persistent search.max_buckets setting', function() { + before(async () => { + await esSupertest + .put('/_cluster/settings') + .send({ persistent: { 'search.max_buckets': 9000 } }) + .expect(200); + }); + + after(async () => { + await esSupertest + .put('/_cluster/settings') + .send({ persistent: { 'search.max_buckets': null } }) + .expect(200); + }); + + const testData = testDataList[0]; + + it(`estimates the bucket span`, async () => { + const { body } = await supertest + .post('/api/ml/validate/estimate_bucket_span') + .auth(testData.user, mlSecurity.getPasswordForUser(testData.user)) + .set(COMMON_HEADERS) + .send(testData.requestBody) + .expect(testData.expected.responseCode); + + expect(body).to.eql(testData.expected.responseBody); + }); + }); }); };